zonegroup_name?: string;
}
-export interface StorageClassDetails {
- target_path: string;
- access_key: string;
- secret: string;
- multipart_min_part_size: number;
- multipart_sync_threshold: number;
- host_style: string;
- retain_head_object: boolean;
- allow_read_through: boolean;
-}
-
export interface TierTarget {
key: string;
val: {
tier_type: string;
retain_head_object: boolean;
allow_read_through: boolean;
+ read_through_restore_days: number;
+ restore_storage_class: string;
s3?: S3Details;
+ 's3-glacier': S3Glacier;
};
}
}
export interface StorageClassDetails {
+ tier_type: string;
target_path: string;
access_key: string;
secret: string;
multipart_min_part_size: number;
multipart_sync_threshold: number;
host_style: string;
+ allow_read_through: boolean;
zonegroup_name?: string;
placement_targets?: string;
+ glacier_restore_days?: number;
+ glacier_restore_tier_type?: string;
+ read_through_restore_days?: number;
+ restore_storage_class?: string;
+ retain_head_object?: boolean;
}
export interface ZoneGroup {
retain_head_object?: boolean;
allow_read_through?: boolean;
}
+export interface S3Glacier {
+ glacier_restore_days: number;
+ glacier_restore_tier_type: string;
+}
+
export interface RequestModel {
zone_group: string;
placement_targets: PlacementTarget[];
}
export interface PlacementTarget {
- tags: string[];
+ tags?: string[];
placement_id: string;
tier_type?: TIER_TYPE;
tier_config?: {
region: string;
multipart_sync_threshold: number;
multipart_min_part_size: number;
+ glacier_restore_days?: number;
+ glacier_restore_tier_type?: string;
+ restore_storage_class?: string;
+ read_through_restore_days?: number;
};
storage_class?: string;
name?: string;
tier_targets?: TierTarget[];
}
+export interface StorageClassOption {
+ value: string;
+ label: string;
+}
+
+export interface TextLabels {
+ targetPathText: string;
+ targetEndpointText: string;
+ targetRegionText: string;
+ multipartMinPartText: string;
+ storageClassText: string;
+ multipartSyncThresholdText: string;
+ targetSecretKeyText: string;
+ targetAccessKeyText: string;
+ retainHeadObjectText: string;
+ allowReadThroughText: string;
+ glacierRestoreDayText: string;
+ glacierRestoreTiertypeText: string;
+ tiertypeText: string;
+ restoreDaysText: string;
+ readthroughrestoreDaysText: string;
+ restoreStorageClassText: string;
+}
+
export const TIER_TYPE = {
LOCAL: 'local',
CLOUD_TIER: 'cloud-s3',
GLACIER: 'cloud-s3-glacier'
} as const;
+export const STORAGE_CLASS_CONSTANTS = {
+ DEFAULT_GLACIER_RESTORE_DAYS: 1,
+ DEFAULT_READTHROUGH_RESTORE_DAYS: 1,
+ DEFAULT_MULTIPART_SYNC_THRESHOLD: 33554432,
+ DEFAULT_MULTIPART_MIN_PART_SIZE: 33554432,
+ DEFAULT_STORAGE_CLASS: 'Standard'
+} as const;
+
export const DEFAULT_PLACEMENT = 'default-placement';
+export type TIER_TYPE = typeof TIER_TYPE[keyof typeof TIER_TYPE];
+
+export const TIER_TYPE_DISPLAY = {
+ LOCAL: 'Local',
+ CLOUD_TIER: 'Cloud S3',
+ GLACIER: 'Cloud S3 Glacier'
+};
+
export const ALLOW_READ_THROUGH_TEXT =
'Enables fetching objects from remote cloud S3 if not found locally.';
export const CLOUDS3_STORAGE_CLASS_TEXT = $localize`Cloud S3 storage uses Amazon S3-compatible cloud services for tiering.`;
-export type TIER_TYPE = typeof TIER_TYPE[keyof typeof TIER_TYPE];
+export const GLACIER_STORAGE_CLASS_TEXT = $localize`Glacier storage uses Amazon S3 Glacier for low-cost, long-term archival data storage.`;
-export const TIER_TYPE_DISPLAY = {
- LOCAL: 'Local',
- CLOUD_TIER: 'Cloud S3',
- GLACIER: 'Cloud S3 Glacier'
-};
+export const GLACIER_RESTORE_DAY_TEXT = $localize`Refers to number of days to the object will be restored on glacier/tape endpoint.`;
+
+export const GLACIER_RESTORE_TIER_TYPE_TEXT = $localize`Restore retrieval type.`;
+
+export const STANDARD_TIER_TYPE_TEXT = $localize`Standard glacier restore tier type restores data in 3–5 hours.`;
+
+export const EXPEDITED_TIER_TYPE_TEXT = $localize`Expedited glacier restore tier type restores in 1–5 minutes (faster but costlier).`;
+
+export const RESTORE_DAYS_TEXT = $localize`Refers to number of days to the object will be restored on glacier/tape endpoint.`;
+
+export const READTHROUGH_RESTORE_DAYS_TEXT = $localize`The duration for which objects restored via read-through are retained.`;
+
+export const RESTORE_STORAGE_CLASS_TEXT = $localize`The storage class to which object data is to be restored.`;
+
+export const ZONEGROUP_TEXT = $localize`A Zone Group is a logical grouping of one or more zones that share the same data
+ and metadata, allowing for multi-site replication and geographic distribution of
+ data.`;
data-testid="rgw-storage-details"
>
<tbody>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.LOCAL">
+ @if( isTierMatch(
+ TIER_TYPE_DISPLAY.LOCAL
+ )){
+ <tr>
<td class="bold"
i18n>
Zone Group
<cd-helper class="text-pre-wrap">
<span>
- A Zone Group is a logical grouping of one or more zones that share the same data
- and metadata, allowing for multi-site replication and geographic distribution of
- data.
+ {{ zoneGroupText }}
</span>
</cd-helper>
</td>
<td>{{ selection?.zonegroup_name }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.LOCAL">
+ }
+ @if(isTierMatch(
+ TIER_TYPE_DISPLAY.LOCAL
+ )){
+ <tr>
<td class="bold"
i18n>
Placement Target
</td>
<td>{{ selection?.placement_target }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
<td class="bold"
i18n>
Target Path
<cd-helper class="text-pre-wrap">
<span>
- {{ targetPathText }}
+ {{ targetPathText }}
</span>
</cd-helper>
</td>
<td>{{ selection?.target_path }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch(TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
<td class="bold"
i18n>
Access key
</div>
</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch(TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
<td class="bold"
i18n>
Secret key
</div>
</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
<td class="bold"
i18n>
Host Style
</td>
<td>{{ selection?.host_style }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
<td class="bold"
i18n>
- Multipart Minimum Part Size
+ Head Object (Stub File)
+ <cd-helper class="text-pre-wrap">
+ <span> {{ retainHeadObjectText }}</span>
+ </cd-helper>
+ </td>
+ <td>{{ selection?.retain_head_object ? 'Enabled' : 'Disabled' }}</td>
+ </tr>
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
+ <td class="bold"
+ i18n>
+ Allow Read Through
<cd-helper class="text-pre-wrap">
<span>
- {{ multipartMinPartText }}
+ {{ allowReadThroughText }}
</span>
</cd-helper>
</td>
- <td>{{ selection?.multipart_min_part_size }}</td>
+ <td>{{ selection?.allow_read_through ? 'Enabled' : 'Disabled' }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch(TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER) && (selection?.allow_read_through)) {
+ <tr *ngIf="isTierMatch(TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER) && (selection?.allow_read_through)">
<td class="bold"
i18n>
- Multipart Sync Threshold
+ Read through Restore Days
<cd-helper class="text-pre-wrap">
<span>
- {{ multipartSyncThreholdText }}
+ {{ readthroughrestoreDaysText }}
</span>
</cd-helper>
</td>
- <td>{{ selection?.multipart_sync_threshold }}</td>
+ <td>{{ selection?.read_through_restore_days }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
<td class="bold"
i18n>
- Retain Head Object
+ Glacier Restore Days
<cd-helper class="text-pre-wrap">
<span>
- Retain object metadata after transition to the cloud (default: false).
+ {{ glacierRestoreDayText }}
</span>
</cd-helper>
</td>
- <td>{{ selection?.retain_head_object }}</td>
+ <td>{{ selection?.glacier_restore_days }}</td>
</tr>
- <tr *ngIf="selection.tier_type === TIER_TYPE_DISPLAY.CLOUD_TIER">
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.GLACIER)) {
+ <tr>
<td class="bold"
i18n>
- Allow Read Through
+ Glacier Restore Tier Type
<cd-helper class="text-pre-wrap">
<span>
- {{ allowReadThroughText }}
+ {{ glacierRestoreTiertypeText }}
+ </span>
+ </cd-helper>
+ </td>
+ <td>{{ selection?.glacier_restore_tier_type }}</td>
+ </tr>
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
+ <td class="bold"
+ i18n>
+ Restore Storage Class
+ <cd-helper class="text-pre-wrap">
+ <span>
+ {{ restoreStorageClassText }}
+ </span>
+ </cd-helper>
+ </td>
+ <td>{{ selection?.restore_storage_class }}</td>
+ </tr>
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
+ <td class="bold"
+ i18n>
+ Multipart Minimum Part Size
+ <cd-helper class="text-pre-wrap">
+ <span>
+ {{ multipartMinPartText }}
</span>
</cd-helper>
</td>
- <td>{{ selection?.allow_read_through }}</td>
+ <td>{{ selection?.multipart_min_part_size }}</td>
+ </tr>
+ }
+ @if(isTierMatch( TIER_TYPE_DISPLAY.CLOUD_TIER, TIER_TYPE_DISPLAY.GLACIER)){
+ <tr>
+ <td class="bold"
+ i18n>
+ Multipart Sync Threshold
+ <cd-helper class="text-pre-wrap">
+ <span>
+ {{ multipartSyncThreholdText }}
+ </span>
+ </cd-helper>
+ </td>
+ <td>{{ selection?.multipart_sync_threshold }}</td>
</tr>
+ }
</tbody>
</table>
</cds-tab>
multipart_sync_threshold: 200,
host_style: 'path',
retain_head_object: true,
- allow_read_through: true
+ allow_read_through: true,
+ tier_type: 'local'
};
component.selection = mockSelection;
component.ngOnChanges();
TARGET_ACCESS_KEY_TEXT,
TARGET_PATH_TEXT,
TARGET_SECRET_KEY_TEXT,
- TIER_TYPE_DISPLAY
+ TIER_TYPE_DISPLAY,
+ TIER_TYPE,
+ GLACIER_RESTORE_DAY_TEXT,
+ GLACIER_RESTORE_TIER_TYPE_TEXT,
+ RESTORE_DAYS_TEXT,
+ READTHROUGH_RESTORE_DAYS_TEXT,
+ RESTORE_STORAGE_CLASS_TEXT,
+ ZONEGROUP_TEXT
} from '../models/rgw-storage-class.model';
@Component({
selector: 'cd-rgw-storage-class-details',
targetPathText = TARGET_PATH_TEXT;
hostStyleText = HOST_STYLE;
TIER_TYPE_DISPLAY = TIER_TYPE_DISPLAY;
+ TIER_TYPE = TIER_TYPE;
+ glacierRestoreDayText = GLACIER_RESTORE_DAY_TEXT;
+ glacierRestoreTiertypeText = GLACIER_RESTORE_TIER_TYPE_TEXT;
+ restoreDaysText = RESTORE_DAYS_TEXT;
+ readthroughrestoreDaysText = READTHROUGH_RESTORE_DAYS_TEXT;
+ restoreStorageClassText = RESTORE_STORAGE_CLASS_TEXT;
+ zoneGroupText = ZONEGROUP_TEXT;
ngOnChanges() {
if (this.selection) {
access_key: this.selection.access_key,
secret: this.selection.secret,
target_path: this.selection.target_path,
+ tier_type: this.selection.tier_type,
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,
- allow_read_through: this.selection.allow_read_through
+ allow_read_through: this.selection.allow_read_through,
+ glacier_restore_days: this.selection.glacier_restore_days,
+ glacier_restore_tier_type: this.selection.glacier_restore_tier_type,
+ restore_storage_class: this.selection.restore_storage_class,
+ read_through_restore_days: this.selection.read_through_restore_days
};
}
}
+
+ isTierMatch(...types: string[]): boolean {
+ const tier_type = this.selection.tier_type?.toLowerCase();
+ return types.some((type) => type.toLowerCase() === tier_type);
+ }
}
i18n-label
for="storageClassType"
formControlName="storageClassType"
- [helperText]="storageClassText"
+ [helperText]="textLabels.storageClassText"
id="storageClassType"
[invalid]="storageClassForm.showError('storageClassType', formDir, 'required')"
[invalidText]="storageError"
>
<option value=""
i18n>-- Select Storage Class --</option>
- <option value="local"
- i18n>Local</option>
- <option value="cloud-s3"
- i18n>Cloud S3</option>
+ <option *ngFor="let opt of storageClassOptions"
+ [value]="opt.value"
+ i18n>
+ {{ opt.label }}
+ </option>
</cds-select>
<ng-template #storageError>
<span
>
</ng-template>
</div>
- <div *ngIf="storageClassForm.getValue('storageClassType') === TIER_TYPE.CLOUD_TIER">
+ @if( isTierMatch( TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
+ <div>
<div class="form-item form-item-append"
cdsRow>
<div cdsCol>
i18n
[invalid]="storageClassForm.showError('region', formDir, 'required')"
[invalidText]="regionError"
- [helperText]="targetRegionText"
+ [helperText]="textLabels.targetRegionText"
>Target Region
<input
cdsText
i18n
[invalid]="storageClassForm.showError('endpoint', formDir, 'required')"
[invalidText]="endpointError"
- [helperText]="targetEndpointText"
+ [helperText]="textLabels.targetEndpointText"
>Target Endpoint
<input
cdsText
</ng-template>
</div>
</div>
-
<!-- Access Key -->
<div class="form-item">
<div cdsCol
labelInputID="access_key"
[invalid]="storageClassForm.showError('access_key', formDir, 'required')"
[invalidText]="accessError"
- [helperText]="targetAccessKeyText"
+ [helperText]="textLabels.targetAccessKeyText"
i18n
>Target Access Key
<input
</ng-template>
</div>
</div>
-
<!-- Secret Key -->
<div class="form-item">
<div cdsCol
class="d-flex">
<cds-password-label
labelInputID="secret_key"
- [helperText]="targetSecretKeyText"
+ [helperText]="textLabels.targetSecretKeyText"
[invalid]="storageClassForm.showError('secret_key', formDir, 'required')"
[invalidText]="secretError"
i18n
</ng-template>
</div>
</div>
-
<!-- Target Path -->
<div class="form-item">
<cds-text-label
i18n
[invalid]="storageClassForm.showError('target_path', formDir, 'required')"
[invalidText]="targetError"
- [helperText]="targetPathText"
+ [helperText]="textLabels.targetPathText"
>Target Path
<input
cdsText
>
</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>{{ textLabels?.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>{{ textLabels?.retainHeadObjectText }}</cd-help-text>
+ </cds-checkbox>
+ </div>
+ <div class="form-item form-item-append"
+ cdsRow>
+ <div cdsCol>
+ <cds-number
+ name="read_through_restore_days"
+ formControlName="read_through_restore_days"
+ id="read_through_restore_days"
+ min="1"
+ label="ReadThrough Restore Days"
+ [helperText]="textLabels.readthroughrestoreDaysText"
+ i18n-helperText
+ i18n-label
+ i18n
+ [invalid]="
+ storageClassForm.controls.read_through_restore_days.invalid &&
+ storageClassForm.controls.read_through_restore_days.dirty
+ "
+ [invalidText]="readThroughError"
+ ></cds-number>
+ <ng-template #readThroughError>
+ <span
+ class="invalid-feedback"
+ *ngIf="storageClassForm.showError('read_through_restore_days', formDir, 'pattern')"
+ i18n
+ >The entered value must be a positive integer.</span
+ >
+ <span
+ class="invalid-feedback"
+ *ngIf="storageClassForm.showError('read_through_restore_days', formDir, 'lockDays')"
+ i18n
+ >ReadThrough Restore Days must be positive.</span
+ >
+ </ng-template>
+ </div>
+ <div cdsCol>
+ <cds-select
+ formControlName="restore_storage_class"
+ label="Restore Storage Class"
+ id="restore_storage_class"
+ [helperText]="textLabels.restoreStorageClassText"
+ i18n-label
+ >
+ <option value=""
+ i18n>-- Select the glacier restore storage class --</option>
+ <option [ngValue]="standard"
+ i18n>Standard</option>
+ </cds-select>
+ </div>
+ </div>
</div>
- <div *ngIf="storageClassForm.getValue('storageClassType') === TIER_TYPE.CLOUD_TIER">
- <ng-template #title>
- <h5 class="cds--accordion__title cd-header">Advanced</h5>
- </ng-template>
- <fieldset>
- <cds-accordion size="lg"
- class="form-item">
- <cds-accordion-item
- [title]="title"
- id="advanced-fieldset"
- (selected)="showAdvanced = !showAdvanced"
+ } @if(isTierMatch(TIER_TYPE.GLACIER)){
+ <div>
+ <legend class="cd-header"
+ i18n>Glacier Configuration</legend>
+ <div class="form-item form-item-append"
+ cdsRow>
+ <div cdsCol>
+ <cds-select
+ formControlName="glacier_restore_tier_type"
+ label="Glacier Restore Tier Type"
+ cdRequiredField="Glacier Restore Tier Type"
+ id="glacier_restore_tier_type"
+ [invalid]="
+ storageClassForm.controls.glacier_restore_tier_type.invalid &&
+ storageClassForm.controls.glacier_restore_tier_type.dirty
+ "
+ [invalidText]="glacierError"
+ [helperText]="textLabels.tiertypeText"
+ i18n-label
>
- <!-- Multi Part Sync Threshold -->
- <div class="form-item form-item-append"
- cdsRow>
- <div cdsCol>
- <cds-text-label
- labelInputID="multipart_sync_threshold"
- i18n
- [helperText]="multipartSyncThreholdText"
- cdOptionalField="Multipart Sync Threshold"
- >Multipart Sync Threshold
- <input
- cdsText
- type="text"
- id="multipart_sync_threshold"
- formControlName="multipart_sync_threshold"
- />
- </cds-text-label>
- </div>
- <div cdsCol>
- <cds-text-label
- labelInputID="multipart_min_part_size"
- i18n
- [helperText]="multipartMinPartText"
- cdOptionalField="Multipart Minimum Part Size"
- >Multipart Minimum Part Size
- <input
- cdsText
- type="text"
- id="multipart_min_part_size"
- formControlName="multipart_min_part_size"
- />
- </cds-text-label>
- </div>
- </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>
- </cds-accordion-item>
- </cds-accordion>
- </fieldset>
+ <option value=""
+ i18n>-- Select the glacier restore tier type --</option>
+ <option [ngValue]="standard"
+ i18n>Standard</option>
+ <option [ngValue]="expedited"
+ i18n>Expedited</option>
+ </cds-select>
+ <ng-template #glacierError>
+ <span
+ class="invalid-feedback"
+ *ngIf="storageClassForm.showError('glacier_restore_tier_type', formDir, 'required')"
+ i18n
+ >This field is required.</span
+ >
+ </ng-template>
+ </div>
+ <div cdsCol>
+ <cds-number
+ [id]="'glacier_restore_days'"
+ [formControlName]="'glacier_restore_days'"
+ [label]="'Glacier Restore Days'"
+ [helperText]="textLabels.restoreDaysText"
+ [min]="1"
+ i18n-helperText
+ i18n-label
+ i18n
+ [invalid]="
+ storageClassForm.controls.glacier_restore_days.invalid &&
+ storageClassForm.controls.glacier_restore_days.dirty
+ "
+ [invalidText]="glacierRestoreError"
+ >
+ </cds-number>
+ <ng-template #glacierRestoreError>
+ <span
+ class="invalid-feedback"
+ *ngIf="storageClassForm.showError('glacier_restore_days', formDir, 'pattern')"
+ i18n
+ >The entered value must be a positive integer.</span
+ >
+ <span
+ class="invalid-feedback"
+ *ngIf="storageClassForm.showError('glacier_restore_days', formDir, 'lockDays')"
+ i18n
+ >Glacier Restore Days must be positive.</span
+ >
+ </ng-template>
+ </div>
+ </div>
</div>
- <cd-alert-panel
- type="warning"
- spacingClass="mb-2"
- *ngIf="storageClassForm.getValue('storageClassType') === TIER_TYPE.CLOUD_TIER"
- >
+ } @if( isTierMatch( TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
+ <fieldset>
+ <div>
+ <ng-template #title>
+ <h5 class="cds--accordion__title cd-header">Advanced</h5>
+ </ng-template>
+ <fieldset>
+ <cds-accordion size="lg"
+ class="form-item">
+ <cds-accordion-item
+ [title]="title"
+ id="advanced-fieldset"
+ (selected)="showAdvanced = !showAdvanced"
+ >
+ <!-- Multi Part Sync Threshold -->
+ <div class="form-item form-item-append"
+ cdsRow>
+ <div cdsCol>
+ <cds-text-label
+ labelInputID="multipart_sync_threshold"
+ i18n
+ [helperText]="textLabels.multipartSyncThresholdText"
+ cdOptionalField="Multipart Sync Threshold"
+ >Multipart Sync Threshold
+ <input
+ cdsText
+ type="text"
+ id="multipart_sync_threshold"
+ formControlName="multipart_sync_threshold"
+ cdDimlessBinary
+ />
+ </cds-text-label>
+ </div>
+ <div cdsCol>
+ <cds-text-label
+ labelInputID="multipart_min_part_size"
+ i18n
+ [helperText]="textLabels.multipartMinPartText"
+ cdOptionalField="Multipart Minimum Part Size"
+ >Multipart Minimum Part Size
+ <input
+ cdsText
+ type="text"
+ id="multipart_min_part_size"
+ formControlName="multipart_min_part_size"
+ cdDimlessBinary
+ />
+ </cds-text-label>
+ </div>
+ </div>
+ </cds-accordion-item>
+ </cds-accordion>
+ </fieldset>
+ </div>
+ </fieldset>
+ } @if( isTierMatch( TIER_TYPE.CLOUD_TIER, TIER_TYPE.GLACIER )){
+ <cd-alert-panel type="warning"
+ spacingClass="mb-2">
<span i18n>RGW service would be restarted after creating the storage class.</span>
</cd-alert-panel>
+ }
<cd-form-button-panel
(submitActionEvent)="submitAction()"
[form]="storageClassForm"
} from 'carbon-components-angular';
import { CoreModule } from '~/app/core/core.module';
import { RgwStorageClassFormComponent } from './rgw-storage-class-form.component';
+import { TIER_TYPE_DISPLAY } from '../models/rgw-storage-class.model';
describe('RgwStorageClassFormComponent', () => {
let component: RgwStorageClassFormComponent;
retain_head_object: true,
storage_class: 'CLOUDIBM',
allow_read_through: true,
+ read_through_restore_days: 1,
+ restore_storage_class: 'test67',
s3: {
storage_class: 'CLOUDIBM',
endpoint: 'https://s3.amazonaws.com',
multipart_min_part_size: 87877,
multipart_sync_threshold: 987877,
host_style: true
+ },
+ 's3-glacier': {
+ glacier_restore_days: 5,
+ glacier_restore_tier_type: 'Standard'
}
}
}
component.submitAction();
expect(component).toBeTruthy();
});
+
+ it('should set required validators for CLOUD_TIER fields', () => {
+ (component as any).updateValidatorsBasedOnStorageClass(TIER_TYPE_DISPLAY.CLOUD_TIER);
+ const requiredFields = ['region', 'endpoint', 'access_key', 'secret_key', 'target_path'];
+ requiredFields.forEach((field) => {
+ const control = component.storageClassForm.get(field);
+ control.setValue('');
+ control.updateValueAndValidity();
+ });
+ ['glacier_restore_tier_type', 'restore_storage_class'].forEach((field) => {
+ const control = component.storageClassForm.get(field);
+ control.setValue('');
+ control.updateValueAndValidity();
+ expect(component).toBeTruthy();
+ });
+ });
+
+ it('should set required validators for GLACIER fields', () => {
+ (component as any).updateValidatorsBasedOnStorageClass(TIER_TYPE_DISPLAY.GLACIER);
+ const requiredFields = [
+ 'region',
+ 'endpoint',
+ 'access_key',
+ 'secret_key',
+ 'target_path',
+ 'glacier_restore_tier_type',
+ 'restore_storage_class'
+ ];
+ requiredFields.forEach((field) => {
+ const control = component.storageClassForm.get(field);
+ control.setValue('');
+ control.updateValueAndValidity();
+ expect(component).toBeTruthy();
+ });
+ });
+
+ it('should clear validators for LOCAL fields', () => {
+ (component as any).updateValidatorsBasedOnStorageClass(TIER_TYPE_DISPLAY.LOCAL);
+
+ const allFields = [
+ 'region',
+ 'endpoint',
+ 'access_key',
+ 'secret_key',
+ 'target_path',
+ 'glacier_restore_tier_type',
+ 'restore_storage_class'
+ ];
+ allFields.forEach((field) => {
+ const control = component.storageClassForm.get(field);
+ control.setValue('');
+ control.updateValueAndValidity();
+ expect(component).toBeTruthy();
+ });
+ });
});
import { Component, OnInit } from '@angular/core';
-import { FormControl, Validators } from '@angular/forms';
+import { AbstractControl, FormControl, Validators } from '@angular/forms';
import { ActionLabelsI18n, URLVerbs } from '~/app/shared/constants/app.constants';
import { CdForm } from '~/app/shared/forms/cd-form';
import { CdFormBuilder } from '~/app/shared/forms/cd-form-builder';
ZoneGroup,
ZoneGroupDetails,
CLOUDS3_STORAGE_CLASS_TEXT,
- LOCAL_STORAGE_CLASS_TEXT
+ LOCAL_STORAGE_CLASS_TEXT,
+ GLACIER_STORAGE_CLASS_TEXT,
+ GLACIER_RESTORE_DAY_TEXT,
+ GLACIER_RESTORE_TIER_TYPE_TEXT,
+ RESTORE_DAYS_TEXT,
+ READTHROUGH_RESTORE_DAYS_TEXT,
+ RESTORE_STORAGE_CLASS_TEXT,
+ TIER_TYPE_DISPLAY,
+ S3Glacier,
+ StorageClassOption,
+ STORAGE_CLASS_CONSTANTS,
+ STANDARD_TIER_TYPE_TEXT,
+ EXPEDITED_TIER_TYPE_TEXT,
+ TextLabels
} from '../models/rgw-storage-class.model';
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
import { NotificationService } from '~/app/shared/services/notification.service';
action: string;
resource: string;
editing: boolean;
- targetPathText: string;
- targetEndpointText: string;
- targetRegionText: string;
showAdvanced: boolean = false;
defaultZoneGroup: string;
zonegroupNames: ZoneGroup[];
placementTargets: string[] = [];
- multipartMinPartText: string;
- storageClassText: string;
- multipartSyncThreholdText: string;
selectedZoneGroup: string;
defaultZonegroup: ZoneGroup;
zoneGroupDetails: ZoneGroupDetails;
- targetSecretKeyText: string;
- targetAccessKeyText: string;
- retainHeadObjectText: string;
storageClassInfo: StorageClass;
tierTargetInfo: TierTarget;
- allowReadThroughText: string;
+ glacierStorageClassDetails: S3Glacier;
allowReadThrough: boolean = false;
TIER_TYPE = TIER_TYPE;
+ TIER_TYPE_DISPLAY = TIER_TYPE_DISPLAY;
+ storageClassOptions: StorageClassOption[];
+ textLabels: TextLabels;
constructor(
public actionLabels: ActionLabelsI18n,
}
ngOnInit() {
- 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.storageClassText = LOCAL_STORAGE_CLASS_TEXT;
- this.storageClassTypeText();
+ this.textLabels = {
+ targetPathText: TARGET_PATH_TEXT,
+ targetEndpointText: TARGET_ENDPOINT_TEXT,
+ targetRegionText: TARGET_REGION_TEXT,
+ targetAccessKeyText: TARGET_ACCESS_KEY_TEXT,
+ targetSecretKeyText: TARGET_SECRET_KEY_TEXT,
+ retainHeadObjectText: RETAIN_HEAD_OBJECT_TEXT,
+ allowReadThroughText: ALLOW_READ_THROUGH_TEXT,
+ storageClassText: LOCAL_STORAGE_CLASS_TEXT,
+ multipartMinPartText: MULTIPART_MIN_PART_TEXT,
+ multipartSyncThresholdText: MULTIPART_SYNC_THRESHOLD_TEXT,
+ tiertypeText: STANDARD_TIER_TYPE_TEXT,
+ glacierRestoreDayText: GLACIER_RESTORE_DAY_TEXT,
+ glacierRestoreTiertypeText: GLACIER_RESTORE_TIER_TYPE_TEXT,
+ restoreDaysText: RESTORE_DAYS_TEXT,
+ readthroughrestoreDaysText: READTHROUGH_RESTORE_DAYS_TEXT,
+ restoreStorageClassText: RESTORE_STORAGE_CLASS_TEXT
+ };
+ this.storageClassOptions = [
+ { value: TIER_TYPE.LOCAL, label: TIER_TYPE_DISPLAY.LOCAL },
+ { value: TIER_TYPE.CLOUD_TIER, label: TIER_TYPE_DISPLAY.CLOUD_TIER },
+ { value: TIER_TYPE.GLACIER, label: TIER_TYPE_DISPLAY.GLACIER }
+ ];
this.createForm();
+ this.storageClassTypeText();
+ this.TierTypeText();
this.loadingReady();
this.loadZoneGroup();
if (this.editing) {
retain_head_object: this.tierTargetInfo?.val?.retain_head_object || false,
multipart_sync_threshold: response?.multipart_sync_threshold || '',
multipart_min_part_size: response?.multipart_min_part_size || '',
- allow_read_through: this.tierTargetInfo?.val?.allow_read_through || false
+ allow_read_through: this.tierTargetInfo?.val?.allow_read_through || false,
+ restore_storage_class: this.tierTargetInfo?.val?.restore_storage_class,
+ read_through_restore_days: this.tierTargetInfo?.val?.read_through_restore_days
});
+ if (this.tierTargetInfo?.val?.tier_type == TIER_TYPE.GLACIER) {
+ let glacierResponse = this.tierTargetInfo?.val['s3-glacier'];
+ this.storageClassForm.patchValue({
+ glacier_restore_tier_type: glacierResponse.glacier_restore_tier_type,
+ glacier_restore_days: glacierResponse.glacier_restore_days
+ });
+ }
});
}
- this.storageClassForm?.get('storageClassType')?.valueChanges.subscribe((value) => {
- const controlsToUpdate = ['region', 'endpoint', 'access_key', 'secret_key', 'target_path'];
- controlsToUpdate.forEach((field) => {
- const control = this.storageClassForm.get(field);
- if (
- value === TIER_TYPE.CLOUD_TIER &&
- ['region', 'endpoint', 'access_key', 'secret_key', 'target_path'].includes(field)
- ) {
- control.setValidators([Validators.required]);
- } else {
- control.clearValidators();
- }
-
- control.updateValueAndValidity();
- });
+ this.storageClassForm.get('storageClassType').valueChanges.subscribe((value) => {
+ this.updateValidatorsBasedOnStorageClass(value);
});
this.storageClassForm.get('allow_read_through').valueChanges.subscribe((value) => {
this.onAllowReadThroughChange(value);
});
}
+ private updateValidatorsBasedOnStorageClass(value: string) {
+ const controlsToUpdate = [
+ 'region',
+ 'endpoint',
+ 'access_key',
+ 'secret_key',
+ 'target_path',
+ 'glacier_restore_tier_type',
+ 'restore_storage_class'
+ ];
+
+ controlsToUpdate.forEach((field) => {
+ const control = this.storageClassForm.get(field);
+
+ if (
+ (value === TIER_TYPE.CLOUD_TIER &&
+ ['region', 'endpoint', 'access_key', 'secret_key', 'target_path'].includes(field)) ||
+ (value === TIER_TYPE.GLACIER &&
+ [
+ 'glacier_restore_tier_type',
+ 'restore_storage_class',
+ 'region',
+ 'endpoint',
+ 'access_key',
+ 'secret_key',
+ 'target_path'
+ ].includes(field))
+ ) {
+ control.setValidators([Validators.required]);
+ } else {
+ control.clearValidators();
+ }
+
+ control.updateValueAndValidity();
+ });
+ }
+
storageClassTypeText() {
this.storageClassForm?.get('storageClassType')?.valueChanges.subscribe((value) => {
if (value === TIER_TYPE.LOCAL) {
- this.storageClassText = LOCAL_STORAGE_CLASS_TEXT;
+ this.textLabels.storageClassText = LOCAL_STORAGE_CLASS_TEXT;
} else if (value === TIER_TYPE.CLOUD_TIER) {
- this.storageClassText = CLOUDS3_STORAGE_CLASS_TEXT;
+ this.textLabels.storageClassText = CLOUDS3_STORAGE_CLASS_TEXT;
+ } else if (value === TIER_TYPE.GLACIER) {
+ this.textLabels.storageClassText = GLACIER_STORAGE_CLASS_TEXT;
+ }
+ });
+ }
+
+ TierTypeText() {
+ this.storageClassForm?.get('glacier_restore_tier_type')?.valueChanges.subscribe((value) => {
+ if (value === STORAGE_CLASS_CONSTANTS.DEFAULT_STORAGE_CLASS) {
+ this.textLabels.tiertypeText = STANDARD_TIER_TYPE_TEXT;
} else {
- this.storageClassText = LOCAL_STORAGE_CLASS_TEXT;
+ this.textLabels.tiertypeText = EXPEDITED_TIER_TYPE_TEXT;
}
});
}
createForm() {
+ const self = this;
+
+ const lockDaysValidator = CdValidators.custom('lockDays', () => {
+ if (!self.storageClassForm || !self.storageClassForm.getRawValue()) {
+ return false;
+ }
+
+ const lockDays = Number(self.storageClassForm.getValue('read_through_restore_days'));
+ return !Number.isInteger(lockDays) || lockDays === 0;
+ });
this.storageClassForm = this.formBuilder.group({
storage_class: new FormControl('', {
validators: [Validators.required]
CdValidators.composeIf({ storageClassType: TIER_TYPE.CLOUD_TIER }, [Validators.required])
]),
retain_head_object: new FormControl(true),
- multipart_sync_threshold: new FormControl(33554432),
- multipart_min_part_size: new FormControl(33554432),
+ glacier_restore_tier_type: new FormControl(STORAGE_CLASS_CONSTANTS.DEFAULT_STORAGE_CLASS, [
+ CdValidators.composeIf({ storageClassType: TIER_TYPE.GLACIER }, [Validators.required])
+ ]),
+ glacier_restore_days: new FormControl(STORAGE_CLASS_CONSTANTS.DEFAULT_GLACIER_RESTORE_DAYS, [
+ CdValidators.composeIf({ storageClassType: TIER_TYPE.GLACIER || TIER_TYPE.CLOUD_TIER }, [
+ CdValidators.number(false),
+ lockDaysValidator
+ ])
+ ]),
+ restore_storage_class: new FormControl(STORAGE_CLASS_CONSTANTS.DEFAULT_STORAGE_CLASS),
+ read_through_restore_days: new FormControl(
+ {
+ value: STORAGE_CLASS_CONSTANTS.DEFAULT_READTHROUGH_RESTORE_DAYS,
+ disabled: true
+ },
+ CdValidators.composeIf(
+ (form: AbstractControl) => {
+ const type = form.get('storageClassType')?.value;
+ return type === TIER_TYPE.GLACIER || type === TIER_TYPE.CLOUD_TIER;
+ },
+ [CdValidators.number(false), lockDaysValidator]
+ )
+ ),
+ multipart_sync_threshold: new FormControl(
+ STORAGE_CLASS_CONSTANTS.DEFAULT_MULTIPART_SYNC_THRESHOLD
+ ),
+ multipart_min_part_size: new FormControl(
+ STORAGE_CLASS_CONSTANTS.DEFAULT_MULTIPART_MIN_PART_SIZE
+ ),
allow_read_through: new FormControl(false),
storageClassType: new FormControl(TIER_TYPE.LOCAL, Validators.required)
});
this.defaultZonegroup = this.zonegroupNames.find(
(zonegroups: ZoneGroup) => zonegroups.id === data.default_zonegroup
);
-
this.storageClassForm.get('zonegroup').setValue(this.defaultZonegroup.name);
this.onZonegroupChange();
resolve();
onAllowReadThroughChange(checked: boolean): void {
this.allowReadThrough = checked;
+ const readThroughDaysControl = this.storageClassForm.get('read_through_restore_days');
if (this.allowReadThrough) {
this.storageClassForm.get('retain_head_object')?.setValue(true);
this.storageClassForm.get('retain_head_object')?.disable();
+ readThroughDaysControl?.enable();
} else {
this.storageClassForm.get('retain_head_object')?.enable();
+ readThroughDaysControl?.disable();
}
}
+ isTierMatch(...types: string[]): boolean {
+ const tierType = this.storageClassForm.getValue('storageClassType');
+ return types.includes(tierType);
+ }
+
buildRequest() {
if (this.storageClassForm.errors) return null;
const placementId = this.storageClassForm.get('placement_target').value;
const storageClassType = this.storageClassForm.get('storageClassType').value;
const retain_head_object = this.storageClassForm.get('retain_head_object').value;
-
return this.buildPlacementTargets(
storageClassType,
zoneGroup,
retain_head_object: boolean,
rawFormValue: any
): RequestModel {
- switch (storageClassType) {
- case TIER_TYPE.LOCAL:
- return {
- zone_group: zoneGroup,
- placement_targets: [
- {
- tags: [],
- placement_id: placementId,
- storage_class: storageClass
+ const baseTarget = {
+ placement_id: placementId,
+ storage_class: storageClass
+ };
+
+ if (storageClassType === TIER_TYPE.LOCAL) {
+ return {
+ zone_group: zoneGroup,
+ placement_targets: [baseTarget]
+ };
+ }
+
+ const tierConfig = {
+ endpoint: rawFormValue.endpoint,
+ access_key: rawFormValue.access_key,
+ secret: rawFormValue.secret_key,
+ target_path: rawFormValue.target_path,
+ retain_head_object,
+ 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,
+ restore_storage_class: rawFormValue.restore_storage_class,
+ ...(rawFormValue.allow_read_through
+ ? { read_through_restore_days: rawFormValue.read_through_restore_days }
+ : {})
+ };
+
+ if (storageClassType === TIER_TYPE.CLOUD_TIER) {
+ return {
+ zone_group: zoneGroup,
+ placement_targets: [
+ {
+ ...baseTarget,
+ tier_type: TIER_TYPE.CLOUD_TIER,
+ tier_config: {
+ ...tierConfig
}
- ]
- };
+ }
+ ]
+ };
+ }
- case TIER_TYPE.CLOUD_TIER:
- return {
- zone_group: zoneGroup,
- placement_targets: [
- {
- tags: [],
- placement_id: placementId,
- storage_class: storageClass,
- tier_type: TIER_TYPE.CLOUD_TIER,
- tier_config: {
- endpoint: rawFormValue.endpoint,
- access_key: rawFormValue.access_key,
- secret: rawFormValue.secret_key,
- target_path: rawFormValue.target_path,
- retain_head_object: retain_head_object,
- 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
- }
+ if (storageClassType === TIER_TYPE.GLACIER) {
+ return {
+ zone_group: zoneGroup,
+ placement_targets: [
+ {
+ ...baseTarget,
+ tier_type: TIER_TYPE.GLACIER,
+ tier_config: {
+ ...tierConfig,
+ glacier_restore_days: rawFormValue.glacier_restore_days,
+ glacier_restore_tier_type: rawFormValue.glacier_restore_tier_type
}
- ]
- };
- default:
- return null;
+ }
+ ]
+ };
}
+ return {
+ zone_group: zoneGroup,
+ placement_targets: [baseTarget]
+ };
}
}
(data: ZoneGroupDetails) => {
this.storageClassList = [];
const tierObj = BucketTieringUtils.filterAndMapTierTargets(data);
- const tierConfig = tierObj.map((item) => ({
- ...item,
- tier_type:
- item.tier_type?.toLowerCase() === TIER_TYPE.CLOUD_TIER
- ? TIER_TYPE_DISPLAY.CLOUD_TIER
- : item.tier_type?.toLowerCase() === TIER_TYPE.LOCAL
- ? TIER_TYPE_DISPLAY.LOCAL
- : item.tier_type
- }));
+ const tierConfig = tierObj.map((item) => {
+ let tierTypeDisplay;
+
+ switch (item.tier_type?.toLowerCase()) {
+ case TIER_TYPE.CLOUD_TIER:
+ tierTypeDisplay = TIER_TYPE_DISPLAY.CLOUD_TIER;
+ break;
+ case TIER_TYPE.LOCAL:
+ tierTypeDisplay = TIER_TYPE_DISPLAY.LOCAL;
+ break;
+ case TIER_TYPE.GLACIER:
+ tierTypeDisplay = TIER_TYPE_DISPLAY.GLACIER;
+ break;
+ default:
+ tierTypeDisplay = item.tier_type;
+ }
+ return {
+ ...item,
+ tier_type: tierTypeDisplay
+ };
+ });
this.transformTierData(tierConfig);
this.storageClassList.push(...tierConfig);
resolve();
private static getTierTargets(tierTarget: TierTarget, zoneGroup: string, targetName: string) {
const val = tierTarget.val;
- if (val.tier_type === TIER_TYPE.CLOUD_TIER) {
- return {
- zonegroup_name: zoneGroup,
- placement_target: targetName,
- storage_class: val.storage_class,
- retain_head_object: val.retain_head_object,
- allow_read_through: val.allow_read_through,
- tier_type: val.tier_type,
- ...val.s3
- };
- } else {
+ const tierType = val.tier_type;
+
+ const commonProps = {
+ zonegroup_name: zoneGroup,
+ placement_target: targetName,
+ storage_class: val.storage_class,
+ tier_type: tierType
+ };
+
+ if (!tierType || tierType === TIER_TYPE.LOCAL) {
+ return commonProps;
+ }
+ const cloudProps = {
+ ...commonProps,
+ retain_head_object: val.retain_head_object,
+ allow_read_through: val.allow_read_through,
+ restore_storage_class: val.restore_storage_class,
+ read_through_restore_days: val.read_through_restore_days,
+ ...val.s3
+ };
+
+ if (tierType === TIER_TYPE.GLACIER) {
return {
- zonegroup_name: zoneGroup,
- placement_target: targetName,
- storage_class: val.storage_class,
- tier_type: TIER_TYPE.LOCAL
+ ...cloudProps,
+ ...val['s3-glacier']
};
}
+ return cloudProps;
}
}
def add_placement_targets(self, zonegroup_name: str, placement_targets: List[Dict]):
rgw_add_placement_cmd = ['zonegroup', 'placement', 'add']
STANDARD_STORAGE_CLASS = "STANDARD"
- CLOUD_S3_TIER_TYPE = "cloud-s3"
+ CLOUD_S3_TIER_TYPES = ["cloud-s3", "cloud-s3-glacier"]
for placement_target in placement_targets: # pylint: disable=R1702
cmd_add_placement_options = [
storage_class_name = placement_target.get('storage_class', None)
tier_type = placement_target.get('tier_type', None)
- if (
- placement_target.get('tier_type') == CLOUD_S3_TIER_TYPE
- and storage_class_name != STANDARD_STORAGE_CLASS
- ):
+ if tier_type in CLOUD_S3_TIER_TYPES and storage_class_name != STANDARD_STORAGE_CLASS:
tier_config = placement_target.get('tier_config', {})
if tier_config:
tier_config_items = self.modify_retain_head(tier_config)
tier_config_str = ','.join(tier_config_items)
cmd_add_placement_options += [
- '--tier-type', 'cloud-s3', '--tier-config', tier_config_str
+ '--tier-type', tier_type,
+ '--tier-config', tier_config_str
]
if placement_target.get('tags') and storage_class_name != STANDARD_STORAGE_CLASS:
)
except SubprocessError as error:
raise DashboardException(error, http_status_code=500, component='rgw')
- if tier_type == CLOUD_S3_TIER_TYPE:
+ if tier_type in CLOUD_S3_TIER_TYPES:
self.ensure_realm_and_sync_period()
if storage_classes:
)
except SubprocessError as error:
raise DashboardException(error, http_status_code=500, component='rgw')
- if tier_type == CLOUD_S3_TIER_TYPE:
+ if tier_type in CLOUD_S3_TIER_TYPES:
self.ensure_realm_and_sync_period()
def modify_placement_targets(self, zonegroup_name: str, placement_targets: List[Dict]):
rgw_add_placement_cmd = ['zonegroup', 'placement', 'modify']
STANDARD_STORAGE_CLASS = "STANDARD"
- CLOUD_S3_TIER_TYPE = "cloud-s3"
+ CLOUD_S3_TIER_TYPES = ["cloud-s3", "cloud-s3-glacier"]
for placement_target in placement_targets: # pylint: disable=R1702,line-too-long # noqa: E501
cmd_add_placement_options = [
'--placement-id', placement_target['placement_id']
]
storage_class_name = placement_target.get('storage_class', None)
+ tier_type = placement_target.get('tier_type')
if (
- placement_target.get('tier_type') == CLOUD_S3_TIER_TYPE
+ placement_target.get('tier_type') == CLOUD_S3_TIER_TYPES
and storage_class_name != STANDARD_STORAGE_CLASS
):
tier_config = placement_target.get('tier_config', {})
)
except SubprocessError as error:
raise DashboardException(error, http_status_code=500, component='rgw')
- self.ensure_realm_and_sync_period()
+ if tier_type in CLOUD_S3_TIER_TYPES:
+ self.ensure_realm_and_sync_period()
if storage_classes:
for sc in storage_classes:
)
except SubprocessError as error:
raise DashboardException(error, http_status_code=500, component='rgw')
- self.ensure_realm_and_sync_period()
+ if tier_type in CLOUD_S3_TIER_TYPES:
+ self.ensure_realm_and_sync_period()
def delete_placement_targets(self, placement_id: str, storage_class: str):
rgw_zonegroup_delete_cmd = ['zonegroup', 'placement', 'rm',