@allow_empty_body
# pylint: disable=W0613
def create(self, zone_name, zonegroup_name=None, default=False, master=False,
- zone_endpoints=None, access_key=None, secret_key=None, tier_type=''):
+ zone_endpoints=None, access_key=None, secret_key=None, tier_type='',
+ sync_from: str = '', sync_from_all: str = ''):
multisite_instance = RgwMultisite()
result = multisite_instance.create_zone(zone_name, zonegroup_name, default,
master, zone_endpoints, access_key,
- secret_key, tier_type)
+ secret_key, tier_type, sync_from,
+ sync_from_all)
return result
@allow_empty_body
master: str = '', zone_endpoints: str = '', access_key: str = '', secret_key: str = '',
placement_target: str = '', data_pool: str = '', index_pool: str = '',
data_extra_pool: str = '', storage_class: str = '', data_pool_class: str = '',
- compression: str = '', tier_type: str = ''):
+ compression: str = '', tier_type: str = '', sync_from: str = '',
+ sync_from_all: str = ''):
multisite_instance = RgwMultisite()
result = multisite_instance.edit_zone(zone_name, new_zone_name, zonegroup_name, default,
master, zone_endpoints, access_key, secret_key,
placement_target, data_pool, index_pool,
data_extra_pool, storage_class, data_pool_class,
- compression, tier_type)
+ compression, tier_type, sync_from, sync_from_all)
return result
@Endpoint()
notif_pool: string;
endpoints: string;
tier_type: string;
+ sync_from: string;
+ sync_from_all: boolean;
}
export class SystemKey {
id="archive_zone"
formControlName="archive_zone"
cdOptionalField="Archive"
+ (checkedChange)="onArchiveZoneChange($event)"
i18n
>Archive
<cd-help-text>
</cd-help-text>
</cds-checkbox>
</div>
+ <div class="form-item">
+ <cds-checkbox
+ id="sync_from_all"
+ formControlName="sync_from_all"
+ cdOptionalField="Sync from all"
+ (checkedChange)="onZoneGroupChange(multisiteZoneForm.getValue('selectedZonegroup'))"
+ i18n
+ >Sync from all zones
+ <cd-help-text>
+ <span
+ >Enable this option to synchronize data from all zones.</span
+ >
+ </cd-help-text>
+ <div class="cds-mt-3">
+ <cd-alert-panel *ngIf="multisiteZoneForm.get('archive_zone')?.value === true"
+ type="warning">
+ “Sync from all zones” is disabled to avoid duplicate objects in archive zones. Please select specific zones instead.
+ </cd-alert-panel>
+ </div>
+ </cds-checkbox>
+ </div>
+ <div *ngIf="multisiteZoneForm.get('sync_from_all')?.value === false"
+ class="form-item">
+ <cds-combo-box type="multi"
+ selectionFeedback="top-after-reopen"
+ label="Sync from zones"
+ formControlName="sync_from_zones"
+ id="sync_from_zones"
+ [appendInline]="true"
+ [items]="syncFromZonesOptions"
+ i18n>
+ <cds-dropdown-list></cds-dropdown-list>
+ </cds-combo-box>
+ <cd-help-text>
+ <span i18n>Select specific zones to synchronize data from when "Sync from all zones" is disabled.</span>
+ </cd-help-text>
+ </div>
<div class="form-item">
<cds-text-label
i18n
import { RgwRealm, RgwZone, RgwZonegroup, SystemKey } from '../models/rgw-multisite';
import { ModalCdsService } from '~/app/shared/services/modal-cds.service';
import { CdForm } from '~/app/shared/forms/cd-form';
+import { ComboBoxItem } from '~/app/shared/models/combo-box.model';
@Component({
selector: 'cd-rgw-multisite-zone-form',
syncStatusTimedOut: boolean = false;
bsModalRef: NgbModalRef;
createSystemUser: boolean = false;
- master_zone_of_master_zonegroup: RgwZone;
+ master_zone_name: string;
masterZoneUser: any;
access_key: any;
master_zonegroup_of_realm: RgwZonegroup;
'To see or copy your S3 secret key, go to Object Gateway > Users and click on your user name. In Keys, click Show. View the secret key by clicking Show and copy the key by clicking Copy to Clipboard';
AccessKeyText =
'To see or copy your S3 access key, go to Object Gateway > Users and click on your user name. In Keys, click Show. View the access key by clicking Show and copy the key by clicking Copy to Clipboard';
+ syncFromZonesOptions: ComboBoxItem[] = [];
+
constructor(
public activeModal: NgbActiveModal,
public actionLabels: ActionLabelsI18n,
placementDataExtraPool: new UntypedFormControl(null),
storageClass: new UntypedFormControl(null),
storageDataPool: new UntypedFormControl(null),
- storageCompression: new UntypedFormControl(null)
+ storageCompression: new UntypedFormControl(null),
+ sync_from_zones: new UntypedFormControl(null),
+ sync_from_all: new UntypedFormControl(true)
});
}
onZoneGroupChange(zonegroupName: string) {
+ this.syncFromZonesOptions = [];
+
let zg = new RgwZonegroup();
zg.name = zonegroupName;
+
this.rgwZoneGroupService.get(zg).subscribe((zonegroup: RgwZonegroup) => {
+ const syncFromZones = this.info?.data?.info?.sync_from || [];
+
+ this.syncFromZonesOptions = zonegroup.zones
+ .filter((zone) => zone.name !== this.multisiteZoneForm.getValue('zoneName'))
+ .map((zone) => ({
+ name: zone.name,
+ content: zone.name,
+ selected: syncFromZones.includes(zone.name)
+ }));
+
+ this.multisiteZoneForm
+ .get('sync_from_zones')
+ .setValue(this.syncFromZonesOptions.filter((opt) => opt.selected));
+
if (_.isEmpty(zonegroup.master_zone)) {
this.multisiteZoneForm.get('master_zone').setValue(true);
this.multisiteZoneForm.get('master_zone').disable();
this.multisiteZoneForm.get('master_zone').disable();
this.disableMaster = true;
}
+ const masterZone = this.zoneList.find((zone) => zone.id === zonegroup.master_zone);
+ if (masterZone) {
+ this.master_zone_name = masterZone.name;
+ }
});
if (
this.multisiteZoneForm.getValue('selectedZonegroup') !==
this.multisiteZoneForm
.get('archive_zone')
.setValue(this.info.data.info.tier_type === 'archive');
+ this.onArchiveZoneChange(this.info.data.info.tier_type === 'archive');
+ this.multisiteZoneForm.get('sync_from_all').setValue(this.info.data.info.sync_from_all);
this.multisiteZoneForm
.get('placementTarget')
.setValue((this.info.data?.parentNode || this.info.parent.data)?.default_placement);
this.zone.system_key.access_key = values['access_key'];
this.zone.system_key.secret_key = values['secret_key'];
this.zone.tier_type = values['archive_zone'] ? 'archive' : '';
+ this.zone.sync_from = values['sync_from_zones']
+ ? values['sync_from_zones'].map((zone: RgwZone) => zone.name).join(',')
+ : '';
+ this.zone.sync_from_all = values['sync_from_all'];
this.rgwZoneService
.create(
this.zone,
this.zone.system_key.access_key = values['access_key'];
this.zone.system_key.secret_key = values['secret_key'];
this.zone.tier_type = values['archive_zone'] ? 'archive' : '';
+ this.zone.sync_from = values['sync_from_zones']
+ ? values['sync_from_zones'].map((zone: RgwZone) => zone.name).join(',')
+ : '';
+ this.zone.sync_from_all = values['sync_from_all'];
this.rgwZoneService
.update(
this.zone,
);
}
}
+
+ onArchiveZoneChange(isArchiveZone: boolean) {
+ if (isArchiveZone) {
+ this.multisiteZoneForm.get('sync_from_all').setValue(false);
+ this.multisiteZoneForm.get('sync_from_all').disable();
+ this.syncFromZonesOptions = this.syncFromZonesOptions.map((zone) => ({
+ ...zone,
+ selected: zone.name === this.master_zone_name
+ }));
+ this.multisiteZoneForm
+ .get('sync_from_zones')
+ .setValue(this.syncFromZonesOptions.filter((opt) => opt.selected));
+ } else {
+ this.multisiteZoneForm.get('sync_from_all').enable();
+ this.multisiteZoneForm.get('sync_from_all').setValue(true);
+ }
+ }
}
zone_endpoints: endpoints,
access_key: zone.system_key.access_key,
secret_key: zone.system_key.secret_key,
- tier_type: zone.tier_type
+ tier_type: zone.tier_type,
+ sync_from: zone.sync_from,
+ sync_from_all: zone.sync_from_all
});
return this.http.post(`${this.url}`, null, { params: params });
}
storage_class: storageClass,
data_pool_class: dataPoolClass,
compression: compression,
- tier_type: zone.tier_type
+ tier_type: zone.tier_type,
+ sync_from: zone.sync_from,
+ sync_from_all: zone.sync_from_all
};
return this.http.put(`${this.url}/${zone.name}`, requestBody);
}
nodes['endpoints'] = zone.endpoints;
nodes['is_master'] = zonegroup && zonegroup.master_zone === zone.id ? true : false;
nodes['tier_type'] = zonegroup?.zones?.find((z) => z.name === zone.name)?.tier_type || '';
+ nodes['sync_from'] = zonegroup?.zones?.find((z) => z.name === zone.name)?.sync_from || [];
+ nodes['sync_from_all'] =
+ zonegroup?.zones?.find((z) => z.name === zone.name)?.sync_from_all ?? true;
nodes['type'] = 'zone';
const zoneNames = zones.map((zone: RgwZone) => {
return zone['name'];
.border-subtle-inline-end {
border-inline-end: 1px solid var(--cds-border-subtle-01);
}
+
+.popover {
+ --bs-popover-zindex: 9999;
+}
type: boolean
secret_key:
type: string
+ sync_from:
+ default: ''
+ type: string
+ sync_from_all:
+ default: ''
+ type: string
tier_type:
default: ''
type: string
storage_class:
default: ''
type: string
+ sync_from:
+ default: ''
+ type: string
+ sync_from_all:
+ default: ''
+ type: string
tier_type:
default: ''
type: string
raise DashboardException(error, http_status_code=500, component='rgw')
def create_zone(self, zone_name, zonegroup_name, default, master, endpoints, access_key,
- secret_key, tier_type):
+ secret_key, tier_type, sync_from: Optional[str] = None,
+ sync_from_all: Optional[str] = None):
rgw_zone_create_cmd = ['zone', 'create']
cmd_create_zone_options = ['--rgw-zone', zone_name]
if zonegroup_name != 'null':
if tier_type:
cmd_create_zone_options.append('--tier-type')
cmd_create_zone_options.append(tier_type)
+ if sync_from is not None:
+ cmd_create_zone_options.append('--sync-from')
+ cmd_create_zone_options.append(sync_from)
+ if sync_from_all is not None:
+ cmd_create_zone_options.append('--sync-from-all')
+ cmd_create_zone_options.append(str(sync_from_all).lower())
rgw_zone_create_cmd += cmd_create_zone_options
try:
exit_code, out, err = mgr.send_rgwadmin_command(rgw_zone_create_cmd)
return '', ''
def modify_zone(self, zone_name: str, zonegroup_name: str, default: str, master: str,
- endpoints: str, access_key: str, secret_key: str, tier_type: str):
+ endpoints: str, access_key: str, secret_key: str, tier_type: str,
+ sync_from: Optional[str] = None, sync_from_all: Optional[str] = None):
rgw_zone_modify_cmd = ['zone', 'modify', '--rgw-zonegroup',
zonegroup_name, '--rgw-zone', zone_name]
if endpoints:
if tier_type is not None:
rgw_zone_modify_cmd.append('--tier-type')
rgw_zone_modify_cmd.append(tier_type)
+ if sync_from is not None:
+ rgw_zone_modify_cmd.append('--sync-from')
+ rgw_zone_modify_cmd.append(sync_from)
+ if sync_from_all is not None:
+ rgw_zone_modify_cmd.append('--sync-from-all')
+ rgw_zone_modify_cmd.append(str(sync_from_all).lower())
try:
exit_code, _, err = mgr.send_rgwadmin_command(rgw_zone_modify_cmd)
if exit_code > 0:
master: str = '', endpoints: str = '', access_key: str = '', secret_key: str = '',
placement_target: str = '', data_pool: str = '', index_pool: str = '',
data_extra_pool: str = '', storage_class: str = '', data_pool_class: str = '',
- compression: str = '', tier_type: str = ''):
+ compression: str = '', tier_type: str = '', sync_from: str = '',
+ sync_from_all: str = ''):
if new_zone_name != zone_name:
rgw_zone_rename_cmd = ['zone', 'rename', '--rgw-zone',
zone_name, '--zone-new-name', new_zone_name]
raise DashboardException(error, http_status_code=500, component='rgw')
self.update_period()
self.modify_zone(new_zone_name, zonegroup_name, default, master, endpoints, access_key,
- secret_key, tier_type)
+ secret_key, tier_type, sync_from, sync_from_all)
if placement_target:
self.add_placement_targets_storage_class_zone(