Adds large object information to End User Guide
With the moving of the Object Storage API content from a long-form dev guide to a specification, some topics needed To be added to the End User Guide. Change-Id: I21813e5975c8cefa9dd5f34cb2039b2f41471cd8 Partial-bug: 1392382
This commit is contained in:
parent
9a74743ccd
commit
356358e94f
@ -0,0 +1,6 @@
|
|||||||
|
PUT /{api_version}/{account}/{container}/{object} HTTP/1.1
|
||||||
|
Host: storage.clouddrive.com
|
||||||
|
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
|
||||||
|
ETag: 8a964ee2a5e88be344f36c22562a6486
|
||||||
|
Content-Length: 1
|
||||||
|
X-Object-Meta-PIN: 1234
|
@ -0,0 +1,6 @@
|
|||||||
|
PUT /{api_version}/{account}/{container}/{object} HTTP/1.1
|
||||||
|
Host: storage.clouddrive.com
|
||||||
|
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
|
||||||
|
ETag: 8a964ee2a5e88be344f36c22562a6486
|
||||||
|
Content-Length: 1
|
||||||
|
X-Object-Meta-PIN: 1234
|
17
doc/user-guide/samples/slo-manifest-example.txt
Normal file
17
doc/user-guide/samples/slo-manifest-example.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"path": "mycontainer/objseg1",
|
||||||
|
"etag": "0228c7926b8b642dfb29554cd1f00963",
|
||||||
|
"size_bytes": 1468006
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "mycontainer/pseudodir/seg-obj2",
|
||||||
|
"etag": "5bfc9ea51a00b790717eeb934fb77b9b",
|
||||||
|
"size_bytes": 1572864
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "other-container/seg-final",
|
||||||
|
"etag": "b9c3da507d2557c1ddc51f27c54bae51",
|
||||||
|
"size_bytes": 256
|
||||||
|
}
|
||||||
|
]
|
6
doc/user-guide/samples/upload-manifest-req.txt
Normal file
6
doc/user-guide/samples/upload-manifest-req.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
PUT /{api_version}/{account}/{container}/{object} HTTP/1.1
|
||||||
|
Host: storage.clouddrive.com
|
||||||
|
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
|
||||||
|
Content-Length: 0
|
||||||
|
X-Object-Meta-PIN: 1234
|
||||||
|
X-Object-Manifest: {container}/{prefix}
|
1
doc/user-guide/samples/upload-manifest-resp.txt
Normal file
1
doc/user-guide/samples/upload-manifest-resp.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
[...]
|
@ -123,4 +123,5 @@ X-Timestamp: 1392684036.33306</computeroutput></screen>
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
<xi:include href="section_object-api-versioning.xml"/>
|
<xi:include href="section_object-api-versioning.xml"/>
|
||||||
|
<xi:include href="section_object-api-create-large-objects.xml"/>
|
||||||
</section>
|
</section>
|
||||||
|
379
doc/user-guide/section_object-api-create-large-objects.xml
Normal file
379
doc/user-guide/section_object-api-create-large-objects.xml
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE section [ <!ENTITY % openstack SYSTEM "../common/entities/openstack.ent"> %openstack; ]>
|
||||||
|
<section xmlns="http://docbook.org/ns/docbook"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
|
||||||
|
xml:id="large-object-creation">
|
||||||
|
<title>Large objects</title>
|
||||||
|
<para>By default, the content of an object cannot be greater than
|
||||||
|
5 GB. However, you can use a number of smaller objects to
|
||||||
|
construct a large object. The large object is comprised of two
|
||||||
|
types of objects:</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para><emphasis role="bold">Segment objects</emphasis>
|
||||||
|
store the object content. You can divide your content
|
||||||
|
into segments, and upload each segment into its own
|
||||||
|
segment object. Segment objects do not have any
|
||||||
|
special features. You create, update, download, and
|
||||||
|
delete segment objects just as you would normal
|
||||||
|
objects.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>A <emphasis role="bold">manifest object</emphasis>
|
||||||
|
links the segment objects into one logical large
|
||||||
|
object. When you download a manifest object, Object
|
||||||
|
Storage concatenates and returns the contents of the
|
||||||
|
segment objects in the response body of the request.
|
||||||
|
This behavior extends to the response headers returned
|
||||||
|
by &GET; and &HEAD; requests. The
|
||||||
|
<literal>Content-Length</literal> response header
|
||||||
|
value is the total size of all segment objects. Object
|
||||||
|
Storage calculates the <literal>ETag</literal>
|
||||||
|
response header value by taking the
|
||||||
|
<literal>ETag</literal> value of each segment,
|
||||||
|
concatenating them together, and returning the MD5
|
||||||
|
checksum of the result. The manifest object types
|
||||||
|
are:</para>
|
||||||
|
<variablelist wordsize="10">
|
||||||
|
<varlistentry>
|
||||||
|
<term><emphasis role="bold">Static large
|
||||||
|
objects</emphasis></term>
|
||||||
|
<listitem>
|
||||||
|
<para>The manifest object content is an
|
||||||
|
ordered list of the names of the segment
|
||||||
|
objects in JSON format. See <xref
|
||||||
|
linkend="static-large-objects"
|
||||||
|
/>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><emphasis role="bold">Dynamic large
|
||||||
|
objects</emphasis></term>
|
||||||
|
<listitem>
|
||||||
|
<para>The manifest object has no content but
|
||||||
|
it has a
|
||||||
|
<literal>X-Object-Manifest</literal>
|
||||||
|
metadata header. The value of this header
|
||||||
|
is
|
||||||
|
<literal>{container}/{prefix}</literal>,
|
||||||
|
where <literal>{container}</literal> is
|
||||||
|
the name of the container where the
|
||||||
|
segment objects are stored, and
|
||||||
|
<literal>{prefix}</literal> is a
|
||||||
|
string that all segment objects have in
|
||||||
|
common. See <xref
|
||||||
|
linkend="dynamic-large-object-creation"
|
||||||
|
/>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<note>
|
||||||
|
<para>If you make a © request by using a manifest object
|
||||||
|
as the source, the new object is a normal, and not a
|
||||||
|
segment, object. If the total size of the source segment
|
||||||
|
objects exceeds 5 GB, the © request fails.
|
||||||
|
However, you can make a duplicate of the manifest object
|
||||||
|
and this new object can be larger than 5 GB.</para>
|
||||||
|
</note>
|
||||||
|
<section xml:id="static-large-objects">
|
||||||
|
<title>Static large objects</title>
|
||||||
|
<para>To create a static large object, divide your content
|
||||||
|
into pieces and create (upload) a segment object to
|
||||||
|
contain each piece.</para>
|
||||||
|
<para>You must record the <literal>ETag</literal> response
|
||||||
|
header that the &PUT; operation returns. Alternatively,
|
||||||
|
you can calculate the MD5 checksum of the segment prior to
|
||||||
|
uploading and include this in the <literal>ETag</literal>
|
||||||
|
request header. This ensures that the upload cannot
|
||||||
|
corrupt your data.</para>
|
||||||
|
<para>List the name of each segment object along with its size
|
||||||
|
and MD5 checksum in order.</para>
|
||||||
|
<para>Create a manifest object. Include the
|
||||||
|
<parameter>?multipart-manifest=put</parameter> query
|
||||||
|
string at the end of the manifest object name to indicate
|
||||||
|
that this is a manifest object.</para>
|
||||||
|
<para>The body of the &PUT; request on the manifest object
|
||||||
|
comprises a json list, where each element contains the
|
||||||
|
following attributes:</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><code>path</code></term>
|
||||||
|
<listitem>
|
||||||
|
<para>The container and object name in the format:
|
||||||
|
<code>{container-name}/{object-name}</code>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><code>etag</code></term>
|
||||||
|
<listitem>
|
||||||
|
<para>The MD5 checksum of the content of the
|
||||||
|
segment object. This value must match the
|
||||||
|
<literal>ETag</literal> of that
|
||||||
|
object.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><code>size_bytes</code></term>
|
||||||
|
<listitem>
|
||||||
|
<para>The size of the segment object. This value
|
||||||
|
must match the
|
||||||
|
<literal>Content-Length</literal> of that
|
||||||
|
object.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<example>
|
||||||
|
<title>Static large object manifest list</title>
|
||||||
|
<para>This example shows three segment objects. You can
|
||||||
|
use several containers and the object names do not
|
||||||
|
have to conform to a specific pattern, in contrast to
|
||||||
|
dynamic large objects.</para>
|
||||||
|
<literallayout class="monospaced"><xi:include href="samples/slo-manifest-example.txt" parse="text"/></literallayout>
|
||||||
|
</example>
|
||||||
|
<para>The <literal>Content-Length</literal> request header
|
||||||
|
must contain the length of the json content—not the
|
||||||
|
length of the segment objects. However, after the &PUT;
|
||||||
|
operation completes, the <literal>Content-Length</literal>
|
||||||
|
metadata is set to the total length of all the object
|
||||||
|
segments. A similar situation applies to the
|
||||||
|
<literal>ETag</literal>. If used in the &PUT;
|
||||||
|
operation, it must contain the MD5 checksum of the json
|
||||||
|
content. The <literal>ETag</literal> metadata value is
|
||||||
|
then set to be the MD5 checksum of the concatenated
|
||||||
|
<literal>ETag</literal> values of the object segments.
|
||||||
|
You can also set the <literal>Content-Type</literal>
|
||||||
|
request header and custom object metadata.</para>
|
||||||
|
<para>When the &PUT; operation sees the
|
||||||
|
<parameter>?multipart-manifest=put</parameter> query
|
||||||
|
parameter, it reads the request body and verifies that
|
||||||
|
each segment object exists and that the sizes and ETags
|
||||||
|
match. If there is a mismatch, the &PUT;operation
|
||||||
|
fails.</para>
|
||||||
|
<para>If everything matches, the manifest object is created.
|
||||||
|
The <literal>X-Static-Large-Object</literal> metadata is
|
||||||
|
set to <literal>true</literal> indicating that this is a
|
||||||
|
static object manifest.</para>
|
||||||
|
<para>Normally when you perform a &GET; operation on the
|
||||||
|
manifest object, the response body contains the
|
||||||
|
concatenated content of the segment objects. To download
|
||||||
|
the manifest list, use the
|
||||||
|
<parameter>?multipart-manifest=get</parameter> query
|
||||||
|
parameter. The resulting list is not formatted the same as
|
||||||
|
the manifest you originally used in the &PUT;
|
||||||
|
operation.</para>
|
||||||
|
<para>If you use the &DELETE; operation on a manifest object,
|
||||||
|
the manifest object is deleted. The segment objects are
|
||||||
|
not affected. However, if you add the
|
||||||
|
<parameter>?multipart-manifest=delete</parameter>
|
||||||
|
query parameter, the segment objects are deleted and if
|
||||||
|
all are successfully deleted, the manifest object is also
|
||||||
|
deleted.</para>
|
||||||
|
<para>To change the manifest, use a &PUT; operation with the
|
||||||
|
<parameter>?multipart-manifest=put</parameter> query
|
||||||
|
parameter. This request creates a manifest object. You can
|
||||||
|
also update the object metadata in the usual way.</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="dynamic-large-object-creation">
|
||||||
|
<title>Dynamic large objects</title>
|
||||||
|
<para>You must segment objects that are larger than 5 GB
|
||||||
|
before you can upload them. You then upload the segment
|
||||||
|
objects like you would any other object and create a
|
||||||
|
dynamic large manifest object. The manifest object tells
|
||||||
|
Object Storage how to find the segment objects that
|
||||||
|
comprise the large object. The segments remain
|
||||||
|
individually addressable, but retrieving the manifest
|
||||||
|
object streams all the segments concatenated. There is no
|
||||||
|
limit to the number of segments that can be a part of a
|
||||||
|
single large object.</para>
|
||||||
|
<para>To ensure the download works correctly, you must upload
|
||||||
|
all the object segments to the same container and ensure
|
||||||
|
that each object name is prefixed in such a way that it
|
||||||
|
sorts in the order in which it should be concatenated. You
|
||||||
|
also create and upload a manifest file. The manifest file
|
||||||
|
is a zero-byte file with the extra
|
||||||
|
<literal>X-Object-Manifest</literal>
|
||||||
|
<code>{container}/{prefix}</code> header, where
|
||||||
|
<code>{container}</code> is the container the object
|
||||||
|
segments are in and <code>{prefix}</code> is the common
|
||||||
|
prefix for all the segments. You must UTF-8-encode and
|
||||||
|
then URL-encode the container and common prefix in the
|
||||||
|
<literal>X-Object-Manifest</literal> header.</para>
|
||||||
|
<para>It is best to upload all the segments first and then
|
||||||
|
create or update the manifest. With this method, the full
|
||||||
|
object is not available for downloading until the upload
|
||||||
|
is complete. Also, you can upload a new set of segments to
|
||||||
|
a second location and update the manifest to point to this
|
||||||
|
new location. During the upload of the new segments, the
|
||||||
|
original manifest is still available to download the first
|
||||||
|
set of segments.</para>
|
||||||
|
<example>
|
||||||
|
<title>Upload segment of large object request:
|
||||||
|
HTTP</title>
|
||||||
|
<literallayout class="monospaced"><xi:include href="samples/large-object-upload-segment-req.txt" parse="text"/></literallayout>
|
||||||
|
</example>
|
||||||
|
<para>No response body is returned. A status code of
|
||||||
|
<returnvalue>2<replaceable>nn</replaceable></returnvalue>
|
||||||
|
(between 200 and 299, inclusive) indicates a successful
|
||||||
|
write; status <errorcode>411</errorcode>
|
||||||
|
<errortext>Length Required</errortext> denotes a missing
|
||||||
|
<literal>Content-Length</literal> or
|
||||||
|
<literal>Content-Type</literal> header in the request.
|
||||||
|
If the MD5 checksum of the data written to the storage
|
||||||
|
system does NOT match the (optionally) supplied ETag
|
||||||
|
value, a <errorcode>422</errorcode>
|
||||||
|
<errortext>Unprocessable Entity</errortext> response is
|
||||||
|
returned.</para>
|
||||||
|
<para>You can continue uploading segments, like this example
|
||||||
|
shows, prior to uploading the manifest.</para>
|
||||||
|
<example>
|
||||||
|
<title>Upload next segment of large object request:
|
||||||
|
HTTP</title>
|
||||||
|
<literallayout class="monospaced"><xi:include href="samples/large-object-upload-next-segment-req.txt" parse="text"/></literallayout>
|
||||||
|
</example>
|
||||||
|
<para>Next, upload the manifest you created that indicates the
|
||||||
|
container where the object segments reside. Note that
|
||||||
|
uploading additional segments after the manifest is
|
||||||
|
created causes the concatenated object to be that much
|
||||||
|
larger but you do not need to recreate the manifest file
|
||||||
|
for subsequent additional segments.</para>
|
||||||
|
<example>
|
||||||
|
<title>Upload manifest request: HTTP</title>
|
||||||
|
<literallayout class="monospaced"><xi:include href="samples/upload-manifest-req.txt" parse="text"/></literallayout>
|
||||||
|
</example>
|
||||||
|
<example>
|
||||||
|
<title>Upload manifest response: HTTP</title>
|
||||||
|
<literallayout class="monospaced"><xi:include href="samples/upload-manifest-resp.txt" parse="text"/></literallayout>
|
||||||
|
</example>
|
||||||
|
<para>The <literal>Content-Type</literal> in the response for
|
||||||
|
a &GET; or &HEAD; on the manifest is the same as the
|
||||||
|
<literal>Content-Type</literal> set during the &PUT;
|
||||||
|
request that created the manifest. You can change the
|
||||||
|
<literal>Content-Type</literal> by reissuing the &PUT;
|
||||||
|
request.</para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="comparison_dynamic_static_objects">
|
||||||
|
<title>Comparison of static and dynamic large objects</title>
|
||||||
|
<para>While static and dynamic objects have similar behavior,
|
||||||
|
this table describes their differences:</para>
|
||||||
|
<table rules="all">
|
||||||
|
<caption>Static and dynamic large objects</caption>
|
||||||
|
<col width="20%"/>
|
||||||
|
<col width="40%"/>
|
||||||
|
<col width="40%"/>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td/>
|
||||||
|
<th>Static large object</th>
|
||||||
|
<th>Dynamic large object</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>End-to-end integrity</th>
|
||||||
|
<td><para>Assured. The list of segments includes
|
||||||
|
the MD5 checksum (<literal>ETag</literal>)
|
||||||
|
of each segment. You cannot upload the
|
||||||
|
manifest object if the
|
||||||
|
<literal>ETag</literal> in the list
|
||||||
|
differs from the uploaded segment object.
|
||||||
|
If a segment is somehow lost, an attempt
|
||||||
|
to download the manifest object results in
|
||||||
|
an error.</para></td>
|
||||||
|
<td><para>Not guaranteed. The eventual consistency
|
||||||
|
model means that although you have
|
||||||
|
uploaded a segment object, it might not
|
||||||
|
appear in the container listing until
|
||||||
|
later. If you download the manifest before
|
||||||
|
it appears in the container, it does not
|
||||||
|
form part of the content returned in
|
||||||
|
response to a &GET; request.</para></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Upload order</th>
|
||||||
|
<td><para>You must upload the segment objects
|
||||||
|
before you upload the manifest
|
||||||
|
object.</para></td>
|
||||||
|
<td><para>You can upload manifest and segment
|
||||||
|
objects in any order. You are recommended
|
||||||
|
to upload the manifest object after the
|
||||||
|
segments in case a premature download of
|
||||||
|
the manifest occurs. However, this is not
|
||||||
|
enforced.</para></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Removal or addition of segment objects</th>
|
||||||
|
<td><para>You cannot add or remove segment objects
|
||||||
|
from the manifest. However, you can create
|
||||||
|
a completely new manifest object of the
|
||||||
|
same name with a different manifest
|
||||||
|
list.</para></td>
|
||||||
|
<td><para>You can upload new segment objects or
|
||||||
|
remove existing segments. The names must
|
||||||
|
simply match the
|
||||||
|
<literal>{prefix}</literal> supplied
|
||||||
|
in
|
||||||
|
<literal>X-Object-Manifest</literal>.</para></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Segment object size and number</th>
|
||||||
|
<td><para>Segment objects must be at least
|
||||||
|
1 MB in size (by default). The final
|
||||||
|
segment object can be any size. At most,
|
||||||
|
1000 segments are supported (by
|
||||||
|
default).</para></td>
|
||||||
|
<td><para>Segment objects can be any
|
||||||
|
size.</para></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Segment object container name</th>
|
||||||
|
<td><para>The manifest list includes the container
|
||||||
|
name of each object. Segment objects can
|
||||||
|
be in different containers.</para></td>
|
||||||
|
<td><para>All segment objects must be in the same
|
||||||
|
container.</para></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Manifest object metadata</th>
|
||||||
|
<td><para>The object has
|
||||||
|
<literal>X-Static-Large-Object</literal>
|
||||||
|
set to <literal>true</literal>. You do not
|
||||||
|
set this metadata directly. Instead the
|
||||||
|
system sets it when you &PUT; a static
|
||||||
|
manifest object.</para></td>
|
||||||
|
<td><para>The <literal>X-Object-Manifest</literal>
|
||||||
|
value is the
|
||||||
|
<literal>{container}/{prefix}</literal>,
|
||||||
|
which indicates where the segment objects
|
||||||
|
are located. You supply this request
|
||||||
|
header in the &PUT; operation.</para></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Copying the manifest object</th>
|
||||||
|
<td><para>Include the
|
||||||
|
<parameter>?multipart-manifest=get</parameter>
|
||||||
|
query string in the © request. The
|
||||||
|
new object contains the same manifest as
|
||||||
|
the original. The segment objects are not
|
||||||
|
copied. Instead, both the original and new
|
||||||
|
manifest objects share the same set of
|
||||||
|
segment objects.</para>
|
||||||
|
</td>
|
||||||
|
<td><para>The © operation does not create a
|
||||||
|
manifest object. To duplicate a manifest
|
||||||
|
object, use the &GET; operation to read
|
||||||
|
the value of
|
||||||
|
<literal>X-Object-Manifest</literal>
|
||||||
|
and use this value in the
|
||||||
|
<literal>X-Object-Manifest</literal>
|
||||||
|
request header in a &PUT; operation. This
|
||||||
|
creates a new manifest object that shares
|
||||||
|
the same set of segment objects as the
|
||||||
|
original manifest object.</para></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
</section>
|
Loading…
Reference in New Issue
Block a user