64b6c9261e
Current folder name New folder name Book title ---------------------------------------------------------- basic-install DELETE cli-guide DELETE common common NEW admin-guide-cloud Cloud Administrators Guide docbkx-example DELETE openstack-block-storage-admin DELETE openstack-compute-admin DELETE openstack-config config-reference OpenStack Configuration Reference openstack-ha high-availability-guide OpenStack High Availabilty Guide openstack-image image-guide OpenStack Virtual Machine Image Guide openstack-install install-guide OpenStack Installation Guide openstack-network-connectivity-admin admin-guide-network OpenStack Networking Administration Guide openstack-object-storage-admin DELETE openstack-security security-guide OpenStack Security Guide openstack-training training-guide OpenStack Training Guide openstack-user user-guide OpenStack End User Guide openstack-user-admin user-guide-admin OpenStack Admin User Guide glossary NEW OpenStack Glossary bug: #1220407 Change-Id: Id5ffc774b966ba7b9a591743a877aa10ab3094c7 author: diane fleming
546 lines
28 KiB
XML
546 lines
28 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<section xml:id="configuring-object-storage-features"
|
||
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">
|
||
<title>Configuring OpenStack Object Storage Features</title>
|
||
<section xml:id="object-storage-rate-limits">
|
||
<?dbhtml stop-chunking?>
|
||
<title>Throttling Resources by Setting Rate Limits</title>
|
||
<para>Rate limiting in OpenStack Object Storage is implemented
|
||
as a pluggable middleware that you configure on the proxy
|
||
server. Rate limiting is performed on requests that result
|
||
in database writes to the account and container sqlite
|
||
dbs. It uses memcached and is dependent on the proxy
|
||
servers having highly synchronized time. The rate limits
|
||
are limited by the accuracy of the proxy server
|
||
clocks.</para>
|
||
<section xml:id="configuration-for-rate-limiting">
|
||
<title>Configuration for Rate Limiting</title>
|
||
<para>All configuration is optional. If no account or
|
||
container limits are provided there will be no rate
|
||
limiting. Available configuration options include:</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-ratelimit.xml"/>
|
||
<para>The container rate limits are linearly interpolated
|
||
from the values given. A sample container rate
|
||
limiting could be:</para>
|
||
<para>container_ratelimit_100 = 100</para>
|
||
<para>container_ratelimit_200 = 50</para>
|
||
<para>container_ratelimit_500 = 20</para>
|
||
<para>This would result in:</para>
|
||
<table rules="all">
|
||
<caption>Values for Rate Limiting with Sample
|
||
Configuration Settings</caption>
|
||
<tbody>
|
||
<tr>
|
||
<td>Container Size</td>
|
||
<td>Rate Limit</td>
|
||
</tr>
|
||
<tr>
|
||
<td>0-99</td>
|
||
<td>No limiting</td>
|
||
</tr>
|
||
<tr>
|
||
<td>100</td>
|
||
<td>100</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td>150</td>
|
||
<td>75</td>
|
||
</tr>
|
||
<tr>
|
||
<td>500</td>
|
||
<td>20</td>
|
||
</tr>
|
||
<tr>
|
||
<td>1000</td>
|
||
<td>20</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
</section>
|
||
<section xml:id="object-storage-healthcheck">
|
||
<title>Health Check</title>
|
||
<para>Health Check provides a simple way to monitor if the
|
||
swift proxy server is alive. If the proxy is access
|
||
with the path /healthcheck, it will respond with “OK”
|
||
in the body, which can be used by monitoring
|
||
tools.</para>
|
||
<xi:include href="../../common/tables/swift-account-server-filter-healthcheck.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-domain-remap">
|
||
<title>Domain Remap</title>
|
||
<para>Domain Remap is middleware that translates container
|
||
and account parts of a domain to path parameters that
|
||
the proxy server understands.</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-domain_remap.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-cname-lookup">
|
||
<title>CNAME Lookup</title>
|
||
<para>CNAME Lookup is middleware that translates an
|
||
unknown domain in the host header to something that
|
||
ends with the configured storage_domain by looking up
|
||
the given domain's CNAME record in DNS.</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-cname_lookup.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-tempurl">
|
||
<title>Temporary URL</title>
|
||
<para>Allows the creation of URLs to provide temporary
|
||
access to objects. For example, a website may wish to
|
||
provide a link to download a large object in Swift,
|
||
but the Swift account has no public access. The
|
||
website can generate a URL that will provide GET
|
||
access for a limited time to the resource. When the
|
||
web browser user clicks on the link, the browser will
|
||
download the object directly from Swift, obviating the
|
||
need for the website to act as a proxy for the
|
||
request. If the user were to share the link with all
|
||
his friends, or accidentally post it on a forum, etc.
|
||
the direct access would be limited to the expiration
|
||
time set when the website created the link. To create
|
||
such temporary URLs, first an
|
||
X-Account-Meta-Temp-URL-Key header must be set on the
|
||
Swift account. Then, an HMAC-SHA1 (RFC 2104) signature
|
||
is generated using the HTTP method to allow (GET or
|
||
PUT), the Unix timestamp the access should be allowed
|
||
until, the full path to the object, and the key set on
|
||
the account. For example, here is code generating the
|
||
signature for a GET for 60 seconds on
|
||
<code>/v1/AUTH_account/container/object</code>:
|
||
<programlisting language="python">
|
||
import hmac
|
||
from hashlib import sha1
|
||
from time import time
|
||
method = 'GET'
|
||
expires = int(time() + 60)
|
||
path = '/v1/AUTH_account/container/object'
|
||
key = 'mykey'
|
||
hmac_body = '%s\n%s\n%s' % (method, expires, path)
|
||
sig = hmac.new(key, hmac_body, sha1).hexdigest()
|
||
</programlisting></para>
|
||
<para>Be certain to use the full path, from the /v1/
|
||
onward. Let's say the sig ends up equaling
|
||
da39a3ee5e6b4b0d3255bfef95601890afd80709 and expires
|
||
ends up 1323479485. Then, for example, the website
|
||
could provide a link to:
|
||
<programlisting>
|
||
https://swift-cluster.example.com/v1/AUTH_account/container/object?
|
||
temp_url_sig=da39a3ee5e6b4b0d3255bfef95601890afd80709&
|
||
temp_url_expires=1323479485
|
||
</programlisting></para>
|
||
<para>Any alteration of the resource path or query
|
||
arguments would result in 401 Unauthorized. Similarly,
|
||
a PUT where GET was the allowed method would 401. HEAD
|
||
is allowed if GET or PUT is allowed. Using this in
|
||
combination with browser form post translation
|
||
middleware could also allow direct-from-browser
|
||
uploads to specific locations in Swift. Note that
|
||
changing the X-Account-Meta-Temp-URL-Key will
|
||
invalidate any previously generated temporary URLs
|
||
within 60 seconds (the memcache time for the key).</para>
|
||
<para>A script called swift-temp-url distributed with swift source
|
||
code eases the temporary URL creation:
|
||
<programlisting>
|
||
$ bin/swift-temp-url GET 3600 /v1/AUTH_account/container/object mykey
|
||
/v1/AUTH_account/container/object?
|
||
temp_url_sig=5c4cc8886f36a9d0919d708ade98bf0cc71c9e91&
|
||
temp_url_expires=1374497657
|
||
</programlisting>
|
||
The path returned by the above command is prefixed with swift
|
||
storage hostname.</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-tempurl.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-name-check">
|
||
<title>Name Check Filter</title>
|
||
<para>Name Check is a filter that disallows any paths that
|
||
contain defined forbidden characters or that exceed a
|
||
defined length.</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-name_check.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-constraints">
|
||
<title>Constraints</title>
|
||
<para>The <literal>swift-constraints</literal> section in
|
||
<filename>swift.conf</filename> allows modification
|
||
of internal limits within swift. These are advanced
|
||
features for tuning the performance of the cluster and
|
||
should be altered with caution.</para>
|
||
<table rules="all">
|
||
<caption>Configuration options for swift-constraints
|
||
in swift.conf</caption>
|
||
<tbody>
|
||
<tr>
|
||
<td>Option</td>
|
||
<td>Default</td>
|
||
<td>Description</td>
|
||
|
||
</tr>
|
||
<tr>
|
||
<td>max_file_size</td>
|
||
<td>5368709122</td>
|
||
<td>the largest "normal" object that can be
|
||
saved in the cluster. This is also the
|
||
limit on the size of each segment of a
|
||
"large" object when using the large object
|
||
manifest support. This value is set in
|
||
bytes. Setting it to lower than 1MiB will
|
||
cause some tests to fail. It is STRONGLY
|
||
recommended to leave this value at the
|
||
default (5 * 2**30 + 2).</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_meta_name_length</td>
|
||
<td>128</td>
|
||
<td>the max number of bytes in the utf8
|
||
encoding of the name portion of a metadata
|
||
header.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_meta_value_lenth</td>
|
||
<td>256</td>
|
||
<td>the max number of bytes in the utf8
|
||
encoding of a metadata value</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_meta_count</td>
|
||
<td>90</td>
|
||
<td>the max number of metadata keys that can
|
||
be stored on a single account, container,
|
||
or object</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_meta_overall_size</td>
|
||
<td>4096</td>
|
||
<td>the max number of bytes in the utf8
|
||
encoding of the metadata (keys +
|
||
values)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_object_name_length</td>
|
||
<td>1024</td>
|
||
<td>the max number of bytes in the utf8
|
||
encoding of an object name</td>
|
||
</tr>
|
||
<tr>
|
||
<td>container_listing_limit</td>
|
||
<td>10000</td>
|
||
<td>the default (and max) number of items
|
||
returned for a container listing
|
||
request</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_account_name_length</td>
|
||
<td>256</td>
|
||
<td>the max number of bytes in the utf8
|
||
encoding of an account name</td>
|
||
</tr>
|
||
<tr>
|
||
<td>max_container_name_length</td>
|
||
<td>256</td>
|
||
<td>the max number of bytes in the utf8
|
||
encoding of a container name</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
<section xml:id="object-storage-dispersion">
|
||
<title>Cluster Health</title>
|
||
<para>There is a
|
||
<literal>swift-dispersion-report</literal> tool
|
||
for measuring overall cluster health. This is
|
||
accomplished by checking if a set of deliberately
|
||
distributed containers and objects are currently in
|
||
their proper places within the cluster. For instance,
|
||
a common deployment has three replicas of each object.
|
||
The health of that object can be measured by checking
|
||
if each replica is in its proper place. If only 2 of
|
||
the 3 is in place the object’s heath can be said to be
|
||
at 66.66%, where 100% would be perfect. A single
|
||
object’s health, especially an older object, usually
|
||
reflects the health of that entire partition the
|
||
object is in. If we make enough objects on a distinct
|
||
percentage of the partitions in the cluster, we can
|
||
get a pretty valid estimate of the overall cluster
|
||
health. In practice, about 1% partition coverage seems
|
||
to balance well between accuracy and the amount of
|
||
time it takes to gather results. The first thing that
|
||
needs to be done to provide this health value is
|
||
create a new account solely for this usage. Next, we
|
||
need to place the containers and objects throughout
|
||
the system so that they are on distinct partitions.
|
||
The swift-dispersion-populate tool does this by making
|
||
up random container and object names until they fall
|
||
on distinct partitions. Last, and repeatedly for the
|
||
life of the cluster, we need to run the
|
||
swift-dispersion-report tool to check the health of
|
||
each of these containers and objects. These tools need
|
||
direct access to the entire cluster and to the ring
|
||
files (installing them on a proxy server will probably
|
||
do). Both <command>swift-dispersion-populate</command> and
|
||
<command>swift-dispersion-report</command> use the same configuration
|
||
file, <filename>/etc/swift/dispersion.conf</filename>.
|
||
Example dispersion.conf file:
|
||
<programlisting language="ini">
|
||
[dispersion]
|
||
auth_url = http://localhost:8080/auth/v1.0
|
||
auth_user = test:tester
|
||
auth_key = testing
|
||
</programlisting>
|
||
There are also options for the conf file for
|
||
specifying the dispersion coverage (defaults to 1%),
|
||
retries, concurrency, etc. though usually the defaults
|
||
are fine. Once the configuration is in place, run
|
||
swift-dispersion-populate to populate the containers
|
||
and objects throughout the cluster. Now that those
|
||
containers and objects are in place, you can run
|
||
swift-dispersion-report to get a dispersion report, or
|
||
the overall health of the cluster. Here is an example
|
||
of a cluster in perfect health:
|
||
<screen><prompt>$</prompt> <userinput>swift-dispersion-report</userinput>
|
||
<computeroutput>Queried 2621 containers for dispersion reporting, 19s, 0 retries
|
||
100.00% of container copies found (7863 of 7863)
|
||
Sample represents 1.00% of the container partition space
|
||
|
||
Queried 2619 objects for dispersion reporting, 7s, 0 retries
|
||
100.00% of object copies found (7857 of 7857)
|
||
Sample represents 1.00% of the object partition space
|
||
</computeroutput></screen>
|
||
Now, deliberately double the weight of a device in the
|
||
object ring (with replication turned off) and rerun
|
||
the dispersion report to show what impact that has:
|
||
<screen><prompt>$</prompt> <userinput>swift-ring-builder object.builder set_weight d0 200</userinput>
|
||
<prompt>$</prompt> <userinput>swift-ring-builder object.builder rebalance</userinput>
|
||
...
|
||
<prompt>$</prompt> <userinput>swift-dispersion-report</userinput>
|
||
<computeroutput>Queried 2621 containers for dispersion reporting, 8s, 0 retries
|
||
100.00% of container copies found (7863 of 7863)
|
||
Sample represents 1.00% of the container partition space
|
||
|
||
Queried 2619 objects for dispersion reporting, 7s, 0 retries
|
||
There were 1763 partitions missing one copy.
|
||
77.56% of object copies found (6094 of 7857)
|
||
Sample represents 1.00% of the object partition space
|
||
</computeroutput></screen>
|
||
You can see the health of the objects in the cluster
|
||
has gone down significantly. Of course, this test
|
||
environment has just four devices, in a production
|
||
environment with many devices the impact of one device
|
||
change is much less. Next, run the replicators to get
|
||
everything put back into place and then rerun the
|
||
dispersion report:
|
||
<programlisting>
|
||
... start object replicators and monitor logs until they're caught up ...
|
||
$ swift-dispersion-report
|
||
Queried 2621 containers for dispersion reporting, 17s, 0 retries
|
||
100.00% of container copies found (7863 of 7863)
|
||
Sample represents 1.00% of the container partition space
|
||
|
||
Queried 2619 objects for dispersion reporting, 7s, 0 retries
|
||
100.00% of object copies found (7857 of 7857)
|
||
Sample represents 1.00% of the object partition space
|
||
</programlisting>
|
||
Alternatively, the dispersion report can also be
|
||
output in json format. This allows it to be more
|
||
easily consumed by third party utilities:
|
||
<screen><prompt>$</prompt> <userinput>swift-dispersion-report -j</userinput>
|
||
<computeroutput>{"object": {"retries:": 0, "missing_two": 0, "copies_found": 7863, "missing_one": 0,
|
||
"copies_expected": 7863, "pct_found": 100.0, "overlapping": 0, "missing_all": 0}, "container":
|
||
{"retries:": 0, "missing_two": 0, "copies_found": 12534, "missing_one": 0, "copies_expected":
|
||
12534, "pct_found": 100.0, "overlapping": 15, "missing_all": 0}}</computeroutput></screen>
|
||
</para>
|
||
<xi:include href="../../common/tables/swift-dispersion-dispersion.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-slo">
|
||
<!-- Usage documented in http://docs.openstack.org/developer/swift/overview_large_objects.html -->
|
||
<title>Static Large Object (SLO) support</title>
|
||
<para>This feature is very similar to Dynamic Large Object
|
||
(DLO) support in that it allows the user to upload
|
||
many objects concurrently and afterwards download them
|
||
as a single object. It is different in that it does
|
||
not rely on eventually consistent container listings
|
||
to do so. Instead, a user defined manifest of the
|
||
object segments is used.</para>
|
||
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-slo.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-container-quotas">
|
||
<title>Container Quotas</title>
|
||
<para>The container_quotas middleware implements simple
|
||
quotas that can be imposed on swift containers by a
|
||
user with the ability to set container metadata, most
|
||
likely the account administrator. This can be useful
|
||
for limiting the scope of containers that are
|
||
delegated to non-admin users, exposed to formpost
|
||
uploads, or just as a self-imposed sanity
|
||
check.</para>
|
||
|
||
<para>Any object PUT operations that exceed these quotas
|
||
return a 413 response (request entity too large) with
|
||
a descriptive body.</para>
|
||
|
||
<para>Quotas are subject to several limitations: eventual
|
||
consistency, the timeliness of the cached
|
||
container_info (60 second ttl by default), and it's
|
||
unable to reject chunked transfer uploads that exceed
|
||
the quota (though once the quota is exceeded, new
|
||
chunked transfers will be refused).</para>
|
||
|
||
<para>Quotas are set by adding meta values to the
|
||
container, and are validated when set: <itemizedlist>
|
||
<listitem>
|
||
<para>X-Container-Meta-Quota-Bytes: Maximum
|
||
size of the container, in bytes.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>X-Container-Meta-Quota-Count: Maximum
|
||
object count of the container.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-container-quotas.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-account-quotas">
|
||
<title>Account Quotas</title>
|
||
<para>The account_quotas middleware aims to block write
|
||
requests (PUT, POST) if a given account quota (in bytes)
|
||
is exceeded while DELETE requests are still
|
||
allowed.</para>
|
||
<para>The x-account-meta-quota-bytes metadata entry must
|
||
be set to store and enable the quota. Write requests
|
||
to this metadata entry are only permitted for resellers.
|
||
There isn't any account quota limitation on a reseller
|
||
account even if x-account-meta-quota-bytes is set.</para>
|
||
<para>Any object PUT operations that exceed the quota
|
||
return a 413 response (request entity too large) with
|
||
a descriptive body.</para>
|
||
<para>The following command uses an admin account that own
|
||
the Reseller role to set a quota on the test account:
|
||
<screen><prompt>$</prompt> <userinput>swift -A http://127.0.0.1:8080/auth/v1.0 -U admin:admin -K admin \
|
||
--os-storage-url=http://127.0.0.1:8080/v1/AUTH_test post -m quota-bytes:10000</userinput></screen>
|
||
Here is the stat listing of an account where quota has been set:
|
||
<screen><prompt>$</prompt> <userinput>swift -A http://127.0.0.1:8080/auth/v1.0 -U test:tester -K testing stat</userinput>
|
||
<computeroutput>Account: AUTH_test
|
||
Containers: 0
|
||
Objects: 0
|
||
Bytes: 0
|
||
Meta Quota-Bytes: 10000
|
||
X-Timestamp: 1374075958.37454
|
||
X-Trans-Id: tx602634cf478546a39b1be-0051e6bc7a</computeroutput></screen>
|
||
The command below removes the account quota:
|
||
<screen><prompt>$</prompt> <userinput>swift -A http://127.0.0.1:8080/auth/v1.0 -U admin:admin -K admin --os-storage-url=http://127.0.0.1:8080/v1/AUTH_test post -m quota-bytes:</userinput></screen>
|
||
</para>
|
||
</section>
|
||
<section xml:id="object-storage-bulk-delete">
|
||
<title>Bulk Delete</title>
|
||
<para>Will delete multiple files from their account with a
|
||
single request. Responds to DELETE requests with a header
|
||
'X-Bulk-Delete: true_value'. The body of the DELETE
|
||
request will be a newline separated list of files to
|
||
delete. The files listed must be URL encoded and in the
|
||
form:
|
||
<programlisting>
|
||
/container_name/obj_name
|
||
</programlisting>
|
||
</para>
|
||
<para>If all files were successfully deleted (or did not
|
||
exist) will return an HTTPOk. If any files failed to
|
||
delete will return an HTTPBadGateway. In both cases the
|
||
response body is a json dictionary specifying in the
|
||
number of files successfully deleted, not found, and a
|
||
list of the files that failed.</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-bulk.xml"/>
|
||
</section>
|
||
<xi:include href="section_configure_s3.xml"/>
|
||
<section xml:id="object-storage-drive-audit">
|
||
<title>Drive Audit</title>
|
||
<para>The swift-drive-audit configuration items reference a script that can be run via cron to watch for bad drives. If
|
||
errors are detected, it will unmount the bad drive, so that OpenStack Object Storage can work
|
||
around it. It takes the following options:</para>
|
||
<xi:include href="../../common/tables/swift-drive-audit-drive-audit.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-form-post">
|
||
<title>Form Post</title>
|
||
<para>The Form Post middleware provides the ability to upload objects to
|
||
a cluster using an HTML form POST. The format of the form is:</para>
|
||
<programlisting><![CDATA[
|
||
<form action="<swift-url>" method="POST"
|
||
enctype="multipart/form-data">
|
||
<input type="hidden" name="redirect" value="<redirect-url>" />
|
||
<input type="hidden" name="max_file_size" value="<bytes>" />
|
||
<input type="hidden" name="max_file_count" value="<count>" />
|
||
<input type="hidden" name="expires" value="<unix-timestamp>" />
|
||
<input type="hidden" name="signature" value="<hmac>" />
|
||
<input type="file" name="file1" /><br />
|
||
<input type="submit" />
|
||
</form>]]>
|
||
</programlisting>
|
||
<para>The <literal>swift-url</literal> is the URL to the Swift destination, such as:
|
||
<uri>https://swift-cluster.example.com/v1/AUTH_account/container/object_prefix</uri>
|
||
The name of each file uploaded will be appended to the <literal>swift-url</literal> given. So, you can upload
|
||
directly to the root of container with a url like:
|
||
<uri>https://swift-cluster.example.com/v1/AUTH_account/container/</uri>
|
||
Optionally, you can include an object prefix to better separate different users’ uploads, such as:
|
||
<uri>https://swift-cluster.example.com/v1/AUTH_account/container/object_prefix</uri>
|
||
</para>
|
||
|
||
<para>Note the form method must be POST and the enctype must be set as “multipart/form-data”.
|
||
|
||
The redirect attribute is the URL to redirect the browser to after the upload completes. The URL
|
||
will have status and message query parameters added to it, indicating the HTTP status code for the
|
||
upload (2xx is success) and a possible message for further information if there was an error (such
|
||
as “max_file_size exceeded”).
|
||
|
||
The max_file_size attribute must be included and indicates the largest single file upload that can
|
||
be done, in bytes.
|
||
|
||
The max_file_count attribute must be included and indicates the
|
||
maximum number of files that can be uploaded with the form. Include
|
||
additional <code><![CDATA[<input type="file" name="filexx"/>]]></code>
|
||
attributes if desired.
|
||
|
||
The expires attribute is the Unix timestamp before which the form must be submitted before it is
|
||
invalidated.
|
||
|
||
The signature attribute is the HMAC-SHA1 signature of the form. Here is sample code for computing
|
||
the signature:
|
||
<programlisting language="python">
|
||
import hmac
|
||
from hashlib import sha1
|
||
from time import time
|
||
path = '/v1/account/container/object_prefix'
|
||
redirect = 'https://myserver.com/some-page'
|
||
max_file_size = 104857600
|
||
max_file_count = 10
|
||
expires = int(time() + 600)
|
||
key = 'mykey'
|
||
hmac_body = '%s\n%s\n%s\n%s\n%s' % (path, redirect,
|
||
max_file_size, max_file_count, expires)
|
||
signature = hmac.new(key, hmac_body, sha1).hexdigest()
|
||
</programlisting>
|
||
The key is the value of the X-Account-Meta-Temp-URL-Key header on the account.
|
||
|
||
Be certain to use the full path, from the /v1/ onward.
|
||
|
||
The command line tool swift-form-signature may be used (mostly just when testing) to compute
|
||
expires and signature.
|
||
</para>
|
||
<para>
|
||
Also note that the file attributes must be after the other attributes in order to be processed
|
||
correctly. If attributes come after the file, they won’t be sent with the subrequest (there is no
|
||
way to parse all the attributes on the server-side without reading the whole thing into memory – to
|
||
service many requests, some with large files, there just isn’t enough memory on the server, so
|
||
attributes following the file are simply ignored).</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-formpost.xml"/>
|
||
</section>
|
||
<section xml:id="object-storage-static-web">
|
||
<title>Static Websites</title>
|
||
<para>When configured, the StaticWeb WSGI middleware serves container
|
||
data as a static web site with index file and error file resolution and
|
||
optional file listings. This mode is normally only active for anonymous
|
||
requests.</para>
|
||
<xi:include href="../../common/tables/swift-proxy-server-filter-staticweb.xml"/>
|
||
</section>
|
||
</section>
|