A cluster’s files and directories can be accessed programmatically, and controlled by filesystem permissions, through the OneFS RESTful Access to Namespace (RAN) API, similarly to the way they’re accessed through the core NAS protocols such as NFS and SMB.
Within the RAN namespace, the following system attributes are common to directories and files:
Attribute | Description | Type |
name | Specifies the name of the object. | String |
size | Specifies the size of the object in bytes. | Integer |
block_size | Specifies the block size of the object. | Integer |
blocks | Specifies the number of blocks that compose the object. | Integer |
last_modified | Specifies the time when the object data was last modified in HTTP date/time format. | HTTP date |
create_time | Specifies the date when the object data was created in HTTP date/time format. | HTTP date |
access_time | Specifies the date when the object was last accessed in HTTP date/time format. | HTTP date |
change_time | Specifies the date when the object was last changed (including data and metadata changes) in HTTP date/time format. | String |
type | Specifies the object type, which can be one of the following values: container, object, pipe, character_device, block_device, symbolic_link, socket, or whiteout_file. | String |
mtime_val | Specifies the time when the object data was last modified in UNIX Epoch format. | Integer |
btime_val | Specifies the time when the object data was created in UNIX Epoch format. | Integer |
atime_val | Specifies the time when the object was last accessed in UNIX Epoch format. | Integer |
ctime_val | Specifies the time when the object was last changed (including data and metadata changes) in UNIX Epoch format. | Integer |
owner | Specifies the user name for the owner of the object. | String |
group | Specifies the group name for the owner of the object. | String |
uid | Specifies the UID for the owner. | Integer |
gid | Specifies the GID for the owner. | Integer |
mode | Specifies the UNIX mode octal number. | String |
id | Specifies the object ID, which is also the INODE number. | Integer |
nlink | Specifies the number of hard links to the object. | Integer |
is_hidden | Specifies whether the file is hidden or not. | Boolean |
In response, the following response headers may be returned when sending a request to RAN.
Attribute | Description | Type |
Content-length | Provides the length of the body message in the response. | Integer |
Connection | Provides the state of connection to the server. | String |
Date | Provides the date when the object store last responded. | HTTP-date |
Server | Provides platform and version information about the server that responded to the request. | String |
x-isi-ifs-target-type | Provides the resource type. This value can be a container or an object. | String |
For diagnostic and troubleshooting purposes, failed requests to the namespace can often be resolved via common error codes and viewing activity logs. Activity logs capture server and object activity and can help identify problems. The following table shows the location of different types of activity logs.
Log | Location |
Server logs |
· /var/log/<server>/webui_httpd_access.log |
Object Daemon Log | · /var/log/isi_object_d.log |
Generic Log | · /var/log/message |
For <server> above, the path to the server directory should be used. For example: /apache2.
The common JSON error is returned in the following format:
{ "errors":[ { "code":"<Error code>", "message":"<some detailed error msg>" } ] }
The following table includes the common error codes, plus their status and description:
Error Code | Description | HTTP status |
AEC_TRANSIENT | The specified request returned a transient error code that is treated as OK. | 200 OK |
AEC_BAD_REQUEST | The specified request returned a bad request error. | 400 Bad Request |
AEC_ARG_REQUIRED | The specified request requires an argument for the operation. | 400 Bad Request |
AEC_ARG_SINGLE_ONLY | The specified request requires only a single argument for the operation. | 400 Bad Request |
AEC_UNAUTHORIZED | The specified request requires user authentication. | 401 Unauthorized |
AEC_FORBIDDEN | The specified request was denied by the server. Typically, this response includes permission errors on OneFS. | 403 Forbidden |
AEC_NOT_FOUND | The specified request has a target object that was not found. | 404 Not Found |
AEC_METHOD_NOT_ALLOWED | The specified request sent a method that is not allowed for the target object. | 405 Method Not Allowed |
AEC_NOT_ACCEPTABLE | The specified request is unacceptable. | 406 Not Acceptable |
AEC_CONFLICT | The specified request has a conflict that prevents the operation from completing. | 409 Conflict |
AEC_PRE_CONDITION_FAILED | The specified request has failed a precondition. | 412 Precondition failed |
AEC_INVALID_REQUEST_RANGE | The specified request has requested a range that cannot be satisfied. | 416 Requested Range not Satisfiable |
AEC_NOT_MODIFIED | The specified request was not modified. | 304 Not Modified |
AEC_LIMIT_EXCEEDED | The specified request exceeded the limit set on the server side. | 403 Forbidden |
AEC_INVALID_LICENSE | The specified request has an invalid license. | 403 Forbidden |
AEC_NAMETOOLONG | The specified request has an object name size that is too long. | 403 Forbidden |
AEC_SYSTEM_INTERNAL_ERROR | The specified request has failed because the server encountered an unexpected condition. | 500 Internal Server Error |
For example, an invalid copy source path yields the ‘AEC_BAD_REQUEST’ code:
# curl -X PUT --insecure --basic --user <name>:<passwd> --header "clone=true" --header "x-isi-ifs-copy-source:/namespace/ifs/data-other/testfile1/" https://10.1.10.20:8080/namespace/ifs/data/testfile1/ { "errors" : [ { "code" : "AEC_BAD_REQUEST", "message" : "Unable to open object '/data-other/testfile1/' in store 'ifs' -- a component of the path is not a directory." } ] }
When crafting straightforward HTTP requests to RAN, such as create a file (object), the ‘curl’ CLI utility can be a useful asset:
# curl -X PUT --insecure --basic --user <username>:<passwd> -H "x-isi-ifs-target-type:object" https://<cluster_ip>:8080/namespace/<path>/<file>/
For example, to create ‘file1’ under ‘/ifs/data’:
# curl -X PUT --insecure --basic --user <username>:<passwd> -H "x-isi-ifs-target-type:object" https://10.1.10.20:8080/namespace/ifs/data/file1/ # ls -lsia /ifs/data/file1 6668484639 64 -rw------- 1 root wheel 0 Aug 28 00:58 /ifs/data/file1
And to read the contents of the file via RAN:
# echo "This is file1" > /ifs/data/file1 # curl -X GET --insecure --basic --user <username>:<passwd> https://10.1.10.20:8080/namespace/ifs/data/file1 This is file1
However, ‘curl’ and its ‘-H’ header option can quickly get unwieldy for more complex HTML requests, such as setting ACLs and configuring SmartLock immutability via RAN. As such, more versatile dev tools and/or scripting languages may be a better alternative in these cases. Plus, familiarity with HTTP/1.1 and experience writing HTTP-based client utilities is of considerable help when implementing RAN endpoints in production environments.
Next, are a couple of examples of more complex HTTP requests to RAN.
Set the ACL on a file
In the first instance, the following request syntax can be used to configure the access control list (ACL) of a file:
PUT /namespace/<access_point>/<container_path>/<file_name>?acl HTTP/1.1 Host: <hostname>[:<port>] Content-Length: <length> Date: <date> Authorization: <signature> x-isi-ifs-target-type: object Content-Type: application/json { "owner":{ "id":"<owner id>", "name":"<owner name>", "type":"<type>" }, "group":{ "id":"<group id>", "name":"<group name>", "type":"<type>" }, "authoritative":"acl"|"mode", "mode":"<POSIX mode>", "action":"<action_value>", "acl":[ { "trustee":{ "id":"<trustee id>", "name":"<trustee name>", "type":"<trustee type>" }, "accesstype":"allow"|"deny", "accessrights":"<accessrights_list>", "op":"<operation_value>" } ] }
The ACL endpoint parameters for RAN include:
Parameter | Description |
acl | The acl argument must be placed at the first position of the argument list in the URI. |
owner | Specifies the JSON object for the owner persona. You should only specify the owner or group persona if you want to change the owner or group of the target. |
group | Specifies the JSON object for the group persona of the owner. You should only specify the owner or group persona if you want to change the owner or group of the target. |
authoritative | The authoritative field is mandatory and can take the value of either acl or mode.
acl: You can modify the owner, group personas, or access rights for the file by setting the authoritative field to acl and by setting <action_value> to update. When the authoritative field is set to acl, access rights are set for the file from the acl structure. Any value that is specified for the mode parameter is ignored. Note: When the authoritative field is set to acl, the default value for the <action_value> field is replace. If the <action_value> field is set to replace, the system replaces the existing access rights of the file with the access rights that are specified in the acl structure. If the acl structure is empty, the existing access rights are deleted and default access rights are provided by the system. The default access rights for files are read access control list (‘std_read_dac’) and write access control list (‘std_write_dac’) for the owner. mode: You can modify the owner and group personas by setting the authoritative field to mode. When the authoritative field is set to mode, POSIX permissions are set on the file. The <action_value> field and acl structure are ignored. If mode is set on a file that already has access rights or if access rights are set on a file that already has POSIX permissions set, the result of the operation varies based on the Global ACL Policy. |
mode | Specifies the POSIX mode as an cctal number string. By default, these are 0700 for directories and 0600 for files. |
action | The <action_value> field is applied when the authoritative field is set to acl. You can set the <action_value> field to either update or replace. The default value is replace.
When set to update, the existing access control list of the file is modified with the access control entries that are specified in the acl structure of the JSON body. When set to replace, the entire access control list is deleted and replaced with the access control entries that are specified in the acl structure of the JSON body. Also, when set to replace, the acl structure is optional. If the acl structure is left empty, the entire access control list is deleted and replaced with the system set default access rights. The default access rights for files are read access control list (‘ std_read_dac’) and write access control list (‘ std_write_dac’) for the owner. |
acl | Specifies the JSON array of access rights. |
accesstype | Can be set to allow or deny.
allow: Allows access to the file based on the access rights set for the trustee. deny: Denies access to the file based on the access rights set for the trustee. |
accessrights | Specifies the access right values that are defined for the file. |
inherit_flags | Specifies the inherit flag values for the file. |
op | The <operation_value> field is applied when the <action_value> field is set to update. You can set the <operation_value> field to add, replace, or delete. If no <operation_value> field is specified, the default value is add.
add: Creates an access control entry (ACE) if an ACE is not already present for a trustee and trustee access type. If an entry is already present for that trustee and trustee access type, this operation appends the access rights list to the current ACE for that trustee and trustee access type. delete: Removes the access rights list provided from the existing ACE for a trustee and trustee access type. If the input access rights list is empty , the entire ACE that corresponds to the trustee and trustee access type is deleted. replace: Replaces the entire ACE for the trustee and trustee access type with the input access rights list. |
The following HTTP ‘put’ syntax can be used to set the ACL of a file, in this case ‘file1’.
PUT /namespace/ifs/dir1/dir2/ns/file1?acl HTTP/1.1 Host: my_cluster:8080 Content-Length: <length> Date: Tue, 22 May 2024 12:00:00 GMT Authorization: <signature> Content-Type: application/json { "owner":{ "id":"UID:0", "name":"root", "type":"user" }, "group":{ "id":"GID:0", "name”:"wheel", "type":"group" }, "authoritative":"acl", "action":"update", "acl": [ { "trustee":{ "id":"UID:0", "name":"root", "type":"user" }, "accesstype":"allow", "accessrights":[ "file_read", "file_write" ], "op":"add" }, { "trustee":{ "id":"GID:1201", "name":"group12", "type":"group" }, "accesstype":"allow", "accessrights":"std_write_dac" ], "op":"replace" } ] }
And the corresponding successful response from RAN is along the following lines:
HTTP/1.1 200 OK
Date: Tue, 22 May 2024 12:00:00 GMT
Content-Length: <length>
Connection: close
Server: Apache2/2.2.19
Set the retention period and commit a file in a SmartLock directory
Similarly, the following request syntax can be used to set the retention period and commits a file in a SmartLock directory.
PUT /namespace/<access_point>/<WORM_directory>/<file_name>?worm HTTP/1.1 Host: <hostname>[:<port>] Date: <date> Authorization: <signature> { "worm_retention_date":<"YYYY-MM-DD hh:mm:ss GMT">, "commit_to_worm":<Boolean> }
Note that if a file is not explicitly committed when an autocommit time period is configured for the SmartLock directory where the file resides, the file is automatically committed when the autocommit period elapses.
If the file is committed without setting a retention expiration date, the default retention period that is specified for the SmartLock directory where the file resides is applied. The retention date on the file can also be limited by the maximum retention period set on the SmartLock directory.
The pertinent WORM endpoint parameters in RAN include:
Parameter | Description |
Parameter | Description |
worm | The worm argument must be placed at the first position of the argument list in the URI. |
worm_committed | Indicates whether the file was committed to the WORM state. |
worm_retention_date | Provides the retention expiration date in Coordinated Universal Time (such as UTC/GMT). If a value is not specified, the field has a null value. |
worm_retention_date_val | Provides the retention expiration date in seconds from UNIX Epoch or UTC. |
worm_override_retention_date | Provides the override retention date that is set on the SmartLock directory where the file resides. If the date is not set or is earlier than or equal to the existing file retention date, this field has a null value. Otherwise, the date is expressed in UTC/GMT, and is the retention expiration date for the file if the worm_committed parameter is also set to true. |
worm_override_retention_date_val | Provides the override retention date that is set on the SmartLock directory where the file resides. If the date is not set or if the date is set to earlier than or equal to the file retention date, this field has a null value. Otherwise, the date is expressed in seconds from UNIX Epoch and UTC, and is the retention expiration date set for the file if the worm_committed parameter is set to true. This parameter is the same as worm_override_retention_date, but is expressed in seconds from the Epoch or UTC. |
For example, the following request will set the retention date for a ‘file1’ in the SmartLock directory ‘dir1’ to 25th December 2024:
PUT /namespace/ifs/dir1/file1?worm HTTP/1.1 Host: my_cluster:8080 Date: Wed, 25 Dec 2024 12:00:00 GMT Authorization: <signature> { "worm_retention_date":"2024-12-25 12:00:00 GMT", "commit_to_worm":true }
And the corresponding successful response:
HTTP/1.1 200 OK Date: Tue, 25 Dec 2024 12:00:00 GMT Content-Length: 0 Connection: close Server: Apache2/2.2.19