]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: make application field for pool creation mandatory 51566/head
authoravanthakkar <avanjohn@gmail.com>
Thu, 18 May 2023 12:14:50 +0000 (17:44 +0530)
committerAvan Thakkar <athakkar@redhat.com>
Tue, 18 Jun 2024 07:13:40 +0000 (12:43 +0530)
Fixes: https://tracker.ceph.com/issues/61238
Signed-off-by: avanthakkar <avanjohn@gmail.com>
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.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts

index d3176b61dfd62b30517c68e9e090b4c6ab303032..fbd5fe0ccdad54a5237cc21b3c2feb5d427a6c2d 100644 (file)
         </div>
         <!-- Applications -->
         <div class="form-group row">
-          <label i18n
-                 class="cd-col-form-label"
-                 for="applications">Applications</label>
+          <label class="cd-col-form-label required"
+                 for="applications">
+            <ng-container i18n>Applications</ng-container>
+            <cd-helper>
+              <span i18n>Pools need to be associated with an application before use</span>
+            </cd-helper>
+          </label>
           <div class="cd-col-form-input">
             <cd-select-badges id="applications"
+                              name="applications"
                               [customBadges]="true"
                               [customBadgeValidators]="data.applications.validators"
                               [messages]="data.applications.messages"
                title="Pools should be associated with an application tag"
                class="{{icons.warning}} icon-warning-color">
             </i>
+            <span class="invalid-feedback"
+                  *ngIf="!isApplicationsSelected && data.applications.selected <= 0"
+                  i18n>Application selection is required!</span>
           </div>
         </div>
         <!-- Mirroring -->
index 5556e4b2df44a2924223b283eed4c6cc4f06acbe..caf8c0b6a71a66a1c737bad5f625bcf4f369c20b 100644 (file)
@@ -1099,6 +1099,7 @@ describe('PoolFormComponent', () => {
         // Mock that no ec profiles exist
         infoReturn.erasure_code_profiles = [];
         setUpPoolComponent();
+        component.data.applications.selected = ['cephfs', 'rgw'];
         setMultipleValues({
           name: 'minECPool',
           poolType: 'erasure',
@@ -1108,37 +1109,46 @@ describe('PoolFormComponent', () => {
           pool: 'minECPool',
           pool_type: 'erasure',
           pg_autoscale_mode: 'off',
-          pg_num: 4
+          pg_num: 4,
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
       it('creates ec pool with erasure coded profile', () => {
+        component.data.applications.selected = ['cephfs', 'rgw'];
         const ecp = { name: 'ecpMinimalMock' };
         setMultipleValues({
           erasureProfile: ecp
         });
         expectEcSubmit({
-          erasure_code_profile: ecp.name
+          erasure_code_profile: ecp.name,
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
       it('creates ec pool with ec_overwrite flag', () => {
+        component.data.applications.selected = ['cephfs', 'rgw'];
         setMultipleValues({
           ecOverwrites: true
         });
         expectEcSubmit({
-          flags: ['ec_overwrites']
+          flags: ['ec_overwrites'],
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
       it('should ignore replicated set settings for ec pools', () => {
+        component.data.applications.selected = ['cephfs', 'rgw'];
         setMultipleValues({
           size: 2 // will be ignored
         });
-        expectEcSubmit({});
+        expectEcSubmit({
+          application_metadata: ['cephfs', 'rgw']
+        });
       });
 
       it('creates a pool with compression', () => {
+        component.data.applications.selected = ['cephfs', 'rgw'];
         setMultipleValues({
           mode: 'passive',
           algorithm: 'lz4',
@@ -1151,7 +1161,8 @@ describe('PoolFormComponent', () => {
           compression_algorithm: 'lz4',
           compression_min_blob_size: 4096,
           compression_max_blob_size: 4194304,
-          compression_required_ratio: 0.7
+          compression_required_ratio: 0.7,
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
@@ -1199,12 +1210,14 @@ describe('PoolFormComponent', () => {
           size: 2,
           pgNum: 32
         });
+        component.data.applications.selected = ['cephfs', 'rgw'];
         expectValidSubmit({
           pool: 'minRepPool',
           pool_type: 'replicated',
           pg_num: 32,
           pg_autoscale_mode: 'off',
-          size: 2
+          size: 2,
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
@@ -1218,8 +1231,10 @@ describe('PoolFormComponent', () => {
          *  if type `replicated` is set, pgNum will be set to 256 with the current rule for
          *  a replicated pool.
          */
+        component.data.applications.selected = ['cephfs', 'rgw'];
         expectReplicatedSubmit({
-          pg_num: 256
+          pg_num: 256,
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
@@ -1228,9 +1243,11 @@ describe('PoolFormComponent', () => {
           max_bytes: 1024 * 1024,
           max_objects: 3000
         });
+        component.data.applications.selected = ['cephfs', 'rgw'];
         expectReplicatedSubmit({
           quota_max_bytes: 1024 * 1024,
-          quota_max_objects: 3000
+          quota_max_objects: 3000,
+          application_metadata: ['cephfs', 'rgw']
         });
       });
 
@@ -1238,10 +1255,12 @@ describe('PoolFormComponent', () => {
         component.currentConfigurationValues = {
           rbd_qos_bps_limit: 55
         };
+        component.data.applications.selected = ['cephfs', 'rgw'];
         expectReplicatedSubmit({
           configuration: {
             rbd_qos_bps_limit: 55
-          }
+          },
+          application_metadata: ['cephfs', 'rgw']
         });
       });
     });
index a87aa6c019be3986be46a6afc999cf74248c816c..ed8bda277fd648515dabdad1c17004218c574341 100644 (file)
@@ -86,6 +86,7 @@ export class PoolFormComponent extends CdForm implements OnInit {
   ecpUsage: string[] = undefined; // Will only be set if a rule is used by some pool
   crushRuleMaxSize = 10;
   DEFAULT_RATIO = 0.875;
+  isApplicationsSelected = true;
 
   private modalSubscription: Subscription;
 
@@ -860,6 +861,9 @@ export class PoolFormComponent extends CdForm implements OnInit {
       if (apps.includes('rbd')) {
         pool['rbd_mirroring'] = this.form.getValue('rbdMirroring');
       }
+      this.isApplicationsSelected = true;
+    } else {
+      this.isApplicationsSelected = false;
     }
 
     // Only collect configuration data for replicated pools, as QoS cannot be configured on EC
@@ -868,6 +872,11 @@ export class PoolFormComponent extends CdForm implements OnInit {
       pool['configuration'] = this.currentConfigurationValues;
     }
 
+    if (!this.isApplicationsSelected) {
+      this.form.setErrors({ cdSubmitButton: true });
+      return;
+    }
+
     this.triggerApiTask(pool);
   }