Glance-tasks-api

Overview
This proposal unifies the new upload workflow, new download workflow , and image cloning blueprints in an extensible, consistent, and easy-to-learn way.

Role of Glance Tasks

 * It provides a common API across openstack installations.
 * Workflow of actual operation is customisable per cloud provider.
 * It will not creates images until there is a high probability of success.
 * It provides a way to deliver meaningful helpful error messages, this depends on how right user is doing things.
 * It free’s the normal upload/download path for trusted users.

Task Address: Manageability
Tasks allow glance to only store “real images” e.g somebody continues to upload JPEG’s and there is nothing to stop him and these images will fill up the queue. Tasks keep glance highly available for NOVA, so the upload and download paths are separated and nobody can use that and use can control the tasks because they are mainly asynchronous. One good thing about the tasks is that user can create a task and then you can pull and see what the status of the task is, so the expectation in the end user that it may take some time. What basically done is queuing up the task and then processing.

Task Address: Security
Screens images for vulnerability user desire

Task Address: Scalability
Tasks enable user to process images asynchronously according to current resource availability. User can do it because some other jobs e.g scanning might be pretty CPU intensive so user might not be able to do a lot at once.

Task Address: Usability
Tasks help manage end user’s expectations. Tasks can reduce user frustration, if user did not upload JPEG; user does not need to reboot 500 servers and then call support to find out where did the process reach.

Tasks can provide better error feedback, so there is a way for user to get info about what exactly is going on and why the image may or may not have been imported.

Pros of Tasks
All pros are also cons.
 * Flexible
 * Customisable
 * Provides a common

Tasks are flexible and customisable
Tasks are flexible, this means that any parameters can be used but it doesn’t gives the end user the exact idea of what parameters should be used. Since, you don’t know the exact idea of the structure, so it is a downside of customisation.

General Workflow

 * 1) User posts a request to /v2/tasks
 * 2) Glance returns a 201 with Location: /v2/tasks/{task-uuid}
 * 3) * The resource at /v2/tasks/{task-uuid} will be an expirable entity
 * 4) User polls /v2/tasks/{task-uuid} for status information on the requested task
 * 5) Eventually, when the task is completed, the resource will contain
 * 6) * task result information, e.g.,
 * 7) ** if the task was successful, the location of the result of the task
 * 8) *** for import or clone tasks, this will be an /images resource
 * 9) *** for export, it will be a location where the exported item may be retrieved
 * 10) ** if the task was not successful, an informative message
 * 11) * the expiration datetime of the tasks resource itself

Task Entities
An task entity is represented by a JSON-encoded data structure.

An task entity has an identifier (id) that is guaranteed to be unique within the endpoint to which it belongs. The id is used as a token in request URIs to interact with that specific task.

An task is always guaranteed to have the following attributes: id, type, status, and self. The other attributes defined in the task schema below are guaranteed to be defined, but will only be returned with a task entity if they have been explicitly set.

Task Properties
(no ordering, just using the numerals to keep count)
 * id
 * 1) type
 * 2) status
 * 3) owner : this is whatever is being used as the image owner in this glance installation
 * 4) input : task "parameters"
 * 5) result
 * 6) created_at
 * 7) updated_at
 * 8) expires_at
 * 9) message

Task Schema
A json-schema for the task entity will be available at the URI /v2/schemas/task

And it goes a little something like this: {   "name": "task", "properties": { "id": { "description": "An identifier for the task", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "type": "string", "required": true },       "owner": { "description": "An identifier for the owner of this task", "type": "string", "required": true },       "type" : { "description": "The type of task represented by this content", "enum": [ "import", "export", "clone" ],           "type": "string", "required": true },       "status" : { "description": "The current status of this task.", "enum": [ "pending", "processing", "success", "failure" ],           "type": "string", "required": true },       "created_at": { "description": "Datetime when this resource was created", "type": "string", "required": true },        "updated_at": { "description": "Datetime when this resource was most recently updated", "type": "string", "required": true },       "expires_at": { "description": "Datetime when this resource is subject to removal", "type": "string" },      "message": { "description": "Human-readable informative message only included when appropriate (usually on failure)", "type": "string", },       "input": { "description": "The input parameters for this task", "type": "object", "required": true },      "result": { "description": "Informatic results of this task", "type": "object", },   },    "links": [ {           "href": "{self}", "rel": "self" },        {            "href": "{file}", "rel": "enclosure" },        {            "href": "{schema}", "rel": "describedby" }   ], }

