]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add fields to EC profile form 58625/head
authorPedro Gonzalez Gomez <pegonzal@redhat.com>
Wed, 19 Jun 2024 20:23:11 +0000 (22:23 +0200)
committerPedro Gonzalez Gomez <pegonzal@redhat.com>
Tue, 16 Jul 2024 15:12:46 +0000 (17:12 +0200)
Fixes: https://tracker.ceph.com/issues/66571
Signed-off-by: Pedro Gonzalez Gomez <pegonzal@redhat.com>
(cherry picked from commit 8f7a5de584b04b1dcba04799d1d9301af325d64b)

 Conflicts:
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts

src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form-modal.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form-modal.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/models/erasure-code-profile.ts

index b186677c5c560f8a0f26147b7316f08c027a3af1..7888fa853e3dd0038086326451cd33ce7c11842f 100644 (file)
           </div>
         </div>
 
+        <div class="form-group row">
+          <label for="crushNumFailureDomains"
+                 class="cd-col-form-label">
+            <ng-container i18n>Crush num failure domain</ng-container>
+            <cd-helper [html]="tooltips.crushNumFailureDomains">
+            </cd-helper>
+          </label>
+          <div class="cd-col-form-input">
+            <input type="number"
+                   id="crushNumFailureDomains"
+                   name="crushNumFailureDomains"
+                   class="form-control"
+                   formControlName="crushNumFailureDomains"
+                   min="0">
+            <span class="invalid-feedback"
+                  *ngIf="form.showError('crushNumFailureDomains', frm, 'required')"
+                  i18n>This field is required when crush osds per failure domain is set!</span>
+          </div>
+        </div>
+
+        <div class="form-group row">
+          <label for="crushOsdsPerFailureDomain"
+                 class="cd-col-form-label">
+            <ng-container i18n>Crush osds per failure domain</ng-container>
+            <cd-helper [html]="tooltips.crushOsdsPerFailureDomain">
+            </cd-helper>
+          </label>
+          <div class="cd-col-form-input">
+            <input type="number"
+                   id="crushOsdsPerFailureDomain"
+                   name="crushOsdsPerFailureDomain"
+                   class="form-control"
+                   formControlName="crushOsdsPerFailureDomain"
+                   min="0">
+            <span class="invalid-feedback"
+                  *ngIf="form.showError('crushOsdsPerFailureDomain', frm, 'required')"
+                  i18n>This field is required when crush num failure domain is set!</span>
+          </div>
+        </div>
+
         <div class="form-group row"
              *ngIf="plugin === PLUGIN.LRC">
           <label for="crushLocality"
index 01f7dcb1ee94636bd2f994db5a1af792abbb925a..5982dfe24fb1f652e41c4149ba0d198a5dfe0bd5 100644 (file)
@@ -89,6 +89,14 @@ export class ErasureCodeProfileFormModalComponent
         [Validators.required, CdValidators.custom('max', () => this.baseValueValidation())]
       ],
       crushFailureDomain: '', // Will be preselected
+      crushNumFailureDomains: [
+        0,
+        CdValidators.requiredIf({ crushOsdsPerFailureDomain: { op: 'minValue', arg1: 1 } })
+      ],
+      crushOsdsPerFailureDomain: [
+        0,
+        CdValidators.requiredIf({ crushNumFailureDomains: { op: 'minValue', arg1: 1 } })
+      ],
       crushRoot: null, // Will be preselected
       crushDeviceClass: '', // Will be preselected
       directory: '',
