multipart_sync_threshold: number;
host_style: string;
retain_head_object: boolean;
-}
-
-export interface S3Details {
- endpoint: string;
- access_key: string;
- storage_class: string;
- target_path: string;
- target_storage_class: string;
- region: string;
- secret: string;
- multipart_min_part_size: number;
- multipart_sync_threshold: number;
- host_style: boolean;
+ allow_read_through: boolean;
}
export interface TierTarget {
storage_class: string;
tier_type: string;
retain_head_object: boolean;
+ allow_read_through: boolean;
s3: S3Details;
};
}
tier_targets: TierTarget[];
}
-export interface StorageClassDetails {
- target_path: string;
- access_key: string;
- secret: string;
- multipart_min_part_size: number;
- multipart_sync_threshold: number;
- host_style: string;
-}
-
export interface ZoneGroup {
name: string;
id: string;
multipart_sync_threshold: number;
host_style: boolean;
retain_head_object?: boolean;
+ allow_read_through?: boolean;
}
export interface RequestModel {
zone_group: string;
secret: string;
target_path: string;
retain_head_object: boolean;
+ allow_read_through: boolean;
region: string;
multipart_sync_threshold: number;
multipart_min_part_size: number;
export const CLOUD_TIER = 'cloud-s3';
export const DEFAULT_PLACEMENT = 'default-placement';
+
+export const ALLOW_READ_THROUGH_TEXT =
+ 'Enables fetching objects from remote cloud S3 if not found locally.';
+
+export const MULTIPART_MIN_PART_TEXT =
+ 'It specifies that objects this size or larger are transitioned to the cloud using multipart upload.';
+
+export const MULTIPART_SYNC_THRESHOLD_TEXT =
+ 'It specifies the minimum part size to use when transitioning objects using multipart upload.';
+
+export const TARGET_PATH_TEXT =
+ 'Target Path refers to the storage location (e.g., bucket or container) in the cloud where data will be stored.';
+
+export const TARGET_REGION_TEXT =
+ 'The region of the remote cloud service where storage is located.';
+
+export const TARGET_ENDPOINT_TEXT =
+ 'The URL endpoint of the remote cloud service for accessing storage.';
+
+export const TARGET_ACCESS_KEY_TEXT =
+ "To view or copy your access key, go to your cloud service's user management or credentials section, find your user profile, and locate the access key. You can view and copy the key by following the instructions provided.";
+
+export const TARGET_SECRET_KEY_TEXT =
+ "To view or copy your secret key, go to your cloud service's user management or credentials section, find your user profile, and locate the secret key. You can view and copy the key by following the instructions provided.";
+
+export const RETAIN_HEAD_OBJECT_TEXT = 'Retain object metadata after transition to the cloud.';
+
+export const HOST_STYLE = `The URL format for accessing the remote S3 endpoint:
+ - 'Path': Use for a path-based URL
+ - 'Virtual': Use for a domain-based URL`;
Target Path
<cd-helper class="text-pre-wrap">
<span i18n>
- The target path specifies a prefix to which the source bucket-name/object-name is
- appended.
+ {{ targetPathText }}
</span>
</cd-helper>
</td>
Access key
<cd-helper class="text-pre-wrap">
<span i18n>
- Access key is the remote cloud S3 access key used for a specific connection.
+ {{ targetAccessKeyText }}
</span>
</cd-helper>
</td>
<td class="bold">
Secret key
<cd-helper class="text-pre-wrap">
- <span i18n> Secret is the secret key for the remote cloud S3 service. </span>
+ <span i18n> {{ targetSecretKeyText }} </span>
</cd-helper>
</td>
<td>
</td>
</tr>
<tr>
- <td
- class="bold">
+ <td class="bold">
Host Style
<cd-helper class="text-pre-wrap">
- <span i18n>The URL format for accessing the remote S3 endpoint: 'Path' for a path-based URL
- or 'Virtual' for a domain-based URL.</span>
+ <span i18n>{{ hostStyleText }}</span
+ >
</cd-helper>
</td>
<td>{{ selection?.host_style }}</td>
</tr>
<tr>
- <td
- class="bold">
+ <td class="bold">
Multipart Minimum Part Size
<cd-helper class="text-pre-wrap">
<span i18n>
- Minimum parts size to use when transitioning objects using multipart upload.
+ {{ multipartMinPartText }}
</span>
</cd-helper>
</td>
<td>{{ selection?.multipart_min_part_size }}</td>
</tr>
<tr>
- <td
- class="bold">
+ <td class="bold">
Multipart Sync Threshold
<cd-helper class="text-pre-wrap">
<span i18n>
- Objects this size or larger will be transitioned to the cloud using multipart
- upload.
+ {{ multipartSyncThreholdText }}
</span>
</cd-helper>
</td>
<td>{{ selection?.multipart_sync_threshold }}</td>
</tr>
<tr>
- <td
- class="bold">
- Retain Head Object
+ <td class="bold">
+ <span i18n>Allow Read Through </span>
+ <cd-helper class="text-pre-wrap">
+ <span i18n>
+ {{ allowReadThroughText }}
+ </span>
+ </cd-helper>
+ </td>
+ <td>{{ selection?.allow_read_through }}</td>
+ </tr>
+ <tr>
+ <td class="bold">
+ Head Object (Stub File)
<cd-helper class="text-pre-wrap">
<span i18n>
- Retain object metadata after transition to the cloud (default: false).
+ {{ retainHeadObjectText }}
</span>
</cd-helper>
</td>
multipart_min_part_size: 100,
multipart_sync_threshold: 200,
host_style: 'path',
- retain_head_object: true
+ retain_head_object: true,
+ allow_read_through: true
};
component.selection = mockSelection;
component.ngOnChanges();
import { Component, Input, OnChanges } from '@angular/core';
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
-import { StorageClassDetails } from '../models/rgw-storage-class.model';
+import {
+ ALLOW_READ_THROUGH_TEXT,
+ HOST_STYLE,
+ MULTIPART_MIN_PART_TEXT,
+ MULTIPART_SYNC_THRESHOLD_TEXT,
+ RETAIN_HEAD_OBJECT_TEXT,
+ StorageClassDetails,
+ TARGET_ACCESS_KEY_TEXT,
+ TARGET_PATH_TEXT,
+ TARGET_SECRET_KEY_TEXT
+} from '../models/rgw-storage-class.model';
@Component({
selector: 'cd-rgw-storage-class-details',
selection: StorageClassDetails;
columns: CdTableColumn[] = [];
storageDetails: StorageClassDetails;
+ allowReadThroughText = ALLOW_READ_THROUGH_TEXT;
+ retainHeadObjectText = RETAIN_HEAD_OBJECT_TEXT;
+ multipartMinPartText = MULTIPART_MIN_PART_TEXT;
+ multipartSyncThreholdText = MULTIPART_SYNC_THRESHOLD_TEXT;
+ targetAccessKeyText = TARGET_ACCESS_KEY_TEXT;
+ targetSecretKeyText = TARGET_SECRET_KEY_TEXT;
+ targetPathText = TARGET_PATH_TEXT;
+ hostStyleText = HOST_STYLE;
ngOnChanges() {
if (this.selection) {
multipart_min_part_size: this.selection.multipart_min_part_size,
multipart_sync_threshold: this.selection.multipart_sync_threshold,
host_style: this.selection.host_style,
- retain_head_object: this.selection.retain_head_object
+ retain_head_object: this.selection.retain_head_object,
+ allow_read_through: this.selection.allow_read_through
};
}
}
placeholder="e.g, us-east-1"
i18n-placeholder
[invalid]="
- storageClassForm.showError('region', formDir, 'required')
- "
- />
+ storageClassForm.showError('region', formDir, 'required')"/>
</cds-text-label>
<ng-template #regionError>
<span
>
</ng-template>
</div>
+ <div class="form-item">
+ <cds-checkbox
+ id="allow_read_through"
+ formControlName="allow_read_through"
+ cdOptionalField="Allow Read Through"
+ i18n
+ (change)="onAllowReadThroughChange($event)"
+ >Allow Read Through
+ <cd-help-text>{{ allowReadThroughText }}</cd-help-text>
+ </cds-checkbox>
+ </div>
+ <div class="form-item">
+ <cds-checkbox
+ id="retain_head_object"
+ formControlName="retain_head_object"
+ cdOptionalField="Head Object (Stub File)"
+ i18n
+ >Head Object (Stub File)
+ <cd-help-text>{{ retainHeadObjectText }}</cd-help-text>
+ </cds-checkbox>
+ </div>
<fieldset>
<cds-accordion size="lg"
</cds-text-label>
</div>
</div>
- <div class="form-item">
- <cds-checkbox
- id="retain_head_object"
- formControlName="retain_head_object"
- cdOptionalField="Retain Head Object"
- i18n-label
- >Retain Head Object
- <cd-help-text>{{ retainHeadObjectText }}</cd-help-text>
- </cds-checkbox>
- </div>
</cds-accordion-item>
</cds-accordion>
<ng-template #title>
storage_class: 'CLOUDIBM',
tier_type: 'cloud-s3',
retain_head_object: true,
+ allow_read_through: true,
s3: {
endpoint: 'https://s3.amazonaws.com',
access_key: 'ACCESSKEY',
storage_class: 'CloudIBM',
tier_type: 'cloud-s3',
retain_head_object: true,
+ allow_read_through: true,
s3: {
endpoint: 'https://s3.amazonaws.com',
access_key: 'ACCESSKEY',
component.storageClassForm.get('secret_key').setValue('secretkey');
component.storageClassForm.get('target_path').setValue('/target');
component.storageClassForm.get('retain_head_object').setValue(true);
+ component.storageClassForm.get('allow_read_through').setValue(true);
component.storageClassForm.get('region').setValue('useast1');
component.storageClassForm.get('multipart_sync_threshold').setValue(1024);
component.storageClassForm.get('multipart_min_part_size').setValue(256);
import { RgwStorageClassService } from '~/app/shared/api/rgw-storage-class.service';
import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
import {
+ ALLOW_READ_THROUGH_TEXT,
CLOUD_TIER,
DEFAULT_PLACEMENT,
+ MULTIPART_MIN_PART_TEXT,
+ MULTIPART_SYNC_THRESHOLD_TEXT,
PlacementTarget,
RequestModel,
+ RETAIN_HEAD_OBJECT_TEXT,
StorageClass,
Target,
+ TARGET_ACCESS_KEY_TEXT,
+ TARGET_ENDPOINT_TEXT,
+ TARGET_PATH_TEXT,
+ TARGET_REGION_TEXT,
+ TARGET_SECRET_KEY_TEXT,
TierTarget,
ZoneGroup,
ZoneGroupDetails
retainHeadObjectText: string;
storageClassInfo: StorageClass;
tierTargetInfo: TierTarget;
+ allowReadThroughText: string;
+ allowReadThrough: boolean = false;
constructor(
public actionLabels: ActionLabelsI18n,
}
ngOnInit() {
- this.multipartMinPartText =
- 'It specifies that objects this size or larger are transitioned to the cloud using multipart upload.';
- this.multipartSyncThreholdText =
- 'It specifies the minimum part size to use when transitioning objects using multipart upload.';
- this.targetPathText =
- 'Target Path refers to the storage location (e.g., bucket or container) in the cloud where data will be stored.';
- this.targetRegionText = 'The region of the remote cloud service where storage is located.';
- this.targetEndpointText = 'The URL endpoint of the remote cloud service for accessing storage.';
- this.targetAccessKeyText =
- "To view or copy your access key, go to your cloud service's user management or credentials section, find your user profile, and locate the access key. You can view and copy the key by following the instructions provided.";
-
- this.targetSecretKeyText =
- "To view or copy your secret key, go to your cloud service's user management or credentials section, find your user profile, and locate the access key. You can view and copy the key by following the instructions provided.";
- this.retainHeadObjectText =
- 'Retain object metadata after transition to the cloud (default: false).';
+ this.multipartMinPartText = MULTIPART_MIN_PART_TEXT;
+ this.multipartSyncThreholdText = MULTIPART_SYNC_THRESHOLD_TEXT;
+ this.targetPathText = TARGET_PATH_TEXT;
+ this.targetRegionText = TARGET_REGION_TEXT;
+ this.targetEndpointText = TARGET_ENDPOINT_TEXT;
+ this.targetAccessKeyText = TARGET_ACCESS_KEY_TEXT;
+ this.targetSecretKeyText = TARGET_SECRET_KEY_TEXT;
+ this.retainHeadObjectText = RETAIN_HEAD_OBJECT_TEXT;
+ this.allowReadThroughText = ALLOW_READ_THROUGH_TEXT;
this.createForm();
this.loadingReady();
this.loadZoneGroup();
this.storageClassForm
.get('multipart_min_part_size')
.setValue(response.multipart_min_part_size || '');
+ this.storageClassForm
+ .get('allow_read_through')
+ .setValue(this.tierTargetInfo?.val?.allow_read_through || false);
});
}
+ this.storageClassForm.get('allow_read_through').valueChanges.subscribe((value) => {
+ this.onAllowReadThroughChange(value);
+ });
}
createForm() {
target_path: new FormControl('', {
validators: [Validators.required]
}),
- retain_head_object: new FormControl(false),
+ retain_head_object: new FormControl(true),
multipart_sync_threshold: new FormControl(33554432),
- multipart_min_part_size: new FormControl(33554432)
+ multipart_min_part_size: new FormControl(33554432),
+ allow_read_through: new FormControl(false)
});
}
return tierTarget;
}
+ onAllowReadThroughChange(checked: boolean): void {
+ this.allowReadThrough = checked;
+ if (this.allowReadThrough) {
+ this.storageClassForm.get('retain_head_object')?.setValue(true);
+ this.storageClassForm.get('retain_head_object')?.disable();
+ } else {
+ this.storageClassForm.get('retain_head_object')?.enable();
+ }
+ }
+
buildRequest() {
const rawFormValue = _.cloneDeep(this.storageClassForm.value);
const zoneGroup = this.storageClassForm.get('zonegroup').value;
const storageClass = this.storageClassForm.get('storage_class').value;
const placementId = this.storageClassForm.get('placement_target').value;
+ const headObject = this.storageClassForm.get('retain_head_object').value;
const requestModel: RequestModel = {
zone_group: zoneGroup,
placement_targets: [
access_key: rawFormValue.access_key,
secret: rawFormValue.secret_key,
target_path: rawFormValue.target_path,
- retain_head_object: rawFormValue.retain_head_object,
+ retain_head_object: headObject,
+ allow_read_through: rawFormValue.allow_read_through,
region: rawFormValue.region,
multipart_sync_threshold: rawFormValue.multipart_sync_threshold,
multipart_min_part_size: rawFormValue.multipart_min_part_size
placement_target: targetName,
storage_class: tierTarget.val.storage_class,
retain_head_object: tierTarget.val.retain_head_object,
+ allow_read_through: tierTarget.val.allow_read_through,
...tierTarget.val.s3
};
}
secret: 'test56',
target_path: 'tsest-dnyanee',
retain_head_object: false,
+ allow_read_through: true,
region: 'ams3d',
multipart_sync_threshold: 33554432,
multipart_min_part_size: 33554432