def setup_multisite_replication(self, daemon_name=None, realm_name=None, zonegroup_name=None,
zonegroup_endpoints=None, zone_name=None, zone_endpoints=None,
username=None, cluster_fsid=None, replication_zone_name=None,
- cluster_details=None):
+ cluster_details=None, selectedRealmName=None):
multisite_instance = RgwMultisiteAutomation()
result = multisite_instance.setup_multisite_replication(realm_name, zonegroup_name,
zonegroup_endpoints, zone_name,
zone_endpoints, username,
cluster_fsid,
replication_zone_name,
- cluster_details)
+ cluster_details,
+ selectedRealmName)
return result
@RESTController.Collection(method='PUT', path='/setup-rgw-credentials')
StepTitles.CreateZone,
StepTitles.Review
];
+
+export const STEP_TITLES_EXISTING_REALM = [
+ StepTitles.CreateRealmAndZonegroup,
+ StepTitles.SelectCluster,
+ StepTitles.Review
+];
later to manually import into a desired cluster to establish replication
between the clusters.
</cd-alert-panel>
- <div class="form-group row">
+ <div class="form-group row"
+ *ngIf="showConfigType && isMultiClusterConfigured">
<label class="cd-col-form-label required"
- for="realmName"
- i18n>Realm Name</label>
- <div class="cd-col-form-input">
- <input class="form-control"
- type="text"
- placeholder="Realm name..."
- id="realmName"
- name="realmName"
- formControlName="realmName">
- <cd-help-text>
- <span i18n>Enter a unique name for the Realm. The Realm is a logical grouping of all your Zonegroups.</span>
- </cd-help-text>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('realmName', formDir, 'required')"
- i18n>This field is required.</span>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('realmName', formDir, 'uniqueName')"
- i18n>The chosen realm name is already in use.</span>
+ for="configType"
+ i18n>Realm configuration mode</label>
+ <div class="col-md-auto custom-checkbox form-check-inline ms-3">
+ <input class="form-check-input"
+ formControlName="configType"
+ id="newRealm"
+ value="newRealm"
+ (change)="onConfigTypeChange()"
+ type="radio">
+ <label class="custom-check-label"
+ for="newRealm"
+ i18n>Create new realm/zonegroup/zone</label>
</div>
- </div>
- <div class="form-group row">
- <label class="cd-col-form-label required"
- for="zonegroupName"
- i18n>Zone Group Name</label>
- <div class="cd-col-form-input">
- <input class="form-control"
- type="text"
- placeholder="Zone group name..."
- id="zonegroupName"
- name="zonegroupName"
- formControlName="zonegroupName">
- <cd-help-text>
- <span i18n>Enter a name for the Zonegroup. Zonegroup will help you identify and manage the group of zones.</span>
- </cd-help-text>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('zonegroupName', formDir, 'required')"
- i18n>This field is required.</span>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('zonegroupName', formDir, 'uniqueName')"
- i18n>The chosen zone group name is already in use.</span>
+ <div class="col-md-auto custom-checkbox form-check-inline">
+ <input class="form-check-input"
+ formControlName="configType"
+ id="existingRealm"
+ type="radio"
+ (change)="onConfigTypeChange()"
+ value="existingRealm">
+ <label class="custom-check-label"
+ for="existingRealm"
+ i18n>Select existing realm</label>
</div>
</div>
- <div class="form-group row">
- <label class="cd-col-form-label required"
- for="zonegroup_endpoints"
- i18n>Zonegroup Endpoints</label>
+ <div class="form-group row"
+ *ngIf="multisiteSetupForm.get('configType').value === 'existingRealm' && showConfigType && isMultiClusterConfigured">
+ <label class="cd-col-form-label"
+ for="selectedRealm"
+ i18n>Select Realm</label>
<div class="cd-col-form-input">
- <cd-select-badges id="zonegroup_endpoints"
- [data]="rgwEndpoints.value"
- [options]="rgwEndpoints.options"
- [customBadges]="true">
- </cd-select-badges>
- <cd-help-text>
- <span i18n>Select the endpoints for the Zonegroup. Endpoints are the URLs or IP addresses from which the rgw gateways in that zonegroup can be accessed. You can select multiple endpoints in case you have multiple rgw gateways in a zonegroup</span>
- </cd-help-text>
+ <select class="form-select"
+ id="selectedRealm"
+ formControlName="selectedRealm">
+ <option *ngFor="let realm of realmsInfo"
+ [value]="realm.realm">
+ {{ realm.realm }}
+ </option>
+ </select>
</div>
</div>
- </div>
- <div *ngSwitchCase="1"
- class="ms-5">
- <div class="form-group row">
- <label class="cd-col-form-label required"
- for="zonegroupName"
- i18n>Zone Name</label>
- <div class="cd-col-form-input">
- <input class="form-control"
- type="text"
- placeholder="Zone name..."
- id="zoneName"
- name="zoneName"
- formControlName="zoneName">
- <cd-help-text>
- <span i18n>Enter a unique name for the Zone. A Zone represents a distinct data center or geographical location within a Zonegroup.</span>
- </cd-help-text>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('zoneName', formDir, 'required')"
- i18n>This field is required.</span>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('zoneName', formDir, 'uniqueName')"
- i18n>The chosen zone name is already in use.</span>
+ <div *ngIf="multisiteSetupForm.get('configType').value === 'newRealm' || !showConfigType">
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="realmName"
+ i18n>Realm Name</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ id="realmName"
+ formControlName="realmName">
+ <cd-help-text>
+ <span i18n>Enter a unique name for the Realm. The Realm is a logical grouping of all your Zonegroups.</span>
+ </cd-help-text>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('realmName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('realmName', formDir, 'uniqueName')"
+ i18n>This realm name is already in use. Choose a unique name.</span>
+ </div>
</div>
- </div>
- <div class="form-group row">
- <label class="cd-col-form-label required"
- for="zone_endpoints"
- i18n>Zone Endpoints</label>
- <div class="cd-col-form-input">
- <cd-select-badges id="zone_endpoints"
- [data]="rgwEndpoints.value"
- [options]="rgwEndpoints.options"
- [customBadges]="true">
- </cd-select-badges>
- <cd-help-text>
- <span i18n>Select the endpoints for the Zone. Endpoints are the URLs or IP addresses from which the rgw gateways in that zone can be accessed. You can select multiple endpoints in case you have multiple rgw gateways in a zone</span>
- </cd-help-text>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="zonegroupName"
+ i18n>Zone Group Name</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ id="zonegroupName"
+ formControlName="zonegroupName">
+ <cd-help-text>
+ <span i18n>Enter a name for the Zonegroup. Zonegroup will help you identify and manage the group of zones.</span>
+ </cd-help-text>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('zonegroupName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('zonegroupName', formDir, 'uniqueName')"
+ i18n>This zonegroup name is already in use. Choose a unique name.</span>
+ </div>
</div>
- </div>
- <div class="form-group row">
- <label class="cd-col-form-label required"
- for="username"
- i18n>Username</label>
- <div class="cd-col-form-input">
- <input class="form-control"
- type="text"
- placeholder="Username..."
- id="username"
- name="username"
- formControlName="username"
- ngbTooltip="White spaces at the beginning and end will be trimmed"
- i18n-ngbTooltip
- cdTrim>
- <cd-help-text>
- <span i18n>Specify the username for the system user.</span>
- </cd-help-text>
- <cd-alert-panel type="info"
- [showTitle]="false">
- <span i18n>This user will be created automatically as part of the process, and it will have the necessary permissions to manage and synchronize resources across zones.</span>
- </cd-alert-panel>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('username', formDir, 'required')"
- i18n>This field is required.</span>
- <span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('username', formDir, 'notUnique')"
- i18n>The username already exists.</span>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="zonegroup_endpoints"
+ i18n>Zonegroup Endpoints</label>
+ <div class="cd-col-form-input">
+ <cd-select-badges id="zonegroup_endpoints"
+ [data]="rgwEndpoints.value"
+ [options]="rgwEndpoints.options"
+ [customBadges]="true">
+ </cd-select-badges>
+ <cd-help-text>
+ <span i18n>Select the endpoints for the Zonegroup. Endpoints are the URLs or IP addresses from which the rgw gateways in that zonegroup can be accessed. You can select multiple endpoints in case you have multiple rgw gateways in a zonegroup</span>
+ </cd-help-text>
+ </div>
</div>
</div>
</div>
- <div cass="ms-5"
- *ngSwitchCase="2">
- <div *ngIf="isMultiClusterConfigured; else nonMultiClusterTemplate">
+ <ng-container *ngSwitchCase="1">
+ <div *ngIf="multisiteSetupForm.get('configType').value === 'newRealm'"
+ class="ms-5">
<div class="form-group row">
<label class="cd-col-form-label required"
- for="cluster"
- i18n>Replication Cluster</label>
+ for="zonegroupName"
+ i18n>Zone Name</label>
<div class="cd-col-form-input">
- <select class="form-select"
- id="cluster"
- [(ngModel)]="selectedCluster"
- formControlName="cluster"
- name="cluster">
- <option *ngFor="let cluster_detail of clusterDetailsArray"
- [value]="cluster_detail.name">
- {{ cluster_detail.cluster_alias }} - {{ cluster_detail.name }}
- </option>
- </select>
+ <input class="form-control"
+ type="text"
+ id="zoneName"
+ formControlName="zoneName">
<cd-help-text>
- <span i18n>Choose the cluster where you want to apply this multisite configuration. The selected cluster will integrate the defined Realm, Zonegroup, and Zones, enabling data synchronization and management across the multisite setup.</span>
+ <span i18n>Enter a unique name for the Zone. A Zone represents a distinct data center or geographical location within a Zonegroup.</span>
</cd-help-text>
- <cd-alert-panel type="info"
- [showTitle]="false">
- <span i18n>Before submitting this form, please verify that the selected cluster has an active RGW (Rados Gateway) service running.</span>
- </cd-alert-panel>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('zoneName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('zoneName', formDir, 'uniqueName')"
+ i18n>This zone name is already in use. Choose a unique name.</span>
</div>
</div>
<div class="form-group row">
<label class="cd-col-form-label required"
- for="zonegroupName"
- i18n>Replication Zone Name</label>
+ for="zone_endpoints"
+ i18n>Zone Endpoints</label>
+ <div class="cd-col-form-input">
+ <cd-select-badges id="zone_endpoints"
+ [data]="rgwEndpoints.value"
+ [options]="rgwEndpoints.options"
+ [customBadges]="true"></cd-select-badges>
+ <cd-help-text>
+ <span i18n>Select the endpoints for the Zone. Endpoints are the URLs or IP addresses from which the rgw gateways in that zone can be accessed. You can select multiple endpoints in case you have multiple rgw gateways in a zone</span>
+ </cd-help-text>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="username"
+ i18n>Username</label>
<div class="cd-col-form-input">
<input class="form-control"
type="text"
- placeholder="Zone name..."
- id="replicationZoneName"
- name="replicationZoneName"
- formControlName="replicationZoneName">
+ id="username"
+ formControlName="username"
+ ngbTooltip="White spaces at the beginning and end will be trimmed"
+ i18n-ngbTooltip
+ cdTrim>
<cd-help-text>
- <span i18n>Replication zone represents the zone to be created in the replication cluster where your data will be replicated.</span>
+ <span i18n>Specify the username for the system user.</span>
</cd-help-text>
+ <cd-alert-panel type="info"
+ [showTitle]="false">
+ <span i18n>This user will be created automatically as part of the process, and it will have the necessary permissions to manage and synchronize resources across zones.</span>
+ </cd-alert-panel>
<span class="invalid-feedback"
- *ngIf="multisiteSetupForm.showError('replicationZoneName', formDir, 'required')"
+ *ngIf="multisiteSetupForm.showError('username', formDir, 'required')"
i18n>This field is required.</span>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('username', formDir, 'notUnique')"
+ i18n>This username is already in use. Choose a unique name.</span>
</div>
</div>
</div>
- </div>
+ <div *ngIf="isMultiClusterConfigured && (multisiteSetupForm.get('configType').value === 'existingRealm')"
+ class="ms-5">
+ <ng-container *ngTemplateOutlet="replicationTemplate"></ng-container>
+ </div>
+ </ng-container>
+ <ng-container *ngSwitchCase="2">
+ <div *ngIf="multisiteSetupForm.get('configType').value === 'newRealm'"
+ class="ms-5">
+ <ng-container *ngIf="isMultiClusterConfigured; else newRealmReviewTemplate">
+ <ng-container *ngTemplateOutlet="replicationTemplate"></ng-container>
+ </ng-container>
+ </div>
+ <div *ngIf="multisiteSetupForm.get('configType').value === 'existingRealm' && isMultiClusterConfigured"
+ class="ms-5">
+ <ng-container *ngIf="!loading; else loadingTemplate">
+ <ng-container *ngIf="!setupCompleted; else progressCompleteTemplate">
+ <ng-container *ngTemplateOutlet="reviewTemplate"></ng-container>
+ </ng-container>
+ </ng-container>
+ </div>
+ </ng-container>
+ <ng-template #newRealmReviewTemplate>
+ <ng-container *ngTemplateOutlet="reviewTemplate"></ng-container>
+ </ng-template>
+ <ng-template #replicationTemplate>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="cluster"
+ i18n>Replication Cluster</label>
+ <div class="cd-col-form-input">
+ <select class="form-select"
+ id="cluster"
+ [(ngModel)]="selectedCluster"
+ formControlName="cluster"
+ name="cluster">
+ <option *ngFor="let cluster_detail of clusterDetailsArray"
+ [value]="cluster_detail.name">
+ {{ cluster_detail.cluster_alias }} - {{ cluster_detail.name }}
+ </option>
+ </select>
+ <cd-help-text>
+ <span i18n>Choose the cluster where you want to apply this multisite configuration. The selected cluster will integrate the defined Realm, Zonegroup, and Zones, enabling data synchronization and management across the multisite setup.</span>
+ </cd-help-text>
+ <cd-alert-panel type="info"
+ [showTitle]="false">
+ <span i18n>Before submitting this form, please verify that the selected cluster has an active RGW (Rados Gateway) service running.</span>
+ </cd-alert-panel>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="replicationZoneName"
+ i18n>Replication Zone Name</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ id="replicationZoneName"
+ name="replicationZoneName"
+ formControlName="replicationZoneName">
+ <cd-help-text>
+ <span i18n>Replication zone represents the zone to be created in the replication cluster where your data will be replicated.</span>
+ </cd-help-text>
+ <span class="invalid-feedback"
+ *ngIf="multisiteSetupForm.showError('replicationZoneName', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+ </ng-template>
<div *ngSwitchCase="3"
class="ms-5">
<div *ngIf="isMultiClusterConfigured">
name="skip-cluster-selection"
aria-label="Skip"
(click)="onSkip()"
- *ngIf="stepTitles[currentStep.stepIndex]['label'] === 'Select Cluster'"
+ *ngIf="stepTitles[currentStep.stepIndex]['label'] === 'Select Cluster' && multisiteSetupForm.get('configType').value === 'newRealm'"
i18n>Skip</button>
<button cdsButton="secondary"
(click)="onPreviousStep()"
[attr.aria-label]="showCancelButtonLabel()"
- [disabled]="loading"
i18n>{{ showCancelButtonLabel() }}</button>
<button cdsButton="primary"
(click)="onNextStep()"
<cds-loading [isActive]="loading"
[overlay]="false"
size="sm"
- *ngIf="loading"></cds-loading>
+ *ngIf="loading">
+ </cds-loading>
</button>
</cds-modal-footer>
</cds-modal>
+
<ng-template #nonMultiClusterTemplate>
<ng-container *ngIf="!loading; else loadingTemplate">
<ng-container *ngIf="!setupCompleted else exportTokenTemplate">
</ng-template>
<ng-template #reviewTemplate>
+ <ng-container [ngSwitch]="multisiteSetupForm.get('configType').value">
+ <ng-container *ngSwitchCase="'newRealm'">
+ <ng-container *ngTemplateOutlet="newRealmInfo"></ng-container>
+ <ng-container *ngTemplateOutlet="replicationInfo"></ng-container>
+ </ng-container>
+ <ng-container *ngSwitchCase="'existingRealm'">
+ <ng-container *ngTemplateOutlet="existingRealmInfo"></ng-container>
+ <ng-container *ngTemplateOutlet="replicationInfo"></ng-container>
+ </ng-container>
+ </ng-container>
+</ng-template>
+
+<ng-template #newRealmInfo>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Realm Name:</label>
- <div class="cd-col-form-input mt-2 text-muted"
- id="realmName">
- <b>{{ multisiteSetupForm.get('realmName').value }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ multisiteSetupForm.get('realmName').value }}</b></div>
</div>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Zonegroup Name:</label>
- <div class="cd-col-form-input mt-2 text-muted"
- id="zonegroupName">
- <b>{{ multisiteSetupForm.get('zonegroupName').value }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ multisiteSetupForm.get('zonegroupName').value }}</b></div>
</div>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Zonegroup Endpoints:</label>
- <div class="cd-col-form-input mt-2 text-muted">
- <b>{{ rgwEndpoints.value.join(', ') }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ rgwEndpoints.value.join(', ') }}</b></div>
</div>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Zone Name:</label>
- <div class="cd-col-form-input mt-2 text-muted"
- id="zoneName">
- <b>{{ multisiteSetupForm.get('zoneName').value }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ multisiteSetupForm.get('zoneName').value }}</b></div>
</div>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Zone Endpoints:</label>
- <div class="cd-col-form-input mt-2 text-muted">
- <b>{{ rgwEndpoints.value.join(', ') }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ rgwEndpoints.value.join(', ') }}</b></div>
</div>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Username:</label>
- <div class="cd-col-form-input mt-2 text-muted">
- <b>{{ multisiteSetupForm.get('username').value }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ multisiteSetupForm.get('username').value }}</b></div>
</div>
+</ng-template>
+
+<ng-template #existingRealmInfo>
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ i18n>Selected Realm:</label>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ multisiteSetupForm.get('selectedRealm').value }}</b></div>
+ </div>
+</ng-template>
+
+<ng-template #replicationInfo>
<div *ngIf="isMultiClusterConfigured && !stepsToSkip['Select Cluster']">
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Selected Replication Cluster:</label>
- <div class="cd-col-form-input mt-2 text-muted">
- <b>{{ selectedCluster }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ selectedCluster }}</b></div>
</div>
<div class="form-group row">
<label class="cd-col-form-label"
i18n>Replication Zone Name:</label>
- <div class="cd-col-form-input mt-2 text-muted">
- <b>{{ multisiteSetupForm.get('replicationZoneName').value }}</b>
- </div>
+ <div class="cd-col-form-input mt-2 text-muted"><b>{{ multisiteSetupForm.get('replicationZoneName').value }}</b></div>
</div>
</div>
</ng-template>
-import { Component, OnInit } from '@angular/core';
+import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { UntypedFormControl, Validators } from '@angular/forms';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
-import { Subscription, forkJoin } from 'rxjs';
+import { Observable, Subscription, forkJoin } from 'rxjs';
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { WizardStepModel } from '~/app/shared/models/wizard-steps';
import { SummaryService } from '~/app/shared/services/summary.service';
import { ExecutingTask } from '~/app/shared/models/executing-task';
import {
+ STEP_TITLES_EXISTING_REALM,
STEP_TITLES_MULTI_CLUSTER_CONFIGURED,
STEP_TITLES_SINGLE_CLUSTER
} from './multisite-wizard-steps.enum';
+import { RgwRealmService } from '~/app/shared/api/rgw-realm.service';
+import { MultiCluster, MultiClusterConfig } from '~/app/shared/models/multi-cluster';
+
+interface DaemonStats {
+ rgw_metadata?: {
+ [key: string]: string;
+ };
+}
+
+interface EndpointInfo {
+ hostname: string;
+ port: number;
+ frontendConfig: string;
+}
+
+enum Protocol {
+ HTTP = 'http',
+ HTTPS = 'https'
+}
+
+enum ConfigType {
+ NewRealm = 'newRealm',
+ ExistingRealm = 'existingRealm'
+}
@Component({
selector: 'cd-rgw-multisite-wizard',
stepsToSkip: { [steps: string]: boolean } = {};
daemons: RgwDaemon[] = [];
selectedCluster = '';
- clusterDetailsArray: any;
+ clusterDetailsArray: MultiCluster[] = [];
isMultiClusterConfigured = false;
exportTokenForm: CdFormGroup;
realms: any;
rgwEndpoints: { value: any[]; options: any[]; messages: any };
executingTask: ExecutingTask;
setupCompleted = false;
+ showConfigType = false;
+ realmList: string[] = [];
+ realmsInfo: { realm: string; token: string }[];
constructor(
private wizardStepsService: WizardStepsService,
private rgwDaemonService: RgwDaemonService,
private multiClusterService: MultiClusterService,
private rgwMultisiteService: RgwMultisiteService,
+ private rgwRealmService: RgwRealmService,
public notificationService: NotificationService,
private route: ActivatedRoute,
private summaryService: SummaryService,
- private location: Location
+ private location: Location,
+ private cdr: ChangeDetectorRef
) {
super();
this.pageURL = 'rgw/multisite/configuration';
ngOnInit(): void {
this.open = this.route.outlet === 'modal';
- this.rgwDaemonService
- .list()
- .pipe(
- switchMap((daemons) => {
- this.daemons = daemons;
- const daemonStatsObservables = daemons.map((daemon) =>
- this.rgwDaemonService.get(daemon.id).pipe(
- map((daemonStats) => ({
- hostname: daemon.server_hostname,
- port: daemon.port,
- frontendConfig: daemonStats['rgw_metadata']['frontend_config#0']
- }))
- )
- );
- return forkJoin(daemonStatsObservables);
- })
- )
- .subscribe((daemonStatsArray) => {
- this.rgwEndpoints.value = daemonStatsArray.map((daemonStats) => {
- const protocol = daemonStats.frontendConfig.includes('ssl_port') ? 'https' : 'http';
- return `${protocol}://${daemonStats.hostname}:${daemonStats.port}`;
- });
- const options: SelectOption[] = this.rgwEndpoints.value.map(
- (endpoint: string) => new SelectOption(false, endpoint, '')
- );
- this.rgwEndpoints.options = [...options];
- });
-
- this.multiClusterService.getCluster().subscribe((clusters) => {
+ this.loadRGWEndpoints();
+ this.multiClusterService.getCluster().subscribe((clusters: MultiClusterConfig) => {
+ const currentUrl = clusters['current_url'];
this.clusterDetailsArray = Object.values(clusters['config'])
.flat()
- .filter((cluster) => cluster['url'] !== clusters['current_url']);
+ .filter((cluster) => cluster['url'] !== currentUrl);
this.isMultiClusterConfigured = this.clusterDetailsArray.length > 0;
- if (!this.isMultiClusterConfigured) {
- this.stepTitles = STEP_TITLES_SINGLE_CLUSTER.map((title) => ({
- label: title
- }));
- this.stepTitles.forEach((steps, index) => {
- steps.onClick = () => (this.currentStep.stepIndex = index);
- });
- } else {
- this.selectedCluster = this.clusterDetailsArray[0]['name'];
- }
+ this.stepTitles = (this.isMultiClusterConfigured
+ ? STEP_TITLES_MULTI_CLUSTER_CONFIGURED
+ : STEP_TITLES_SINGLE_CLUSTER
+ ).map((label, index) => ({
+ label,
+ onClick: () => (this.currentStep.stepIndex = index)
+ }));
this.wizardStepsService.setTotalSteps(this.stepTitles.length);
+ this.selectedCluster = this.isMultiClusterConfigured
+ ? this.clusterDetailsArray[0]['name']
+ : null;
});
this.summaryService.subscribe((summary) => {
- this.executingTask = summary.executing_tasks.filter((tasks) =>
- tasks.name.includes('progress/Multisite-Setup')
- )[0];
+ this.executingTask = summary.executing_tasks.find((task) =>
+ task.name.includes('progress/Multisite-Setup')
+ );
+ });
+
+ this.stepTitles.forEach((step) => {
+ this.stepsToSkip[step.label] = false;
});
- this.stepTitles.forEach((stepTitle) => {
- this.stepsToSkip[stepTitle.label] = false;
+ this.rgwRealmService.getRealmTokens().subscribe((data: { realm: string; token: string }[]) => {
+ const base64Matcher = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/;
+ this.realmsInfo = data.filter((realmInfo) => base64Matcher.test(realmInfo.token));
+ this.showConfigType = this.realmsInfo.length > 0;
+ if (this.showConfigType) {
+ this.multisiteSetupForm.get('selectedRealm')?.setValue(this.realmsInfo[0].realm);
+ this.cdr.detectChanges();
+ }
});
}
+ private loadRGWEndpoints(): void {
+ this.rgwDaemonService
+ .list()
+ .pipe(
+ switchMap((daemons: RgwDaemon[]) => {
+ this.daemons = daemons;
+ return this.fetchDaemonStats(daemons);
+ })
+ )
+ .subscribe((daemonStatsArray: EndpointInfo[]) => {
+ this.populateRGWEndpoints(daemonStatsArray);
+ });
+ }
+
+ private fetchDaemonStats(daemons: RgwDaemon[]): Observable<EndpointInfo[]> {
+ const observables = daemons.map((daemon) =>
+ this.rgwDaemonService.get(daemon.id).pipe(
+ map((daemonStats: DaemonStats) => ({
+ hostname: daemon.server_hostname,
+ port: daemon.port,
+ frontendConfig: daemonStats?.rgw_metadata?.['frontend_config#0'] || ''
+ }))
+ )
+ );
+ return forkJoin(observables);
+ }
+
+ private populateRGWEndpoints(statsArray: EndpointInfo[]): void {
+ this.rgwEndpoints.value = statsArray.map((stats: EndpointInfo) => {
+ const protocol = stats.frontendConfig.includes('ssl_port') ? Protocol.HTTPS : Protocol.HTTP;
+ return `${protocol}://${stats.hostname}:${stats.port}`;
+ });
+ this.rgwEndpoints.options = this.rgwEndpoints.value.map(
+ (endpoint) => new SelectOption(false, endpoint, '')
+ );
+ this.cdr.detectChanges();
+ }
+
createForm() {
this.multisiteSetupForm = new CdFormGroup({
realmName: new UntypedFormControl('default_realm', {
}),
replicationZoneName: new UntypedFormControl('new_replicated_zone', {
validators: [Validators.required]
- })
+ }),
+ configType: new UntypedFormControl(ConfigType.NewRealm, {}),
+ selectedRealm: new UntypedFormControl(null, {})
});
if (!this.isMultiClusterConfigured) {
} else {
const cluster = values['cluster'];
const replicationZoneName = values['replicationZoneName'];
+ let selectedRealmName = '';
+ if (this.multisiteSetupForm.get('configType').value === ConfigType.ExistingRealm) {
+ selectedRealmName = this.multisiteSetupForm.get('selectedRealm').value;
+ }
this.rgwMultisiteService
.setUpMultisiteReplication(
realmName,
username,
cluster,
replicationZoneName,
- this.clusterDetailsArray
+ this.clusterDetailsArray,
+ selectedRealmName
)
.subscribe(
() => {
closeModal(): void {
this.location.back();
}
+
+ onConfigTypeChange() {
+ const configType = this.multisiteSetupForm.get('configType')?.value;
+ if (configType === ConfigType.ExistingRealm) {
+ this.stepTitles = STEP_TITLES_EXISTING_REALM.map((title) => ({
+ label: title
+ }));
+ this.stepTitles.forEach((steps, index) => {
+ steps.onClick = () => (this.currentStep.stepIndex = index);
+ });
+ } else if (this.isMultiClusterConfigured) {
+ this.stepTitles = STEP_TITLES_MULTI_CLUSTER_CONFIGURED.map((title) => ({
+ label: title
+ }));
+ } else {
+ this.stepTitles = STEP_TITLES_SINGLE_CLUSTER.map((title) => ({
+ label: title
+ }));
+ }
+ this.wizardStepsService.setTotalSteps(this.stepTitles.length);
+ }
}
username: string,
cluster?: string,
replicationZoneName?: string,
- clusterDetailsArray?: any
+ clusterDetailsArray?: any,
+ selectedRealmName?: string
) {
let params = new HttpParams()
.set('realm_name', realmName)
params = params.set('replication_zone_name', replicationZoneName);
}
+ if (selectedRealmName) {
+ params = params.set('selectedRealmName', selectedRealmName);
+ }
+
return this.http.post(`${this.uiUrl}/multisite-replications`, null, { params: params });
}
ssl_certificate: string;
ttl: number;
}
+
+export interface MultiClusterConfig {
+ current_url: string;
+ current_user: string;
+ hub_url: string;
+ config: {
+ [clusterId: string]: MultiCluster[];
+ };
+}
zone_endpoints: str, username: str,
cluster_fsid: Optional[str] = None,
replication_zone_name: Optional[str] = None,
- cluster_details: Optional[str] = None):
+ cluster_details: Optional[str] = None,
+ selectedRealmName: Optional[str] = None):
- # Set up multisite replication for Ceph RGW.
logger.info("Starting multisite replication setup")
- if cluster_details:
- cluster_details_dict = json.loads(cluster_details)
+
+ cluster_details_dict = json.loads(cluster_details) if cluster_details else {}
orch = OrchClient.instance()
- rgw_multisite_instance = RgwMultisite()
if cluster_fsid:
self.progress_total = 4
- def get_updated_endpoints(endpoints):
- # Update endpoint URLs by replacing hostnames with IP addresses.
- try:
- hostname_to_ip = {host['hostname']: host['addr'] for host in (h.to_json() for h in orch.hosts.list())} # noqa E501 # pylint: disable=line-too-long
- updated_endpoints = [self.replace_hostname(endpoint, hostname_to_ip) for endpoint in endpoints.split(',')] # noqa E501 # pylint: disable=line-too-long
- logger.debug("Updated endpoints: %s", updated_endpoints)
- return updated_endpoints
- except Exception as e:
- logger.error("Failed to update endpoints: %s", e)
- raise
-
- zonegroup_ip_url = ','.join(get_updated_endpoints(zonegroup_endpoints))
- zone_ip_url = ','.join(get_updated_endpoints(zone_endpoints))
- try:
- # Create the realm and zonegroup
- self.update_progress(
- f"Creating realm: {realm_name}, zonegroup: {zonegroup_name} and zone: {zone_name}")
- logger.info("Creating realm: %s", realm_name)
- rgw_multisite_instance.create_realm(realm_name=realm_name, default=True)
- logger.info("Creating zonegroup: %s", zonegroup_name)
- rgw_multisite_instance.create_zonegroup(realm_name=realm_name,
- zonegroup_name=zonegroup_name,
- default=True, master=True,
- endpoints=zonegroup_ip_url)
+ if selectedRealmName:
+ self.progress_total = 2
+
+ zonegroup_ip_url = ','.join(self.get_updated_endpoints(zonegroup_endpoints, orch))
+ zone_ip_url = ','.join(self.get_updated_endpoints(zone_endpoints, orch))
+
+ if not selectedRealmName:
+ self.create_realm_and_zonegroup(
+ realm_name, zonegroup_name, zone_name, zonegroup_ip_url)
+ self.create_zone_and_user(zone_name, zonegroup_name, username, zone_ip_url)
+ self.restart_daemons()
+
+ return self.export_and_import_realm(
+ realm_name, zonegroup_name, cluster_fsid, replication_zone_name,
+ cluster_details_dict, selectedRealmName, username
+ )
+
+ def get_updated_endpoints(self, endpoints: str, orch: OrchClient) -> list[str]:
+ try:
+ hostname_to_ip = {host['hostname']: host['addr'] for host in
+ (h.to_json() for h in orch.hosts.list())}
+ return [self.replace_hostname(endpoint, hostname_to_ip) for endpoint
+ in endpoints.split(',')]
+ except Exception as e:
+ logger.error("Failed to update endpoints: %s", e)
+ raise
+
+ def create_realm_and_zonegroup(self, realm: str, zg: str, zone: str, zg_url: str):
+ try:
+ rgw_multisite_instance = RgwMultisite()
+ self.update_progress(f"Creating realm: {realm}, zonegroup: {zg} and zone: {zone}")
+ rgw_multisite_instance.create_realm(realm_name=realm, default=True)
+ rgw_multisite_instance.create_zonegroup(realm_name=realm, zonegroup_name=zg,
+ default=True, master=True, endpoints=zg_url)
except Exception as e:
logger.error("Failed to create realm or zonegroup: %s", e)
self.update_progress("Failed to create realm or zonegroup", 'fail', str(e))
raise
+
+ def create_zone_and_user(self, zone: str, zg: str, username: str, zone_url: str):
try:
- # Create the zone and system user, then modify the zone with user credentials
- logger.info("Creating zone: %s", zone_name)
- if rgw_multisite_instance.create_zone(zone_name=zone_name,
- zonegroup_name=zonegroup_name,
- default=True, master=True,
- endpoints=zone_ip_url,
- access_key=None,
- secret_key=None):
+ rgw_multisite_instance = RgwMultisite()
+ if rgw_multisite_instance.create_zone(zone_name=zone, zonegroup_name=zg, default=True,
+ master=True, endpoints=zone_url,
+ access_key=None, secret_key=None):
self.progress_done += 1
- logger.info("Creating system user: %s", username)
- user_details = rgw_multisite_instance.create_system_user(username, zone_name)
- if user_details:
- keys = user_details['keys'][0]
- access_key = keys['access_key']
- secret_key = keys['secret_key']
- if access_key and secret_key:
- rgw_multisite_instance.modify_zone(zone_name=zone_name,
- zonegroup_name=zonegroup_name,
- default='true', master='true',
- endpoints=zone_ip_url,
- access_key=keys['access_key'],
- secret_key=keys['secret_key'])
- else:
- raise ValueError("Access key or secret key is missing")
+ user_details = rgw_multisite_instance.create_system_user(username, zone)
+ keys = user_details.get('keys', [{}])[0]
+ access_key = keys.get('access_key')
+ secret_key = keys.get('secret_key')
+ if access_key and secret_key:
+ rgw_multisite_instance.modify_zone(
+ zone_name=zone, zonegroup_name=zg, default='true',
+ master='true', endpoints=zone_url, access_key=access_key,
+ secret_key=secret_key)
+ else:
+ raise DashboardException("Access key or secret key is missing",
+ component='rgw', http_status_code=500)
except Exception as e:
logger.error("Failed to create zone or system user: %s", e)
- self.update_progress("Failed to create zone or system user:", 'fail', str(e))
+ self.update_progress("Failed to create zone or system user", 'fail', str(e))
raise
+
+ def restart_daemons(self):
try:
- logger.info("Restarting RGW daemons and setting credentials")
self.update_progress("Restarting RGW daemons and setting credentials")
- rgw_service_manager = RgwServiceManager()
- rgw_service_manager.restart_rgw_daemons_and_set_credentials()
+ RgwServiceManager().restart_rgw_daemons_and_set_credentials()
self.progress_done += 1
except Exception as e:
logger.error("Failed to restart RGW daemon: %s", e)
- self.update_progress("Failed to restart RGW daemons:", 'fail', str(e))
+ self.update_progress("Failed to restart RGW daemons", 'fail', str(e))
raise
+
+ def export_and_import_realm(self, realm: str, zg: str,
+ fsid: Optional[str], rep_zone: Optional[str],
+ details_dict: dict, selectedRealm: Optional[str],
+ username: str):
try:
- # Get realm tokens and import to another cluster if specified
- logger.info("Getting realm tokens")
realm_token_info = CephService.get_realm_tokens()
- logger.info("Realm tokens: %s", realm_token_info)
-
- if cluster_fsid and realm_token_info and replication_zone_name and cluster_details_dict:
- logger.info("Importing realm token to cluster: %s", cluster_fsid)
- self.update_progress(f"Importing realm token to cluster: {cluster_fsid}")
- self.import_realm_token_to_cluster(cluster_fsid, realm_name,
- zonegroup_name, realm_token_info,
- username, replication_zone_name,
- cluster_details_dict)
+ if fsid and realm_token_info and rep_zone and details_dict:
+ self.update_progress(f"Importing realm token to cluster: {fsid}")
+ self.import_realm_token_to_cluster(fsid, realm, zg, realm_token_info, username,
+ rep_zone, details_dict, selectedRealm)
else:
self.update_progress("Realm Export Token fetched successfully", 'complete')
+ logger.info("Multisite replication setup completed")
+ return realm_token_info
except Exception as e:
logger.error("Failed to get realm tokens or import to cluster: %s", e)
- self.update_progress("Failed to get realm tokens or import to cluster:", 'fail', str(e))
+ self.update_progress("Failed to get realm tokens or import to cluster",
+ 'fail', str(e))
raise
- logger.info("Multisite replication setup completed")
- return realm_token_info
def import_realm_token_to_cluster(self, cluster_fsid, realm_name, zonegroup_name,
realm_token_info, username, replication_zone_name,
- cluster_details):
+ cluster_details, selectedRealmName):
try:
- for realm_token in realm_token_info:
- if realm_token['realm'] == realm_name:
- realm_export_token = realm_token['token']
- break
- else:
- raise ValueError(f"Realm {realm_name} not found in realm tokens")
- for cluster in cluster_details:
- if cluster['name'] == cluster_fsid:
- cluster_token = cluster['token']
- cluster_url = cluster['url']
- break
- if cluster_token:
- if not cluster_url.endswith('/'):
- cluster_url += '/'
+ if selectedRealmName:
+ rgw_service_manager = RgwServiceManager()
+ username = rgw_service_manager.get_username_from_realm_name(selectedRealmName)
+ realm_name = selectedRealmName
+
+ realm_export_token = self._get_realm_export_token(realm_token_info, realm_name)
+ cluster_url, cluster_token = self._get_cluster_details(cluster_fsid, cluster_details)
+
+ self._configure_selected_cluster(cluster_url, cluster_token, realm_name,
+ zonegroup_name, replication_zone_name)
+
+ token_import_response = self._import_realm_token(
+ cluster_url, cluster_token, realm_export_token,
+ replication_zone_name)
+
+ self.progress_done += 1
+ self.update_progress(f"Checking for user {username} in the selected cluster \
+ and setting credentials")
+
+ self._verify_user_and_daemons(cluster_url, cluster_token, realm_name,
+ replication_zone_name, username)
+
+ return token_import_response
- path = 'api/rgw/realm/import_realm_token'
- try:
- multi_cluster_instance = MultiCluster()
- daemon_name = f"{realm_name}.{replication_zone_name}"
- # pylint: disable=protected-access
- config_payload = {
- 'realm_name': realm_name,
- 'zonegroup_name': zonegroup_name,
- 'zone_name': replication_zone_name,
- 'daemon_name': daemon_name,
- }
- config_info = multi_cluster_instance._proxy(method='PUT', base_url=cluster_url,
- path='api/rgw/daemon/set_multisite_config', # noqa E501 # pylint: disable=line-too-long
- payload=config_payload,
- token=cluster_token)
- logger.info("setting config response: %s", config_info)
- available_port = multi_cluster_instance._proxy(method='GET',
- base_url=cluster_url,
- path='ui-api/rgw/multisite/available-ports', # noqa E501 # pylint: disable=line-too-long
- token=cluster_token)
- placement_spec: Dict[str, Dict] = {"placement": {}}
- payload = {
- 'realm_token': realm_export_token,
- 'zone_name': replication_zone_name,
- 'port': available_port,
- 'placement_spec': placement_spec,
- }
- token_import_response = multi_cluster_instance._proxy(method='POST',
- base_url=cluster_url,
- path=path,
- payload=payload,
- token=cluster_token)
- logger.info("Import realm token response: %s", token_import_response)
- self.progress_done += 1
- self.update_progress(f"Checking for user {username} in the selected cluster and setting credentials") # noqa E501 # pylint: disable=line-too-long
- service_name = f"rgw.{daemon_name}"
- daemons_status = multi_cluster_instance._proxy(method='GET',
- base_url=cluster_url,
- path=f'ui-api/rgw/multisite/check-daemons-status?service_name={service_name}', # noqa E501 # pylint: disable=line-too-long
- token=cluster_token)
- logger.info("Daemons status: %s", daemons_status)
- realms_list = multi_cluster_instance._proxy(
- method='GET',
- base_url=cluster_url,
- path='api/rgw/realm',
- token=cluster_token
- )
- logger.debug("Realms info in the selected cluster: %s", realms_list)
- system_user_param = "realmName" if realms_list.get('default_info') \
- else "zoneName"
- if daemons_status is True:
- self.check_user_in_second_cluster(cluster_url, cluster_token,
- username, replication_zone_name,
- system_user_param, realm_name)
- else:
- self.update_progress("Failed to set credentials in selected cluster", 'fail', "RGW daemons failed to start") # noqa E501 # pylint: disable=line-too-long
- return token_import_response
- except requests.RequestException as e:
- logger.error("Could not reach %s: %s", cluster_url, e)
- raise DashboardException(f"Could not reach {cluster_url}: {e}",
- http_status_code=404, component='dashboard')
- except json.JSONDecodeError as e:
- logger.error("Error parsing Dashboard API response: %s", e.msg)
- raise DashboardException(f"Error parsing Dashboard API response: {e.msg}",
- component='dashboard')
except Exception as e:
logger.error("Failed to import realm token to cluster: %s", e)
self.update_progress("Failed to import realm token to cluster:", 'fail', str(e))
raise
+ def _get_realm_export_token(self, realm_token_info, realm_name):
+ for realm_token in realm_token_info:
+ if realm_token['realm'] == realm_name:
+ return realm_token['token']
+ raise DashboardException('Realm token not found',
+ http_status_code=500, component='rgw')
+
+ def _get_cluster_details(self, cluster_fsid, cluster_details):
+ for cluster in cluster_details:
+ if cluster['name'] == cluster_fsid:
+ cluster_url = cluster['url'].rstrip('/') + '/'
+ return cluster_url, cluster['token']
+ raise DashboardException("Cluster details not found",
+ http_status_code=500, component='rgw')
+
+ def _configure_selected_cluster(self, cluster_url, cluster_token, realm_name,
+ zonegroup_name, replication_zone_name):
+ daemon_name = f"{realm_name}.{replication_zone_name}"
+ config_payload = {
+ 'realm_name': realm_name,
+ 'zonegroup_name': zonegroup_name,
+ 'zone_name': replication_zone_name,
+ 'daemon_name': daemon_name,
+ }
+ multi_cluster_instance = MultiCluster()
+ # pylint: disable=protected-access
+ config_info = multi_cluster_instance._proxy(method='PUT', base_url=cluster_url,
+ path='api/rgw/daemon/set_multisite_config',
+ payload=config_payload,
+ token=cluster_token)
+ logger.info("setting config response: %s", config_info)
+
+ def _import_realm_token(self, cluster_url, cluster_token, realm_token, zone_name):
+ multi_cluster_instance = MultiCluster()
+ # pylint: disable=protected-access
+ available_port = multi_cluster_instance._proxy(
+ method='GET', base_url=cluster_url, path='ui-api/rgw/multisite/available-ports',
+ token=cluster_token)
+ payload = {
+ 'realm_token': realm_token,
+ 'zone_name': zone_name,
+ 'port': available_port,
+ 'placement_spec': {"placement": {}}
+ }
+ # pylint: disable=protected-access
+ token_import_response = multi_cluster_instance._proxy(
+ method='POST', base_url=cluster_url, path='api/rgw/realm/import_realm_token',
+ payload=payload, token=cluster_token)
+ logger.info("Import realm token response: %s", token_import_response)
+ return token_import_response
+
+ def _verify_user_and_daemons(self, cluster_url, cluster_token, realm_name, zone_name,
+ username):
+ multi_cluster_instance = MultiCluster()
+ daemon_name = f"{realm_name}.{zone_name}"
+ service_name = f"rgw.{daemon_name}"
+ # pylint: disable=protected-access
+ daemons_status = multi_cluster_instance._proxy(
+ method='GET', base_url=cluster_url,
+ path=f'ui-api/rgw/multisite/check-daemons-status?service_name={service_name}',
+ token=cluster_token)
+ logger.debug("Daemons status: %s", daemons_status)
+ # pylint: disable=protected-access
+ realms_list = multi_cluster_instance._proxy(method='GET',
+ base_url=cluster_url,
+ path='api/rgw/realm',
+ token=cluster_token)
+ logger.debug("Realms info in the selected cluster: %s", realms_list)
+
+ system_user_param = "realmName" if realms_list.get('default_info') else "zoneName"
+
+ if daemons_status is True:
+ self.check_user_in_second_cluster(cluster_url, cluster_token, username, zone_name,
+ system_user_param, realm_name)
+ else:
+ self.update_progress("Failed to set credentials in selected cluster", 'fail',
+ "RGW daemons failed to start")
+
def check_user_in_second_cluster(self, cluster_url, cluster_token, username,
replication_zone_name, system_user_param,
realm_name):
user_found = True
logger.info("User %s found in the second cluster", username)
# pylint: disable=protected-access
- set_creds_cont = multi_cluster_instance._proxy(method='PUT', base_url=cluster_url, # noqa E501 # pylint: disable=line-too-long
- path='ui-api/rgw/multisite/setup-rgw-credentials', # noqa E501 # pylint: disable=line-too-long
- token=cluster_token) # noqa E501 # pylint: disable=line-too-long
- logger.info("set credentials in selected cluster response: %s", set_creds_cont) # noqa E501 # pylint: disable=line-too-long # noqa E501 # pylint: disable=line-too-long
+ set_creds_cont = multi_cluster_instance._proxy(
+ method='PUT', base_url=cluster_url,
+ path='ui-api/rgw/multisite/setup-rgw-credentials',
+ token=cluster_token)
+ logger.info("set credentials in selected cluster response: %s",
+ set_creds_cont)
self.progress_done += 1
self.update_progress("Multisite replication setup completed",
'complete')
rgw_hostname_setting = Settings.RGW_HOSTNAME_PER_DAEMON
rgw_hostname_setting.pop(daemon_name, None)
Settings.RGW_HOSTNAME_PER_DAEMON = rgw_hostname_setting
+
+ def get_username_from_realm_name(self, realm_name: str) -> str:
+ realm_period_info = {}
+ master_zone_info = {}
+ rgw_realm_period_cmd = ['period', 'get', '--rgw-realm', realm_name]
+ try:
+ exit_code, out, _ = mgr.send_rgwadmin_command(rgw_realm_period_cmd)
+ if exit_code > 0:
+ raise DashboardException('Unable to get realm period info',
+ http_status_code=500, component='rgw')
+ realm_period_info = out
+ except SubprocessError as error:
+ raise DashboardException(error, http_status_code=500, component='rgw')
+
+ if realm_period_info:
+ master_zone_id = realm_period_info.get('master_zone')
+ rgw_zone_info_cmd = ['zone', 'get', '--zone-id', master_zone_id]
+ try:
+ exit_code, out, _ = mgr.send_rgwadmin_command(rgw_zone_info_cmd)
+ if exit_code > 0:
+ raise DashboardException('Unable to get master zone info',
+ http_status_code=500, component='rgw')
+ master_zone_info = out
+ except SubprocessError as error:
+ raise DashboardException(error, http_status_code=500, component='rgw')
+
+ if master_zone_info:
+ access_key = master_zone_info['system_key']['access_key']
+ user_info = {}
+ rgw_user_info_cmd = ['user', 'info', '--access-key', access_key]
+ try:
+ exit_code, out, _ = mgr.send_rgwadmin_command(rgw_user_info_cmd)
+ if exit_code > 0:
+ raise DashboardException('Unable to get user info',
+ http_status_code=500, component='rgw')
+ user_info = out
+ except SubprocessError as error:
+ raise DashboardException(error, http_status_code=500, component='rgw')
+ if user_info:
+ user_id = user_info.get('user_id')
+ if user_id:
+ return user_id
+
+ raise DashboardException('Failed to retrieve user_id for realm',
+ http_status_code=500, component='rgw')