@@ -448,6 +456,8 @@ export class ErasureCodeProfileFormModalComponent
   private extendJson(name: string, ecp: ErasureCodeProfile) {
     const differentApiAttributes = {
       crushFailureDomain: 'crush-failure-domain',
+      crushNumFailureDomains: 'crush-num-failure-domains',
+      crushOsdsPerFailureDomain: 'crush-osds-per-failure-domain',
       crushRoot: 'crush-root',
       crushDeviceClass: 'crush-device-class',
       packetSize: 'packetsize',
index 13103da324aab5cc3194e57701c93b96773942d7..2d6d0a7f5165ee4243bc269015104f43c7900c3b 100644 (file)
                 <select class="form-select"
                         id="erasureProfile"
                         name="erasureProfile"
-                        formControlName="erasureProfile">
+                        formControlName="erasureProfile"
+                        (change)="erasureProfileChange()">
                   <option *ngIf="!ecProfiles"
                           ngValue=""
                           i18n>Loading...</option>
                    for="crushRule"
                    i18n>Crush ruleset</label>
             <div class="cd-col-form-input">
-              <span class="form-text text-muted"
+              <span *ngIf="!msrCrush; else msrCrushText"
+                    class="form-text text-muted"
                     i18n>A new crush ruleset will be implicitly created.</span>
+              <ng-template #msrCrushText>
+                <span class="form-text text-muted"
+                      i18n>A new crush MSR ruleset will be implicitly created.
+                      When crush-osds-per-failure-domain or crush-num-failure-domains is specified</span>
+              </ng-template>
             </div>
           </div>
           <div class="form-group row"
index c91ca765367259823e54c319d21b824b0a121d18..1359a0a3f12355a15ffd6a55cf0d9b3528542974 100644 (file)
@@ -83,6 +83,7 @@ export class PoolFormComponent extends CdForm implements OnInit {
   crushUsage: string[] = undefined; // Will only be set if a rule is used by some pool
   ecpUsage: string[] = undefined; // Will only be set if a rule is used by some pool
   crushRuleMaxSize = 10;
+  msrCrush: boolean = false;
 
   private modalSubscription: Subscription;
 
@@ -194,6 +195,7 @@ export class PoolFormComponent extends CdForm implements OnInit {
       this.listenToChanges();
       this.setComplexValidators();
     });
+    this.erasureProfileChange();
   }
 
   private initInfo(info: PoolFormInfo) {
@@ -913,4 +915,12 @@ export class PoolFormComponent extends CdForm implements OnInit {
   appSelection() {
     this.form.get('name').updateValueAndValidity({ emitEvent: false, onlySelf: true });
   }
+
+  erasureProfileChange() {
+    const profile = this.form.get('erasureProfile').value;
+    if (profile) {
+      this.msrCrush =
+        profile['crush-num-failure-domains'] > 0 || profile['crush-osds-per-failure-domain'] > 0;
+    }
+  }
 }
index d2bd131a464c9e77cd02b8d544d4e6fd3a95a558..988a13de2a9369474de63ba25928454947f7ac8d 100644 (file)
@@ -84,6 +84,13 @@ export class ErasureCodeProfileService {
       domain. For instance, if the failure domain is host no two chunks will be stored on the same
       host. It is used to create a CRUSH rule step such as step chooseleaf host.`,
 
+    crushNumFailureDomains: $localize` Number of failure domains to map. Results in a CRUSH MSR rule being created.
+    Must be specified if crush-osds-per-failure-domain is specified.`,
+
+    crushOsdsPerFailureDomain: $localize`Maximum number of OSDs to place in each failure domain --
+     defaults to 1. Using a value greater than one will cause a CRUSH MSR rule to be created.
+      Must be specified if crush-num-failure-domains is specified.`,
+
     crushDeviceClass: $localize`Restrict placement to devices of a specific class
       (e.g., ssd or hdd), using the crush device class names in the CRUSH map.`,
 
index e2bd67418428657a8600b6e77cfe6e984360246f..65d098d9f04351bd8255d1eb04d09416559409e4 100644 (file)
@@ -194,6 +194,10 @@ export class CdValidators {
                   result = value.length >= prerequisite['arg1'];
                 }
                 break;
+              case 'minValue':
+                if (_.isNumber(value)) {
+                  result = value >= prerequisite['arg1'];
+                }
             }
             return result;
           }
index ea9985ccd499e87b8359fde90a53f86ae0a11b0a..c5e744632acd36aaea50cfe6e65ba07c7205266d 100644 (file)
@@ -12,6 +12,8 @@ export class ErasureCodeProfile {
   'crush-root'?: string;
   'crush-locality'?: string;
   'crush-failure-domain'?: string;
+  'crush-num-failure-domains'?: number;
+  'crush-osds-per-failure-domain'?: number;
   'crush-device-class'?: string;
   'directory'?: string;
 }