Project: Triton Object Storage (Runtime / Cloud Native Storage)
File: storage-reference.md

Manta uses a REST API to read, write, and delete objects. This document assumes that you are familiar with HTTP-based REST systems, including HTTP requests, responses, status codes, and headers. If you want to start with basic information on Manta, see the tutorial. Unless otherwise specified, the semantics described here are stable, which means that you can expect that future updates will not change the documented behavior. You should avoid relying on behavior not specified here. The storage service is based on two concepts: object and directories. Objects* consist of data and metadata you can read, write, and delete from the storage service. The data portion is opaque. The metadata is a set of HTTP headers that describe the object, such as `Content-Type` and `Content-MD5`. An object is identified by a name. Directories* are named groups of objects, as on traditional file systems. Every object belongs to a directory. The private storage directory, `/:login/stor` functions as the top level, or root directory. Objects are the primary entity you store in Manta. Objects can be of any size, including zero bytes. Objects consist of your raw, uninterpreted data, as well as the metadata (HTTP headers) returned when you retrieve an object. There are several headers for objects that control HTTP semantics in Manta. When you write an object, you must use one of two headers: Use `Content-Length` if you can specify the object size in bytes. Use `transfer-encoding: chunked` to upload objects using . Chunked encoding lets you stream an object for storage without knowing the size of the object ahead of time. By default, the maximum amount of data you can send this way is 5GB. You can use the optional `max-content-length` header to specify how much space you estimate the object requires. This estimate is only an upper bound. The system will record how much data you actually transferred and record that. Subsequent GET requests will return the actual size of the object. You can, but are not required to, use the header in your write requests. Using this header saves network bandwidth. If the write request would fail, the system returns an error without transferring any data. The node-manta CLI use this feature. You should always specify a `Content-Type` header, which will be stored and returned back (HTTP content-negotiation will be handled). If you do not specify a content type, the default is `application/octet-stream`. If you specify a `Content-MD5` header, the system validates that the content uploaded matches the value of the header. You must encode MD5 headers in Base64, as described in . The `durability-level` header is a value from 1 to 6 that specifies how many copies of an object the system stores. If you do not specify a durability level, the default is

While you can set a durability-level of 1, doing so would put your data at a higher risk of loss. The system honors the standard HTTP conditional requests such as , , etc. Cross-Origin Resource Sharing headers are supported on a per object basis. If `access-control-allow-origin` is sent on a `PUT`, it can be a comma separated list of `origin` values. When a request is sent with the `origin` header, the list of values of the stored `access-control-allow-origin` header is processed and only the matching value is returned, if any. For example: $ echo "foo" | \ mput -q -H 'access-control-allow-origin: foo.com,bar.com' /:login/public/foo $ curl -is -X HEAD -H 'origin: foo.com' http://10.2.121.5/:login/public/foo HTTP/1.1 200 OK Connection: close Etag: f7c79088-d70d-4725-b716-7b85a40ede6a Last-Modified: Fri, 17 May 2013 20:04:51 GMT access-control-allow-origin: foo.com Content-MD5: 07BzhNET7exJ6qYjitX/AA== Durability-Level: 2 Content-Length: 4 Content-Type: application/octet-stream Date: Fri, 17 May 2013 20:05:58 GMT Server: Manta x-request-id: 30afb030-bf2d-11e2-be7d-99e967737d07 x-response-time: 7 x-server-name: fef8c5b8-3483-458f-95dc-7d9172ecefd1 If no `origin` header is sent, the system assumes that the request did not originate from a browser and the original list of values is echoed back. While this behavior does not conform to the CORS specification, it does allow you to administratively see what is stored on your object. `access-control-expose-headers` is supported as a list of HTTP headers that a browser will expose. This list is not interpreted by the system. `access-control-allow-methods` is supported as a list of HTTP methods that the system will honor for this request. You can only specify HTTP operations the system supports: HEAD, GET, PUT, DELETE. `access-control-max-age` is supported and uninterpreted by the system. The HTTP `cache-control` header is stored and returned by the system. This is useful for controlling how long CDNs or a web caching agent caches a version of an object. You can store custom headers with your object by prefixing them with `m-`. For example, you might use the header `m-local-user: jill` to tag an object with the name of the user who created it. You can use up to 4 KB of header data. Directories contain objects and other directories. All objects are stored at the top level or subdirectory one of the following directories: | Directory | Description | | - | -- | | `/:login/stor` | private object storage | | `/:login/public` | public object storage | As noted above, `/:login/stor` functions as the top level, or root, directory where you store objects and create directories. Only you can read, write, and delete data here. You can create any number of directories and objects in this directory. While the system does not yet support discretionary access controls on objects or directories, you can grant access to individual objects in this namespace by using signed URLs, which are explained

