Image Import Refactor¶
https://blueprints.launchpad.net/glance/+spec/image-import-refactor
注意
This is a very long spec, so we’ve added a FAQ to cover some common questions so that people can make better informed comments on the implementation patches.
In this spec we propose a refactoring of the current Glance image import process to meet the criteria of being discoverable, interoperable, and flexible. The goal is to present a uniform interface for image import that will satisfy the requirements of public and private clouds of various sizes.
注意
This spec is based on ideas expressed in mailing list discussions (see [OSM1], [OSM2]), a meeting in #openstack-glance (see [OSL1], [OSE2]), a video meeting of interested people (summarized in [OSW3]), and a session at the Mitaka design summit [OSE3]. It does not, however, reproduce all the discussion that took place, so the interested reader may wish to glance through those documents to gain wider context.
As a basis for the discussion to follow, image import is described by the following use case
A cloud end-user has a bunch of bits that they want to give to Glance in the expectation that (in the absence of error conditions) Glance will produce an Image (record, file) tuple that can subsequently be used by other OpenStack services that consume Images.
Among the motivations for the above use case are
An end user creates a specialized custom image offline and wants to use it in various OpenStack clouds.
A particular cloud may not offer a public image of some Excellent But Obscure Operating System (EBOOS). The EBOOS User Group could make a VM image available on its website, and EBOOS enthusiasts could import it into the OpenStack cloud of their choice.
An end user finds an interesting image in the OpenStack App Catalog and wants to boot instances from it in an OpenStack cloud.
An end user creates a snapshot of an instance in one OpenStack cloud and wants to boot instances from it in another OpenStack cloud. (Obviously, this would require image export as well.)
注意
Image Creation in OpenStack Clouds
It’s worth distinguishing three distinct use cases around image creation
A deployer wishes to create public images that end users may use to boot instances.
Another OpenStack service creates an image from some other resource it manages (for example, Nova creates an image of a server, or Cinder creates an image from a volume) at the behest of an end user.
An end user wishes to import an image.
Glance should support all three scenarios.
背景¶
Glance contains a “tasks” API that is a result of discussions during and after the Havana design summit (see [OSD1], [OSW2], and [OSW1]). This API was designed to present a uniform interface to end-users that allowed a large degree of customization by individual cloud providers, and currently defines an ‘import’ task. Since the Havana design summit, however, the DefCore movement in OpenStack has developed as a means of ensuring interoperability among OpenStack branded clouds. The current Glance tasks API is too customizable to be suitable for DefCore purposes, and in fact, does not fare well when assessed on the dimensions of interoperability and discoverability.
The primary problem with tasks as defined in the current API is that they have an “input” element, defined in the task schema as a JSON blob, whose exact content is left up to the cloud deployer. This allows for flexibility on the part of a cloud deployer, but introduces a discoverability problem, as the only mechanism currently available for determining acceptable content of the “input” element is the deployer’s documentation. While some flexibility is good, this much flexibility makes it impossible for a competent end-user of one OpenStack cloud to be sure this competence extends to a different OpenStack cloud.
One goal of this spec is to implement image import in such a way that it will be a suitable candidate for inclusion in DefCore. (See [OSR1] for the list of 12 criteria for being included in DefCore Guidelines.)
注意
Currently, Glance is included in two DefCore programs: “OpenStack Powered Compute” and “OpenStack Powered Platform”. (See [OSO1] for a definition of these terms.)
Current Upload Workflow¶
Here’s a quick reminder of the current image upload workflow.
POST v2/imagesThis creates an image record and returns an Image response containing (among other things) an ‘id’ field. (The image record can be modified by PATCH calls, but we’ll ignore that here.) The key thing is that a record must be created so that the user has an image_id to work with for the purposes of uploading the actual image bits.
PUT v2/images/{image_id}/fileThis call instructs Glance to accept the incoming image data and place it into the storage backend. The associated image record must have the
container_formatanddisk_formatproperties set or the call will not succeed. This call returns no content.
This current image upload workflow will still exist for backward compatibility and for use by Glance administrators and trusted OpenStack services.
问题描述¶
For reasons set out in [OSW3] and [OSE1], it is desirable for deployers to have the ability easily to separate untrusted end-user image import from the simple upload facility used by trusted sources (typically, Nova or another OpenStack service, or Glance administrators supplying public images for use in a cloud). What we aim to do in this spec is to define a suitable end-user image import mechanism that will satisfy the requirements of all OpenStack clouds, whether small or large, public or private.
Summary of the Constraints Around This Project¶
Here are, to the best of my recollection, what was agreed upon between the Glance community, DefCore (mostly Doug Hellman), infra (mostly Monty), and various interested parties who showed up at the design session on image import at the Tokyo summit.
First, background, so you can see what problems needed to be addressed
(At least some) Public cloud operators do not want to expose the current glance v1/v2 image upload as it is too fragile.
The TC passed a resolution in December 2015 [NEW1] saying that end user image upload (what we – following industry parlance – are calling “image import”) must be available in OpenStack clouds.
The TC resolution says that an OpenStack cloud should support import of a vanilla linux image; no mandate about image format, size, etc.
Part of the goal of this spec is design a discoverable and interoperable API for image import so that the TC resolution can be satisfied and image import can be included as a DefCore requirement. (See [NEW2] for more about this point.)
The “Tasks” API is a disaster from the interoperability and discoverability standpoint. (We know this because at least one large public cloud has exposed image import via Glance Tasks, and the OpenStack infra team has a lot to say about how bad it is. Just ask them.)
interoperability failures: The Task object, as defined by
v2/schemas/taskcontains an “input” and “result” element which are defined to be JSON blobs; anything could go in there, so possibly radically different stuff for each OpenStack clouddiscoverability failures: You don’t have to support a particular disk/container format, but there must be a way to find out what a particular cloud supports (and this “way” should be the same for all OpenStack clouds, and no, documentation doesn’t count)
There are three cases for “image upload” that Glance should support.
Admin upload of “base” or “public” images
Image upload from OpenStack services (for example, Nova or Cinder)
End user image import
注意
My view is that we are working on the image import use case, and what we come up with there could, but doesn’t have to, be used/usable for the other two use cases. The key point to keep in mind here is that the discovery of various vulnerabilities may cause operators to halt import (temporarily), and they will want to do that while still keeping the other 2 use cases operational.
As Doug pointed out on a previous patch: “It would be nice to have only one API, but the hole we have right now is the public-facing use case and so that’s where the focus of this work should be. If we can make the results work for the other cases, that’s a bonus, but not required.”
OK, without further ado, here’s what was agreed upon
The constraints that an adequate image import solution must meet¶
There must be a well-defined image import structure/framework that should be supportable by all OpenStack clouds.
“well-defined”
calls have request/response schemas that are discoverable
the values that will enable a client to have a successful image import (e.g., supported formats) must be discoverable
“discoverable” == via API call (in what Flavio calls a “follow-your-nose” fashion)
specific API request: this would be the
GET v2/info/importcallavailable in headers: the headers would be returned with the
POST v2/imagesresponse. The idea is that the content of that response is the JSON representation of the Image record (so the import methods available and other associated import information don’t really belong in a particularimageresource), and having the info come back in the headers could allow a client to determine the import method to use without having to make the discovery call.
“supportable by all OpenStack clouds”
it’s acceptable for there to be multiple import methods as long as each is well defined. (See the “Proposed Change” section below for details. An “import method” has to do with how the image data is delivered to Glance. The API calls won’t change, and their body and structure will remain the same for the various methods.)
no cloud has to support all import methods, but it’s expected that to achieve certification as “OpenStack Powered Compute” (and hence, to even have a shot at certification as an “OpenStack Powered Platform”), a cloud must expose at least one of these.
Since Swift is not part of the “OpenStack Powered Compute” program, Glance must expose at least one import method that does not rely upon the presence of an end-user-accessible object store.
The “three step dance” import style was deemed acceptable
one: create image record, two: upload data, three: import call
steps one and two can be independent. For example, in the ‘swift-local’ method sketched out below, an end user could upload the image data to swift first (accomplishing step two), then do step one, followed by step three.
The import workflow should allow for server-side operator customization, but no operator is required to perform such customization.
We’re talking about customization in processing the uploaded data. The API request/response structure is not customizable.
提议的变更¶
Import Workflow¶
The import workflow will respect the basic structure of the current upload workflow described above.
End user creates an image record. (We’ll refer to this as image-create, just keep in mind that what’s created is only the image record.)
End user makes the data available to Glance. (This could be via direct upload, or via some other well-defined import method that is discoverable by an end user.)
End user instructs Glance to process the data and create a bootable image.
图像上传和图像导入的一个关键区别在于,导入的图像并非立即可用,也就是说,在数据 PUT 调用完成后,它们不是“活动”状态。这允许部署者在图像变为“活动”状态之前,可选地处理图像数据(例如,执行验证过程)。此外,部署者可能需要在此时将受保护的属性放置在图像记录上。因此,导入调用需要是异步的。
发现¶
最终用户需要能够执行以下操作
值发现
最终用户需要确定此云接受哪些容器格式和磁盘格式,允许的最大图像大小(实际大小和虚拟大小),以及可用的导入方法。
方法发现
最终用户想要知道此站点支持哪些导入方法。虽然此信息将在上述值发现调用中返回,但我们还建议在用于创建图像记录的调用的响应头中返回它。这样,客户端无需在图像导入工作流程中进行值发现调用。
格式发现
最终用户想要知道导入请求体是什么样的。此信息将由 JSON schema 提供。
我们假设用户已经知道如何发现图像 schema,以便创建图像和读取图像响应。
导入方法¶
我们定义了一种初始导入方法,glance-direct,但我们设想更多的方法,例如 swift-local。(我们将在讨论中包含 swift-local,以便清楚地了解本规范中描述的导入方案如何以可互操作的方式扩展,以包含将图像数据导入 Glance 的其他方法。)
注意
我们可能希望使用不同的术语,以减少向用户暴露内部细节。例如,我们可以只使用 direct 和 indirect,正如 Steve Lewis 在 PS8 中建议的那样。我们可以在开发过程中讨论名称并相应地修改此规范。
glance-direct最终用户使用包含在图像创建请求响应头中的 URL,将图像数据直接 PUT 到 Glance。(该 URL 也将通过约定已知,即
v2/images/{image_id}/stage。在上传数据后,最终用户会继续调用 Glance 以处理数据并完成导入。)swift-local最终用户将图像数据放置在用户对象存储帐户中。数据放置可能在创建图像记录之前或之后发生。在上传数据并创建图像记录后,最终用户会调用 Glance 以处理数据并完成导入。
特定的 Glance 安装不必支持所有方法,但预计它会公开至少一种方法。
注意
我试图避免让最终用户了解暂存区域(以前称为“bikeshed”)。但是,请参阅 Stuart 在 Patch Set 7 的第 207 行发起的关于关注点分离的讨论以及 Amazon 的 s3 “multipart upload” 的示例。
API 变更¶
值发现¶
GET v2/info/import
响应是 JSON 格式的对象。此文档应向最终用户提供足够的信息以执行图像导入。
1{
2 "max_upload_bytes": {
3 "description": "You may not upload more than this number of bytes when importing a virtual disk.",
4 "type": "integer",
5 "value": 10737418240
6 },
7 "max_virtual_bytes": {
8 "description": "You may not upload a virtual disk whose virtual size exceeds this number of bytes.",
9 "type": "integer",
10 "value": 26843545600
11 },
12 "max_upload_time": {
13 "description": "You only have this much time to complete your data upload. Expressed in seconds. (Does not apply to the 'swift-local' import method.)",
14 "type": "integer",
15 "value": 600
16 },
17 "data_TTL_after_import_error": {
18 "description": "If an error occurs when you issue the command to import this data, your uploaded data is subject to deletion after this amount of time. Expressed in hours. (Does not apply to the 'swift-local' import method.)",
19 "type": "integer",
20 "value": 6
21 },
22 "source_container_format": {
23 "description": "Your image data must be in one of these container formats.",
24 "type": "array",
25 "value": [ "bare" ]
26 },
27 "source_disk_format": {
28 "description": "Your image data must be in one of these disk formats.",
29 "type": "array",
30 "value": [ "vhd", "vmdk", "raw" ]
31 },
32 "target_container_format": {
33 "description": "Your image will be saved in Glance in one of these container formats.",
34 "type": "array",
35 "value": [ "ova" ]
36 },
37 "target_disk_format": {
38 "description": "Your image will be saved in Glance in one of these disk formats.",
39 "type": "array",
40 "value": [ "vhd" ]
41 },
42 "os_type" : {
43 "description": "Operating systems allowed for import. Some operating systems may be non-importable due to licensing constraints.",
44 "type": "array",
45 "value": [ "linux", "windows" ]
46 },
47 "import-methods": {
48 "description": "Import methods available at this site.",
49 "type": "array",
50 "value": [ "glance-direct", "swift-local" ]
51 },
52 "import-schema-location": {
53 "description": "Location of the JSON schema for the image import request/response.",
54 "type": "string",
55 "value": "v2/schemas/import"
56 }
57}
注意
我们是否允许用户发送 target_* 字段?
假设最终用户需要图像以不同的格式使用特定的 flavor 或可用区。我们可以通过引入转换任务(本规范范围之外)来处理此问题,其中最终用户指定现有图像并请求创建一个特定支持格式的新图像(其中“支持”格式取决于云)。这将允许解耦
云中实际使用的图像格式
支持导入的图像格式
支持转换的图像格式
拥有这种解耦会很好,因为
正在使用的格式取决于您拥有的超visor 类型以及它们喜欢的格式
导入格式取决于您对筛选过程的充分性充满信心的格式
转换格式取决于您对将正确转换充满信心的格式
摘要¶
方法类型:GET
正常的 http 响应代码:200 (OK)
- 预期的错误 http 响应代码:400、401、405
400:传递了请求体
401:未授权
405:仅支持此调用的 GET
- 资源的 URL:
v2/info/import 替代方案:
v2/info(我认为我们想要子资源,但是,当添加导出、图像转换和其他功能时,它将使响应更简单。)
- 资源的 URL:
可以通过 URL 传递的参数:无
主体数据的 JSON schema 定义:不允许
响应数据的 JSON schema 定义:无
格式发现¶
GET v2/schemas/import
响应是以下 JSON schema。
1{
2 "id": "https://openstack.org/glance/import/request/schema#",
3 "$schema": "https://schema.json.js.cn/draft-04/schema#",
4 "description": "OpenStack Glance image import request schema.",
5 "type": "object",
6 "additionalProperties": false,
7 "required": [
8 "method",
9 "source_disk_format",
10 "source_container_format",
11 ],
12 "properties": {
13 "method": {
14 "type": "object",
15 "oneOf": [
16 { "$ref": "#/definitions/glance-direct" },
17 { "$ref": "#/definitions/swift-local" }
18 ]
19 },
20 "source_disk_format": {
21 "enum": [ "vhd", "vmdk", "raw" ],
22 "description": "The disk format of the data to be imported."
23 },
24 "source_container_format": {
25 "enum": [ "bare", "ovf" ],
26 "description": "The container format of the data to be imported. If no container, use 'bare'."
27 },
28 "os_type": {
29 "enum": [ "linux", "windows" ],
30 "description": "The type of the operating system contained in the image."
31 }
32 },
33 "definitions": {
34 "glance-direct": {
35 "properties": {
36 "name": {
37 "enum": [ "glance-direct" ],
38 "description": "Identifier for this import-method."
39 }
40 },
41 "required": [
42 "name"
43 ],
44 "additionalProperties": false
45 },
46 "swift-local": {
47 "properties": {
48 "name": {
49 "enum": [ "swift-local" ],
50 "description": "Identifier for this import-method."
51 },
52 "swift-location": {
53 "type": "string",
54 "maxLength": 255,
55 "description": "Name of the Swift object to be imported in container/name format."
56 }
57 },
58 "required": [
59 "name",
60 "swift-location"
61 ],
62 "additionalProperties": false
63 }
64 }
65}
请注意,source_disk_format 和 source_container_format 的值将从用于提供值发现调用的配置选项中提取。这将允许最终用户对请求进行准确的 schema 验证。
注意
我尚未解决 Stuart 的问题“我们需要同时拥有‘全局’和磁盘格式特定的参数吗?” 该问题出现在 Patch Set 5 的 schema 中。根据答案,可用的 schema 可能比此处提出的 schema 更复杂。
注意
schema 需要允许一些特定于提供商的属性。一个示例是 os_type,它会影响 Xen hypervisor 创建客户文件系统的方式。云可能会保护此属性,因为否则将值从 linux 更改为 windows 将允许最终用户在云中运行未经许可的 Windows 服务器,从而导致违反许可条款、诉讼和普遍的不满。
我已在 schema 中包含 os_type,但可能还有其他此类属性,因此我已添加一个工作项,以联系 operators 组和 product working 组,以便在 Mitaka 版本之前获得(希望)明确的列表并相应地修改此规范和 schema。
摘要¶
方法类型:GET
正常的 http 响应代码:200 (OK)
- 预期的错误 http 响应代码:400、401、405
400:传递了请求体
401:未授权
405:仅支持此调用的 GET
资源的 URL:
v2/schemas/import可以通过 URL 传递的参数:无
主体数据的 JSON schema 定义:不允许
响应数据的 JSON schema 定义:响应是 JSON schema
image-create¶
此调用已经存在。我们建议添加额外的响应头以促进发现。(我们还在此处讨论它,因为该调用是图像导入工作流程不可或缺的一部分。)
POST v2/images
当前请求体和响应体保持不变。图像以 queued 状态创建(就像 v2 API 中的当前状态一样)。
请注意,disk_format 和 container_format 当前在此请求中是可选的,这对于图像导入来说效果很好,因为导入数据的格式在导入过程中可能会被修改(例如,OVA 可能会被解包,或者裸磁盘可能会被打包)。disk_format 和 container_format 将在 image-import 调用中是必需的,以及通用的图像属性 os_type。在 image-import 调用中指定的值将覆盖图像对象中的任何现有值。
新的响应头¶
OpenStack-image-import-methods
此标头的值将是逗号分隔的导入方法关键字列表。例如,
OpenStack-image-import-methods: glance-direct,swift-local
OpenStack-image-glance-direct-url
标头的值将是图像数据可以由后续调用 PUT 的 URL。仅当站点支持
glance-direct导入方法时,才会包含此标头。(如果glance-direct名称更改,此标头也将重命名。方法名称包含在此处,以便如果存在多个指定可以上传数据的 URL 的导入方法,客户端将有一种方法来区分它们。)
data-put¶
PUT v2/images/{image_id}/stage
此调用将遵循当前 PUT v2/images/{image_id}/file 调用的规范,并进行以下更改
仅当图像上的磁盘和容器格式字段已设置时,才接受对
/file的调用。这对于对/stage的调用将不再要求,因为用户将在后续的 image-import 调用中提供这些字段。当上传的字节数超过值发现调用中发布的 max_upload_bytes 值时,该调用将失败。
当上传时间超过值发现调用中发布的 max_upload_time 值时,该调用将失败。
图像的状态将设置为 uploading 而不是 saving。如果图像状态为 uploading,则不应接受对 /file 的调用。同样,如果图像状态为 saving,则不应接受对 /stage 的调用。因此,不可能在同一图像上使用两种上传方法。
用户通过发出 image-import 调用(见下文)来指示数据已暂存。因此,允许进行多次 data-put 调用。这可能允许同一租户中的两个用户发出竞争的 data-put 调用,但对于此实现,我们将认为租户有责任确保用户适当合作。
如果图像上的后续处理确定应拒绝图像,则将删除图像数据,并且图像将进入 killed 状态。
为了向最终用户传播信息,将在 Image 对象中添加一个新的 message 字段。有关 message 字段将包含的类型的内容的示例,请参阅 [OSE4]。
摘要¶
方法类型:PUT
- 正常的 http 响应代码:204 (No Content)
替代方案是 202,但不太正确,因为在用户发出后续导入调用之前,不会对图像数据发生任何事情。换句话说,我认为 202 意味着“您的图像正在发送中”,但这里不是这样。在之前的补丁集中,成功的 PUT 确实触发了导入处理,但现在不是这样了。
- 预期的错误 http 响应代码:401、405、409、415
401:未授权
405:仅支持此调用的 PUT
405:此站点不支持
glance-direct导入方法409:关联的图像不在适当的状态
415:不支持的媒体类型(必须是
application/octet-stream)
资源的 URL:
v2/images/{image_id}/stage可以通过 URL 传递的参数:无
主体数据的 JSON schema 定义:无
响应数据的 JSON schema 定义:响应中没有内容
实现问题¶
需要确定 stage(以前称为“bikeshed”)的确切性质。
image-detail¶
此调用已经存在,但我们仍然讨论它,因为它对于图像导入工作流程至关重要。
GET v2/images/{image_id}
这将返回格式化为在 v2/schemas/image 中提供的 JSON schema 的 Image 对象。
将向 Image 对象添加两个新的图像状态值
uploading需要的原因:此状态向用户传达已发出导入 data-put 调用。在此状态下,不允许对
PUT /file进行调用。(请注意,对 queued 图像的PUT /file调用会将图像置于saving状态。在图像处于saving状态时,不允许对PUT /stage进行调用。因此,不可能在同一图像上使用两种上传方法。)importing需要的原因:此状态向用户传达已发出导入调用,但图像尚未准备好使用。当图像处于此状态时,不接受 data-put 调用。
将向 Image 对象添加一个新的属性
message需要的原因:如果在导入过程中发生错误,图像将进入
killed状态,但这并不能告诉用户发生了什么或提供有关应采取适当措施的任何线索。此外,
message元素可用于 Glance 和最终用户之间的非错误通信。请参阅 [OSE4] 以获取此类用法的示例。
image-import¶
POST v2/images/{image_id}/import
请求体必须符合从格式发现调用中检索到的 JSON 模式,否则调用将失败。没有响应体。
{image_id} 的状态必须为 uploading 或 queued,否则调用将以 409(冲突)失败。(我们需要允许从 queued 导入非上传导入方法,例如 swift-local 或某种类型的复制功能。)如果 Image {image_id} 不存在或不属于调用者,将返回 404。
summary¶
方法类型:POST
正常的 http 响应代码:202 (Accepted)
- 预期的错误 http 响应代码:400, 401, 404, 405, 409, 415
400:请求格式错误
401:未授权
404:镜像记录不存在或不属于调用者
405:仅支持 POST 方法
409:关联的图像不在适当的状态
415:不支持的媒体类型(必须是
application/json)
资源的 URL:
v2/images/{image_id}/import可以通过 URL 传递的参数:无
主体数据的 JSON 模式定义:
v2/schemas/import响应数据的 JSON 模式定义:无响应
示例(glance-direct 方法)¶
1{
2 "method": {
3 "name": "glance-direct"
4 },
5 "source_disk_format": "raw",
6 "source_container_format": "bare",
7 "os_type": "linux"
8}
示例(swift-local 方法)¶
1{
2 "method": {
3 "name": "swift-local",
4 "swift-location": "import-data/my_image.raw"
5 },
6 "source_disk_format": "raw",
7 "source_container_format": "bare",
8 "os_type": "linux"
9}
备选方案¶
在这里,我们考虑一些“原生”(非 Swift)上传的替代方案。
使用现有的原生 v2 上传¶
我们可以使用现有的同步 v2 上传调用,即
PUT v2/images/{image_id}/file
优点
对现有 API 用户没有影响。
缺点
排除了长期验证/处理。
将现有的原生 v2 上传改为异步¶
(这将包括添加一些简单的可发现性调用。)
优点
与现有行为的微小变化。可能不会影响所有用例。
缺点
更改了现有的 API 行为。不被认为是向后兼容的。
用户/库必须更改为期望非同步行为。
异步上传调用¶
这将是对现有 v2 上传调用的微调,使其成为异步的——但以向后兼容的方式。可以通过使用不同的资源路径、添加标头或使用查询参数来实现向后兼容性。(这将包括添加一些简单的可发现性调用。)
优点
与现有的上传机制非常相似。
仍然只有两个 API 调用(
POST,PUT)不需要新的镜像状态。
缺点
最初上传的数据不会被缓存以供重试。(与现有上传相同。)
预计用户/库将切换到新方法。
与“非原生”导入(即从外部来源导入)的工作流程略有不同
独立 fileIds¶
在这里,上传的字节最初不属于特定的镜像。这将与从 Swift 导入的情况相同,即 fileId 操作与镜像操作以类似于 Swift 对象操作与镜像操作分离的方式分开。
首先使用 POST 上传字节。这将存储字节并生成唯一的 fileId。此时,字节“不属于”任何镜像。然后,进行调用以使镜像消耗该 fileId(类似于消耗 Swift 对象)。然后(可选)删除原始 fileId。
这可以以略微不同的方式实现。
fileId 可以完全不与任何镜像关联,在这种情况下,它可以作为多个镜像的源数据重用。
或者,fileId 可以通过要求指定镜像 uuid 在创建 fileId 时来限制为特定的镜像。在两种情况下,fileId 仅在镜像消耗 fileId 并经历通常的
queued、saving、active阶段时才会影响镜像状态。
优点
Swift 和 Glance 的工作方式相同。(初始数据不被认为是镜像的一部分。)
可以扩展为顺序或并行上传多个 fileIds。
如果导入失败,fileIds 会被缓存以供重试
每个 fileId 都可以有自己的大小和校验和(用于配额/完整性)
关注点分离(对现有代码区域的影响较小,例如镜像删除不必处理多个数据块。)
不需要新的镜像状态。
缺点
更多代码,例如列出 fileIds
比简单的异步上传案例更多的 API 调用
预计用户/库将切换到新方法。
异步上传调用和独立 fileIds¶
这两个选项可以结合起来。“异步上传”为常见的简单上传案例提供了一个“简单”的调用,“独立 fileIds”为并行/分段上传提供了一组更复杂的方法。(在其他地方有基本案例和高级调用的示例,例如常规 Swift 上传与 Swift 大对象上传。)
优点
为标准上传提供简单的 API
为需要它们的人提供更高级的 API
可以先实现简单的案例
缺点
更多代码
预计用户/库将切换到新方法。
URL 提名¶
Glance 可以提名一个不透明的 URL 用于 PUT 数据。例如,POST 请求可以返回
put-data-to: https://example.com/xxx
如果 Swift 可用,URL 将是 Swift TempURL,如果 Swift 不可用,URL 将指向适当的 Glance URL。据我所知,Swift 的 TempURL 允许范围偏移,因此并行上传/部分重试应该可以工作。
优点
漂亮且 RESTful
无论是否使用 Swift,行为几乎相同
缺点
Swift TempURLs 限制上传大小(默认 5GB)。(需要对 Swift 进行更改。)
用户可能在 Swift 中拥有预先存在的镜像数据。无论如何都需要处理这种情况。
在 Swift TempURL 的情况下,不需要将 token 标头与数据一起发送。在 Glance 的情况下,需要 token 标头(除非我们向 Glance 添加 TempURL 类型的功能)。因此,这两件事并不完全等效。您必须知道您是发送到 Glance 还是 Swift——或者至少知道是否发送 token。您可以潜在地同时发送 token,但这有点不整洁(例如,最小权限原则)。
需要一个用于 Swift 导入的特殊帐户(这将是上传目标),即使在多租户存储模式下也是如此,因为提名用户自己帐户中的 URL 可能不安全。
虽然(我认为)使用 Swift 的 TempURL 可以进行并行上传/部分重试,但只有在已知目标是 Swift 时才能尝试,即如果 URL 不透明。因此,我们将回到需要知道我们正在将数据发送到哪个服务。(除非我们放弃 Swift 的一些优势。)
使用现有的任务 API¶
当 Swift 存在时,这有效,但不能提供异步“原生”上传的方式。
超出范围¶
随着此规范的讨论进展,我们已经同意它不包含以下功能。同时,我们应该牢记,在以后某个时候,我们可能希望包含这些功能。因此,我们为镜像导入设计的任何内容都应该使其易于适应它们。
超出范围:导入过程中的镜像转换
超出范围:所有站点必须支持的通用磁盘/容器格式的规范
超出范围:特定云中使用的磁盘/容器格式与镜像导入支持的磁盘/容器格式的等效性。(换句话说,没有要求站点必须允许导入站点上使用的所有格式。有关更多信息,请参阅上面的 value-discovery 部分中的“注意”。)
超出范围:镜像导出(尽管显然我们希望找到一个同样适用于导出和导入的解决方案)
数据模型影响¶
将添加两个新的镜像状态值:importing 和 uploading。
将添加一个新的镜像属性:message。
REST API 影响¶
鉴于正在向 API 添加至少一个新调用,应该进行次要版本更新。
不是此规范的范围,但普遍共识是,本周期应将当前的“任务”API 弃用,并使其成为仅管理员 API。
安全影响¶
由于其目的是消耗用户提供的数据,此功能将引入新的安全风险。从历史上看,Images v1 API 不打算直接暴露给最终用户,而是预计最终用户将使用 Compute API 进行镜像相关调用。Compute API 定义了一个“image-create”操作,但这是服务器资源上的操作,也就是说,它创建现有实例的快照,而不是上传用户提供的镜像。此外,在哈瓦那峰会上(参见 [OSE1])的讨论表明,Images v2 上传也不应暴露给最终用户,而应保留给受信任的用户。因此,即使先前可以将镜像上传直接暴露给最终用户,但这也不是推荐的做法。
镜像导入必须设计成,以便部署者可以在紧急情况下停止镜像导入。
我们预计以下安全风险
它消耗用户提供的数据。根据允许的 container_format 和 disk_format,这可能会使 Glance(以及从 Glance 消费镜像的其他项目)暴露于解压缩炸弹或各种基于 tar 的攻击中。(镜像的消费者可能已经有缓解策略,但 Glance 本身目前没有。)
它会启用资源耗尽攻击。向量包括:上传任意数量的字节(可以通过最大大小限制来缓解),通过极其缓慢的连接上传允许数量的字节(可以通过 Glance 侧超时来缓解),并发导入(可以通过用户配额、用户限制、任务队列或某种组合来缓解)。
(本节中其余的问题将在讨论进展时解决。)
此更改是否涉及敏感数据,例如令牌、密钥或用户数据?
此更改是否以可能影响安全性的方式更改了 API,例如访问敏感信息的新方式或登录的新方式?
此更改是否涉及密码学或哈希?
此更改是否需要使用 sudo 或任何特权?
此更改是否涉及使用或解析用户提供的数据?这可能是直接在 API 级别,或间接例如更改缓存层。
此更改是否会启用资源耗尽攻击,例如允许单个 API 交互消耗大量的服务器资源?这方面的一些例子包括为每个连接启动子进程,或 XML 中的实体扩展攻击。
通知影响¶
镜像导入过程应发出通知。(将在基本设计完成后进一步说明。)
我们应该为导入工作流程的以下部分实现通知
已接受导入操作
已开始处理
定期处理状态(百分比)
处理完成(成功/失败)
策略影响¶
如本文所述的镜像导入是最终用户操作,而不是管理员操作。但是,必须通过 Glance 策略对其进行适当管理。虽然默认策略设置将允许最终用户导入镜像,但资源有限的小型公共部署者可能希望将镜像导入限制为特定用户。
此外,如上所述,部署者应该能够“关闭”镜像导入,如果发现漏洞。
其他最终用户影响¶
我们需要清楚地说明传统的 Glance 镜像不可变性保证如何应用于镜像导入,即,镜像一旦变为活动状态就不可变。
python-glanceclient 将被修改以支持镜像导入。(将在基本设计完成后描述接口。)
性能影响¶
描述系统中的任何潜在性能影响。(将在基本设计完成后填写。)
其他部署者影响¶
此更改可能会影响人们部署和配置 OpenStack 的方式
Nova 依赖 Glance 提供镜像并接受 VM 快照。这些操作不受此提案的影响。
处理镜像导入可能需要专用资源,例如
如果镜像验证是 CPU 密集型的,则需要专用节点
开发人员影响¶
预计此功能不会影响正在 OpenStack 上工作的其他开发人员。
实现¶
负责人¶
- 主要负责人
brian-rosmaita
- 其他贡献者
mclaren
评审人员¶
- 核心评审人
所有当前的 glance 核心。
工作项¶
策略规则和新的配置选项:https://bugs.launchpad.net/glance/+bug/1523937
这些取决于策略更改。
处理 API 模式更改(可发现性):https://bugs.launchpad.net/glance/+bug/1523944
使任务 api 仅管理员:https://bugs.launchpad.net/glance/+bug/1527716
记录 /file 不推荐用于公共节点。
引入策略,以便可以轻松地禁用
/file端点以供遵循上述建议的运营商使用。这些策略的默认设置将不会更改当前行为。联系运营商和产品工作组,了解应包含在导入请求模式中的类似于
os_type的属性。(内部)任务配置
python-glanceclient 支持
tempest 测试
文档
依赖项¶
预计此功能不需要当前 Glance 任务已经使用的依赖项。
测试¶
应该能够添加一个 tempest 测试来导入一个小镜像。
文档影响¶
以下内容将添加到 glance 开发人员文档中。
任何新的 API 调用
对任何现有 API 调用的更改
glance 开发人员希望使用任务的任务信息
任务信息供部署者使用(我建议首先在开发文档中开始,然后将其移动到 OpenStack 运营商手册之一)
常见问题解答¶
你一直想知道关于 Glance 镜像导入的一切,但又害怕去问。
要解决什么用例?
A cloud end-user has a bunch of bits that they want to give to Glance in the expectation that (in the absence of error conditions) Glance will produce an Image (record, file) tuple that can subsequently be used by other OpenStack services that consume Images.
为什么“常规”上传不足够?
与使用 Compute API 获取实例的“快照”不同,在 Nova 处理镜像创建、打包、基本编目和上传到 Glance 的情况下,暴露镜像上传会使云暴露于人为错误(例如,不是虚拟机镜像、不适用于该云中超visor的镜像类型、恶意打包/结构的镜像以攻击超visor)中,从而使云暴露于额外的支持负载、拒绝服务或安全问题中。
此外,不仅仅是安全问题。另一个常见用例是用户上传 OVA,可以自动解包并检查清单以设置镜像的适当元数据。或者,如果 OpenStack 同意通用的镜像交换格式,则可能需要转换导入的镜像。
如何解决上述问题?
与直接将镜像数据放入存储后端“常规”上传不同,镜像导入过程允许操作员检查假定的镜像并执行验证/转换/打包(或不执行任何操作),然后将其存储在后端。
这是否会引入不必要的导入过程变量?
不会。API 是固定的,因此 API 请求和响应格式在所有 OpenStack 云中都是相同的。变量存在于幕后,在用户将数据提供给 Glance 但镜像状态变为“active”之前。
请注意,虽然有多种导入方法,但每种方法都经过精确定义和模式化,因此 API 调用/响应是标准的。
为什么有多种方法?
这是一种不适合一刀切的情况。有几个问题会影响最终用户和操作员的用户体验,例如要导入的镜像大小、可用连接的速度、部署额外上传节点的能力、是否存在对象存储、最终用户执行镜像导入的数量、云操作团队的大小等。某些使用模式可以通过我们称之为“glance-direct”的方法来适应,即最终用户直接将对象流式传输到 Glance;其他模式可能更适合从对象存储导入,即最终用户可以使用适当的工具来确保在上传大型二进制对象时获得良好的用户体验。由于 OpenStack 提供了对象存储解决方案的免费软件,并且 Swift 部署在所有 OpenStack 云的大约一半中,我们建议实施一种“swift-local”导入方法,将镜像数据带外上传到 Swift。
此外,为了预见 Images v1 API 的弃用,一些操作员指出旧 API 中的“copy-from”功能缺失于 Images v2 API。虽然这不是这项工作的主要驱动力,但定义良好的 copy-from 导入方法可以通过此设计来适应。
简而言之,多种导入方法使我们能够在云之间拥有一致且可发现的 API,从而使操作员和最终用户能够提供/使用最适合他们的导入方法。
如果我不喜欢有多种导入方法怎么办?
相信我,我们已经仔细考虑过这个问题。另一种选择是为每种不同的导入方法提供不同的 API 调用。然而,这将损害实现所有 OpenStack 品牌云中支持的稳定 API 调用的目标,因为并非每个云操作员都希望暴露所有导入方法。这将使镜像导入难以包含在 DefCore 中。
让我们非常小心地描述我们在这里谈论的内容。镜像导入的批准设计允许操作员选择,但方式非常受限。对于最终用户而言,每种导入方法在每个 OpenStack 云中都将以相同的方式运行,并且我们设想这些方法数量不多,因为每种方法都必须通过规范流程并内置实现。因此,可以编写一个客户端来无缝处理最终用户视角的镜像导入。
如果存在多种方法,云是否必须支持所有方法才能通过 DefCore 实现“OpenStack”品牌?
这最终取决于 DefCore 项目。我们的想法是,由于所有 OpenStack 云都将支持至少一种导入方法,因此所有 OpenStack 云都将拥有一个可用的 Images v2 API 镜像导入设施,并且可以通过镜像导入要求。
如果存在多种方法,我如何确定特定云中可用的方法?
可以通过编程方式完成。 (a) GET v2/info/import 返回一个定义良好的文档,其中包含特定站点支持的导入方法列表。 (b) 从 POST v2/images 调用返回的标头也包含站点支持的导入方法列表。请参阅此规范的 值发现部分。
如果存在多种方法,我如何知道我想要使用的方法的请求应该是什么样子?
有一个 JSON 模式包含此信息。请参阅 格式发现。
如果存在多种导入方法,有什么可以阻止别人添加更多?
必须在 Glance 规范中提出额外的方案,并且必须满足我们为镜像导入实施的发现性和互操作性约束。因此,这并不是一件可以轻易完成的事情。
旧的镜像上传调用怎么办?
对 v2/images/{image_id}/file 的 PUT 作为操作员和受信任服务使用的调用是有意义的,因此我们不建议将其删除。但是,我们建议操作员不要直接将其暴露给最终用户。
我有一个你没有涵盖的问题。
好吧,你可以阅读整个规范。但这里有一些提示
有关导入工作流程和 API 调用的详细信息,请从 提议的更改部分开始。
如果你想了解更多关于为什么选择该工作流程的背景信息,你需要阅读本文档的开头。
如果你想快速了解设计约束,请从 围绕该项目的约束摘要部分开始。
等等,这个规范不是已经批准用于 Mitaka 了吗?
是的,是这样。我们没有实施它,因为我们想确保在开始实施之前彻底探索 替代方案。最终的共识是我们应该坚持最初的提议。这里的关键点是,此规范的实施绝非匆忙完成。
镜像导入规范确实非常长,但我无法满足它。我在哪里可以阅读更多内容?
该规范包含一个 参考文献列表,你可能会觉得有趣。
还有一些最近的 etherpads
此外,你可能会觉得以下补丁的讨论很有趣
参考资料¶
其他相关支持信息
[OSB1] https://blueprints.launchpad.net/glance/+spec/upload-download-workflow
[OSG1] https://review.openstack.org/#/c/220166/
[OSG2] https://review.openstack.org/#/c/220166/4/doc/source/tasks.rst
[OSW4] https://wiki.openstack.org/wiki/Glance-upload-mechanism-reloaded