Task Response Body
The basic tasks response will be Content-type: application/json and will adhere to the task json schema described above.

Task Request Schema
The basic tasks request is defined by the following JSON schema. {   "name": "task_request", "properties": { "type": { "description": "The type of task requested", "enum": [ "import", "export", "clone" ],           "type": "string", "required": true },       "input": { "description": "The input parameters for this task. Valid content depends on the task type, see the documentation for details.", "type": "object", "required": true }   } }

Task Request Body
The basic task request will be Content-type: application/json and will adhere to the task_request json schema described above.

The request schema will be made available at /v2/schemas/task_request

Task States
Tasks will have the following states:
 * : a task has been created, but Glance (via async worker or whatever) hasn't begun to execute the task yet
 * : the task is underway
 * : the task has complete successfully
 * : something went wrong, the task was not able to complete

In the case of failure, it's expected that the task resource will contain a message explaining what went wrong.

Create a Task
POST /v2/tasks

Request body must be appropriate for the task_type.

Display Task Detail
GET /v2/tasks/{task_id}

Returns a task response as defined above.

List Tasks
GET /v2/tasks

Returns a list of tasks owned by the user making the request. Each task will be listed in a sparse format, i.e., only a subset of task fields will be displayed.

The response will adhere to the following JSON schema, which will be available at the URI /v2/schemas/tasks</tt> {   "name": "tasks", "properties": { "tasks": { "items": { "name": "taskdesc", "properties": { "type": { "description": "The type of task requested", "enum": [ "import", "export", "clone" ],                       "type": "string", "required": true },                   "id": { "description": "An identifier for the task", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "type": "string", "required": true },                   "status" : { "description": "The current status of this task.", "enum": [ "pending", "processing", "success", "failure" ],                       "type": "string", "required": true },                   "updated_at": { "description": "Datetime when this resource was most recently updated", "type": "string", "required": true }               }            },            "type": "array" },       "first": { "type": "string" },       "next": { "type": "string" },       "schema": { "type": "string" }   },    "links": [ {           "href": "{first}", "rel": "first" },       {            "href": "{next}", "rel": "next" },       {            "href": "{schema}", "rel": "describedby" }   ] }

Query Parameters
The list tasks request will accept the following query parameters:

filter by task type
GET /v2/tasks?type=import would return all non-expired import tasks owned by the user making the request. The allowed values are 'import', 'export', 'clone'.

filter by task status
GET /v2/tasks?status=pending would return all non-expired tasks owned by the user making the request that are currently in 'pending' status. The allowed values are the legal task status values, i.e., "pending", "processing", "success", "failure"

sort order
By default, the tasks in the list will be sorted by updated_at time in descending chronological order.

The order can be changed by using the 'sort_dir' parameter. Valid values are 'asc' (ascending) and 'desc' (descending). Default is 'desc.' GET /v2/tasks?sort_dir=asc would return the task list sorted by updated_at time in ascending chronological order.

Open Questions

 * 1) What do we return when a user makes a GET for a task UUID that exists, but they don't own?
 * 2) * 401 or 404?
 * 3) The task request will return a 200 even when the task_status is 'failure' (since the task response itself is being returned OK).  Some of these failures will be for things like not-found, format-not-supported, conflict ... this will be mentioned in the 'message' field, but do we want to have a separate failure code or something to make it easier for an API user to extract this info?

Proposed Tasks

 * 1) import
 * 2) export
 * 3) clone

Related Documents

 * Havana summit discussion etherpad (see bottom of pad)
 * original blueprint proposal
 * mailing list discussion of original proposal
 * mailing list discussion of this proposal
 * etherpad of further discussion refining this proposal

Changes
7 Oct 2013: changed list-tasks to return a sparse list of tasks; added status filter, sorting by updated_at; changed the schema URLs to /v2/schemas/task</tt> for the individual task response, /v2/schemas/tasks</tt> for the list-tasks response.

9 Oct 2013: added URI for task request schema, /v2/schemas/task_request</tt>