With the exception of signed URL requests, all traffic to `/:login/stor` must be made over a secure channel (TLS). `/:login/public` is a world-readable namespace. Only you can create and delete objects in this directory. Read access to objects in this namespace is available through HTTP and HTTPS without authorization headers. Deletions and writes to this directory must made over a secure channel. You create a directory the same way that you create an object, but you use the special header `Content-Type: application/json; type=directory`. When you retrieve a directory, the response has the `Content-Type: application/x-json-stream; type=directory` header. The body consists of a set of JSON objects separated by newlines (`\n`). Each object has a `type` field that indicates whether the JSON object specifies a directory or a storage object. Here is an example with additional newlines added for clarity. { "name": "1c1bf695-230d-490e-aec7-3b11dff8ef32", "type": "directory", "mtime": "2012-09-11T20:28:30Z" } { "name": "695d5de6-45f4-4156-b6b7-3a8d4af89391", "etag": "bdf0aa96e3bb87148be084252a059736", "size": 44, "type": "object", "mtime": "2012-09-11T20:28:31Z" } | Field | Description | | - | -- | | `type` | Either `object` or `directory`. | | `name` | The name of the object or directory. | | `mtime` | An of the last update time of the object or directory. | | `size` | Present only if `type` is `object`. The size of the object in bytes. | | `etag` | Present only if `type` is `object`. Used for conditional requests. | When you use an HTTP GET request to list a directory, the `result-set-size` header in the response contains the total number of entries in the directory. However, you will get 256 entries per request, so you will have to paginate through the result sets. You can increase the number of entries per request to 1024. Results are sorted lexicographically. To get the next page of a listing, pass in the last name returned in the set until the total number of entries you have processed matches `result-set-size`. You can store CORS, `cache-control` and `m-` headers on directories, as you can on objects. Currently, no data is supported on directories. This section describes some of the design principles that guide the operation of Manta. Several principles guide the design of the service: From the perspective of the , the system is strongly consistent. It chooses to be strongly consistent, at the risk of more HTTP 500 errors than an eventually consistent system. This system is engineered to minimize errors in the event of network or system failures and to recover as quickly as possible, but more errors will occur than in an eventually consistent system. However, it is possible to read the writes immediately. The distinction between a HTTP 404 response and a HTTP 500 response is very clear: A 404 response really means your data isn't

A 500 response means that it might be, but there is some sort of outage. When the system responds with an HTTP 200, you can be certain your data is durably stored on the number of servers you requested. The system is designed to never allow data loss or corruption. The system is designed to be secure. All writes must be performed over a secure channel (TLS). Most reads will be as well, unless you are specifically requesting to bypass TLS for browser/web channels. Manta is designed to support an arbitrarily large number of objects and an arbitrarily large number of directories. However, it bounds the number of objects in a single directory so that list operations can be performed efficiently. The system does not have any limit on the size of a single object, but it may return a "no space" error if the requested object size is larger than a single physical server has space for. In practice, this number will be in tens of terabytes, but network transfer times make object sizes of that magnitude unreasonable anyway. There is no default API rate limit imposed upon you, however the system reserves the right to throttle requests if necessary to protect the system. For high-volume web assets, you should use it as a content delivery network (CDN) origin. All REST APIs are modeled as streams. They are designed to let you iterate through result sets without consuming too much memory. For example, listing a directory returns newline separated JSON objects as opposed to an array or large XML document. At a simple level, durability is a system's ability to tolerate failures without a loss of data. By default, the system stores two copies of your object and these two copies are placed in two different data centers. Distributing copies of your objects reduces the risk of data loss in the event of a failure. The system relies on ZFS RAID-Z to store your objects, so the durability is actually greater than two would imply. You can store anywhere from 1 to 6 copies. You are billed for exactly the number of bytes you consume in the system. For example, if you write a 1MB object with the default number of copies (2), you will be billed for 2MB of storage each month. When the number of copies requested is greater than one, the system ensures that at least two copies are placed in two different data centers, and then stripes the other copies across data centers. If any given data center is down at the time, you may have copies unbalanced with extra replicas in fewer data centers, but there will always be at least two data centers with your copy of data. This allows you to still access your data in the event of any one data center failure.