Glance完成一次镜像添加操作的整个流程

简介

首先简单介绍一下Glance项目。Glance项目主要是提供虚拟机镜像的发现、注册和检索服务。它通过提供标准的REST接口,接受对不同后端存储的镜像的查询请求和返回镜像的相关信息。

Glance镜像服务允许上传私有或共有的不同格式的镜像,包括:

  • Raw
  • Machine (kernel/ramdisk outside of image, a.k.a. AMI)
  • VHD (Hyper-V)
  • VDI (VirtualBox)
  • qcow2 (Qemu/KVM)
  • VMDK (VMWare)
  • OVF (VMWare, others)

与其他OpenStack项目相同,Glance也遵循以下几点设计原则:

1.     基于组件

2.     高可用性

3.     高容错性

4.     可扩展性

5.     开放标准

架构

在对Glance项目有了一定的认识之后,我们还应该了解一下它在OpenStack中所处的位置,请看下图

 

Glance在OpenStack中所处位置                

可以看出通过GlanceOpentack3大组件被连接为一个整体。Glacne的存储接口有多种实现,Swift作为其中之一可以为Glance提供实际的存储服务。而在另一方面Glance又为Nova提供镜像的查找操作。同时,这三个组件都需要通过Keystone的认证。

其中Glance的架构如下图所示:      

 

Glance 架构


主要组件

Glance-API 主要用来响应各种REST请求然后通过其他模块(主要是glance-registry组件和后端存储接口)完成镜像的上传、删除、查询等操作。可以简单的再分为两部分:一层中间件,它主要是做一些对请求的解析工作(如分析出版本号), 另外一部分提供实际的服务(如与镜像上传下载的后端存储接口交互)。默认绑定端口是9292

Glance-Registry 镜像注册服务,用于提供镜像元数据的REST接口。主要工作是存储或者获取镜像的元数据,与MySQL数据库进行交互。也可以简单的再细分为两部分,API和具体的Server。元数据是指镜像相关的一些信息(如idsize, status,location, checksum, min_disk, min_ram, owner等),真正的镜像数据保存在实际所使用的后端存储里(如swifts3filesystem等)。默认绑定的端口是9191

Image Store 严格来说image store不属于Glance的组件,这里把它单独分出来只是为了方便理解,它只是一个接口层,提供镜像存储和查询的接口。具体的实现则需要外部存储(SwiftS3)的支持

 Glance添加一个镜像的整个流程

其实,理解了这个流程也就大概掌握glance服务的原理了。

我们使用如下命令:

glance add name="cirros-0.3.0-i386-11-28" is_public=true container_format=ovf disk_format=qcow2 < ./cirros-0.3.0-i386-disk.img

返回结果:

Added new  image with ID: 81cbb863-a38e-48d6-9ff3-4c52800ef10d

在使用这条命令的时候,我们实际上是通过命令行向glance-api发送请求,完成我们对镜像的添加操作。glance命令行与nova命令行类似,都是封装了一层http的客户端。客户端从我们输入的命令中获取所需的参数后,将镜像的元数据包装在HTTP包头中,将镜像读入到请求的body中,然后通过POST请求将数据提交给glance-api

glance-api的作用已经在上面介绍过,但是要想知道他是如何响应RESTAPI的还需要理解一个文件:glance/etc/glance-api-paste.ini。这个文件有点类似nova-apiini文件。首先要熟悉ini配置文件中的几个概念以及他们之间的关系:

app:实际处理REST API请求的python类。

filter:一种装饰器,为app提供一层封装,在app处理请求之前会先调用filter的对象。

pipeline:所对应的对象是对filterapp的的封装,他将多个filter和某个app绑在一起,在app处理请求之前要先通过pipline指定的在app之前的filter的处理。

router:根据REST请求的URL让不同的对象的不同的方法处理该REST请求。

现在来看glance-api-paste.ini文件,glance/etc/glance-api-paste.ini定义了很多不同的pipeline,他们的区别在于定义了不同的filter来处理请求,而最终请求被glance.api.v1.router:API的对象处理。然后我们看一下router.py文件的API类。它继承了wsgi.Router,可以根据REST请求的URL以及请求的类型(GETPUT等)将请求映射给不同对象的不同方法进行处理。

glance/api/v1/router.py映射请求的部分代码如下:

images_resource = images.create_resource()

mapper.resource("image", "images", controller=images_resource,
                collection={'detail': 'GET'})
mapper.connect("/", controller=images_resource, action="index")
mapper.connect("/images/{id}", controller=images_resource,
               action="meta", conditions=dict(method=["HEAD"]))

members_resource = members.create_resource()
mapper.resource("member", "members", controller=members_resource,
                parent_resource=dict(member_name='image',
                collection_name='images'))
mapper.connect("/shared-images/{id}",
               controller=members_resource,
               action="index_shared_images")
mapper.connect("/images/{image_id}/members",
               controller=members_resource,
               action="update_all",
               conditions=dict(method=["PUT"]))

通过查看完整的代码(v1和v2),我们可以知道,请求最终都是被images.pyimage_data.pyschemas.pyimage_access.py以及image_tags.py中的controller类的不同方法处理。 所以上面添加镜像的请求会被glance/api/v1/images.py中的Controller类的create函数处理,该方法会调用_handle_source方法,进而调用_upload_and_activate方法。_upload_and_activate方法做了两件重要的事情:调用self._upload上传镜像,调用self._activate通过glance registry服务更新glance数据库中镜像的状态。具体存储接口实例的选择是在self._upload方法中。之后会调用确定的存储接口中的add方法保存需要上传的镜像。

整个流程看起来如下图所示:

 

Glance处理添加镜像请求的流程

1.  管理员使用上传镜像命令。Glance-API服务收到请求,并通过它的中间件,解析出版本号等信息。

2,3.  Glance-Registry服务的api获取一个registry client,调用registry clientadd_image函数。此时镜像的状态为queued, 标识该镜像ID已经被保留,但是镜像还未上传。

4.  Glance-Registry服务执行clientadd_image函数,向glance数据库中insert一条记录。

56,7.   Glance-API调用Glance-Registryupdate_image_metadata函数,更新数据库中该镜像的状态为saving,标识镜像正在被上传。

8.  Glance-API调用后端存储接口提供的add函数上传镜像文件。

9,10,11.  Glance-API调用Glance-Registryupdate_image_metadata函数,更新数据库中该镜像的状态为 active并发通知。active标识镜像在Glance中完全可用。

在镜像上传完成后,查看Registry的日志,可以验证Glance-Registry服务的主要任务的确是通过 sqlalchemy与MySQL数据库进行交互:

2012-11-28 09:24:22 INFO sqlalchemy.engine.base.Engine [-] BEGIN (implicit)

BEGIN (implicit)

2012-11-28 09:24:22 INFO sqlalchemy.engine.base.Engine [-] INSERT INTO images (created_at, updated_at, deleted_at, deleted, id, name, disk_forma

t, container_format, size, status, is_public, location, checksum, min_disk, min_ram, owner, protected) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %

s, %s, %s, %s, %s, %s, %s, %s, %s)

INSERT INTO images (created_at, updated_at, deleted_at, deleted, id, name, disk_format, container_format, size, status, is_public, location, che

cksum, min_disk, min_ram, owner, protected) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)

 

使用Glance管理镜像

文章的最后介绍一些Glance的简单使用,主要是一些glance客户端命令。

因为Glance服务要经过Keystone认证,所以先设置一些环境变量:

export OS_USERNAME=user
export OS_PASSWORD=password
export OS_TENANT_ID=tenant
export OS_AUTH_URL=http://127.0.0.1:35357/v2.0

完成设置,通过glance index -d -v 查看是否成功。成功后即可通过以下命令来使用Glance:

显示当前存在镜像:

glance index 或者 glance image-list

删除某个镜像:

glance delete ID

显示某个镜像详细信息:

glance show ID

更改已存在镜像的属性:

glance ID  属性=新属性值

例如,改变镜像的protected属性:

glance update ID protected = false

开放私有镜像给某个指定租户使用:

glance member-add ID tenant1

上传镜像的命令已在上面的流程分析中写出。当然我们也可以在这些基本命令的基础上额外添加一些其他参数,如:

-d,打印出调试信息

-v:显示出详细信息

注:以上所有“ID”均为镜像的ID,可以通过glance image-list得到.

更多更详细的Glance客户端命令

请请参:http://docs.openstack.org/developer/glance/glance.html#the-update-command

你可能感兴趣的:(OpenStack,Python)