diff --git a/config.js b/config.js index 3556e7f175..057864f62c 100644 --- a/config.js +++ b/config.js @@ -196,6 +196,14 @@ config.STS_CORS_EXPOSE_HEADERS = 'ETag'; config.DENY_UPLOAD_TO_STORAGE_CLASS_STANDARD = false; +/** + * NSFS_GLACIER_FORCE_STORAGE_CLASS when set to true + * will force `GLACIER` storage class if no storage class + * is provided and if `STANDARD` storage class is provided + * @type {boolean} + */ +config.NSFS_GLACIER_FORCE_STORAGE_CLASS = false; + // S3_RESTORE_MAX_DAYS controls that for how many maximum number // of days an object can be restored using `restore-object` call. config.S3_RESTORE_REQUEST_MAX_DAYS = 30; diff --git a/src/endpoint/s3/s3_rest.js b/src/endpoint/s3/s3_rest.js index eff8e68923..f3cf4187e0 100755 --- a/src/endpoint/s3/s3_rest.js +++ b/src/endpoint/s3/s3_rest.js @@ -107,6 +107,9 @@ async function handle_request(req, res) { } http_utils.check_headers(req, headers_options); + // Will override the storage class if configured + s3_utils.override_storage_class(req); + const redirect = await populate_request_additional_info_or_redirect(req); if (redirect) { res.setHeader('Location', redirect); diff --git a/src/endpoint/s3/s3_utils.js b/src/endpoint/s3/s3_utils.js index 17cee60531..16a1df028c 100644 --- a/src/endpoint/s3/s3_utils.js +++ b/src/endpoint/s3/s3_utils.js @@ -20,6 +20,8 @@ const STORAGE_CLASS_STANDARD = 'STANDARD'; const STORAGE_CLASS_GLACIER = 'GLACIER'; // "S3 Glacier Flexible Retrieval" /** @type {nb.StorageClass} */ const STORAGE_CLASS_GLACIER_IR = 'GLACIER_IR'; // "S3 Glacier Instant Retrieval" +/** @type {nb.StorageClass} */ +const STORAGE_CLASS_GLACIER_DA = 'GLACIER_DA'; // "DBS3 specific Storage Class" const DEFAULT_S3_USER = Object.freeze({ ID: '123', @@ -382,6 +384,7 @@ function parse_storage_class(storage_class) { if (!storage_class) return STORAGE_CLASS_STANDARD; if (storage_class === STORAGE_CLASS_STANDARD) return STORAGE_CLASS_STANDARD; if (storage_class === STORAGE_CLASS_GLACIER) return STORAGE_CLASS_GLACIER; + if (storage_class === STORAGE_CLASS_GLACIER_DA) return STORAGE_CLASS_GLACIER_DA; if (storage_class === STORAGE_CLASS_GLACIER_IR) return STORAGE_CLASS_GLACIER_IR; throw new Error(`No such s3 storage class ${storage_class}`); } @@ -819,9 +822,19 @@ function parse_body_public_access_block(req) { return parsed; } +function override_storage_class(req) { + if ( + config.NSFS_GLACIER_FORCE_STORAGE_CLASS && + parse_storage_class_header(req) === STORAGE_CLASS_STANDARD + ) { + req.headers['x-amz-storage-class'] = STORAGE_CLASS_GLACIER; + } +} + exports.STORAGE_CLASS_STANDARD = STORAGE_CLASS_STANDARD; exports.STORAGE_CLASS_GLACIER = STORAGE_CLASS_GLACIER; exports.STORAGE_CLASS_GLACIER_IR = STORAGE_CLASS_GLACIER_IR; +exports.STORAGE_CLASS_GLACIER_DA = STORAGE_CLASS_GLACIER_DA; exports.DEFAULT_S3_USER = DEFAULT_S3_USER; exports.DEFAULT_OBJECT_ACL = DEFAULT_OBJECT_ACL; exports.decode_chunked_upload = decode_chunked_upload; @@ -863,5 +876,6 @@ exports.key_marker_to_cont_tok = key_marker_to_cont_tok; exports.parse_sse_c = parse_sse_c; exports.verify_string_byte_length = verify_string_byte_length; exports.parse_body_public_access_block = parse_body_public_access_block; +exports.override_storage_class = override_storage_class; exports.OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES; exports.OBJECT_ATTRIBUTES_UNSUPPORTED = OBJECT_ATTRIBUTES_UNSUPPORTED; diff --git a/src/sdk/namespace_fs.js b/src/sdk/namespace_fs.js index 2836b3cf17..a63bad90b3 100644 --- a/src/sdk/namespace_fs.js +++ b/src/sdk/namespace_fs.js @@ -3612,11 +3612,15 @@ class NamespaceFS { } async _is_storage_class_supported(storage_class) { + const glacier_storage_classes = [ + s3_utils.STORAGE_CLASS_GLACIER, + s3_utils.STORAGE_CLASS_GLACIER_DA, + s3_utils.STORAGE_CLASS_GLACIER_IR, + ]; + if (!storage_class || storage_class === s3_utils.STORAGE_CLASS_STANDARD) return true; - if (storage_class === s3_utils.STORAGE_CLASS_GLACIER) { - // TODO: Upon integration with underlying systems, we should - // check if archiving is actually supported or not + if (glacier_storage_classes.includes(storage_class)) { return config.NSFS_GLACIER_ENABLED || false; } diff --git a/src/sdk/nb.d.ts b/src/sdk/nb.d.ts index 0541b68f98..df7d37f4d2 100644 --- a/src/sdk/nb.d.ts +++ b/src/sdk/nb.d.ts @@ -17,7 +17,7 @@ type DigestType = 'sha1' | 'sha256' | 'sha384' | 'sha512'; type CompressType = 'snappy' | 'zlib'; type CipherType = 'aes-256-gcm'; type ParityType = 'isa-c1' | 'isa-rs' | 'cm256'; -type StorageClass = 'STANDARD' | 'GLACIER' | 'GLACIER_IR'; +type StorageClass = 'STANDARD' | 'GLACIER' | 'GLACIER_IR' | 'GLACIER_DA'; type ResourceType = 'HOSTS' | 'CLOUD' | 'INTERNAL'; type NodeType = 'BLOCK_STORE_S3' |