]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Configure NVMe/TCP 57801/head
authorAfreen <afreen23.git@gmail.com>
Fri, 31 May 2024 07:54:27 +0000 (13:24 +0530)
committerAfreen Misbah <afreen23.git@gmail.com>
Thu, 13 Jun 2024 13:02:37 +0000 (18:32 +0530)
Fixes https://tracker.ceph.com/issues/63686

- creation of Nvme-oF/TCP service
- deletion of Nvme-oF/TCP service
- edit/update Nvme-oF/TCP service
- added unit tests for Nvme-oF/TCP service
- changed Id -> Service Name
- added prefix of service type in service name (similar to <client.> in
  fs access)
- service name and pool are required fields for nvmeof
- placement count now takes default value as mentioned in cephadm
- slight refactors
- prepopulate serviceId for each service type setServiceId()
- in case serviceId is same as servcie type then do not add create service name with<servicetype>.<setrviceid> format

Signed-off-by: Afreen <afreen23.git@gmail.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts

index af6cd3963651a40fc8eb8f11d0256a4b395a9559..cb199fe4af4aec57d9d7dcc855389e4aabef2c42 100644 (file)
@@ -75,7 +75,7 @@
                       i18n>Loading...</option>
               <option *ngIf="pools !== null && pools.length === 0"
                       [ngValue]="null"
-                      i18n>-- No rbd pools available --</option>
+                      i18n>-- No block pools available --</option>
               <option *ngIf="pools !== null && pools.length > 0"
                       [ngValue]="null"
                       i18n>-- Select a pool --</option>
index e7278a09868c70f74bebc77b7140e187dd608004..62333d3391b747a7a06d821b18df092641f6e645 100644 (file)
@@ -15,6 +15,7 @@
              (click)="createMultisiteSetup()">
              Click here</a> to create a new Realm/Zone Group/Zone
         </cd-alert-panel>
+
         <!-- Service type -->
         <div class="form-group row">
           <label class="cd-col-form-label required"
@@ -25,7 +26,7 @@
                     name="service_type"
                     class="form-select"
                     formControlName="service_type"
-                    (change)="getServiceIds($event.target.value)">
+                    (change)="onServiceTypeChange($event.target.value)">
               <option i18n
                       [ngValue]="null">-- Select a service type --</option>
               <option *ngFor="let serviceType of serviceTypes"
         </div>
 
         <!-- backend_service -->
-          <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
-               class="form-group row">
-            <label i18n
-                   class="cd-col-form-label"
-                   [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
-                   for="backend_service">Backend Service</label>
-            <div class="cd-col-form-input">
-              <select id="backend_service"
-                      name="backend_service"
-                      class="form-select"
-                      formControlName="backend_service"
-                      (change)="prePopulateId()">
-                <option *ngIf="services === null"
-                        [ngValue]="null"
-                        i18n>Loading...</option>
-                <option *ngIf="services !== null && services.length === 0"
-                        [ngValue]="null"
-                        i18n>-- No service available --</option>
-                <option *ngIf="services !== null && services.length > 0"
-                        [ngValue]="null"
-                        i18n>-- Select an existing service --</option>
-                <option *ngFor="let service of services"
-                        [value]="service.service_name">{{ service.service_name }}</option>
-              </select>
-              <span class="invalid-feedback"
-                    *ngIf="serviceForm.showError('backend_service', frm, 'required')"
-                    i18n>This field is required.</span>
-            </div>
+        <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
+             class="form-group row">
+          <label i18n
+                 class="cd-col-form-label"
+                 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
+                 for="backend_service">Backend Service</label>
+          <div class="cd-col-form-input">
+            <select id="backend_service"
+                    name="backend_service"
+                    class="form-select"
+                    formControlName="backend_service"
+                    (change)="prePopulateId()">
+              <option *ngIf="services === null"
+                      [ngValue]="null"
+                      i18n>Loading...</option>
+              <option *ngIf="services !== null && services.length === 0"
+                      [ngValue]="null"
+                      i18n>-- No service available --</option>
+              <option *ngIf="services !== null && services.length > 0"
+                      [ngValue]="null"
+                      i18n>-- Select an existing service --</option>
+              <option *ngFor="let service of services"
+                      [value]="service.service_name">{{ service.service_name }}</option>
+            </select>
+            <span class="invalid-feedback"
+                  *ngIf="serviceForm.showError('backend_service', frm, 'required')"
+                  i18n>This field is required.</span>
           </div>
+        </div>
+
+        <!-- NVMe/TCP -->
+        <!-- Block Pool -->
+        <div class="form-group row"
+             *ngIf="serviceForm.controls.service_type.value === 'nvmeof'">
+          <label i18n
+                 class="cd-col-form-label required"
+                 for="pool">Block Pool</label>
+          <div class="cd-col-form-input">
+            <select id="pool"
+                    name="pool"
+                    class="form-select"
+                    formControlName="pool"
+                    (change)="onBlockPoolChange()">
+              <option *ngIf="rbdPools === null"
+                      [ngValue]="null"
+                      i18n>Loading...</option>
+              <option *ngIf="rbdPools && rbdPools.length === 0"
+                      [ngValue]="null"
+                      i18n>-- No block pools available --</option>
+              <option *ngIf="rbdPools && rbdPools.length > 0"
+                      [ngValue]="null"
+                      i18n>-- Select a pool --</option>
+              <option *ngFor="let pool of rbdPools"
+                      [value]="pool.pool_name">{{ pool.pool_name }}</option>
+            </select>
+            <cd-help-text i18n>
+              A pool in which the gateway configuration can be managed.
+            </cd-help-text>
+            <span class="invalid-feedback"
+                  *ngIf="serviceForm.showError('pool', frm, 'required')"
+                  i18n>This field is required.</span>
+          </div>
+        </div>
 
         <!-- Service id -->
         <div class="form-group row"
              *ngIf="serviceForm.controls.service_type.value !== 'snmp-gateway'">
           <label class="cd-col-form-label"
-                 [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)}"
+                 [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)}"
                  for="service_id">
-            <span i18n>Id</span>
-            <cd-helper i18n>Used in the service name which is &lt;service_type.service_id&gt;</cd-helper>
+            <span i18n>Service Name</span>
           </label>
           <div class="cd-col-form-input">
-            <input id="service_id"
-                   class="form-control"
-                   type="text"
-                   formControlName="service_id">
+            <div class="input-group">
+              <span class="input-group-text"
+                    *ngIf="serviceForm.controls.service_type.value && ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)"
+                    for="userId"
+                    i18n>{{serviceForm.controls.service_type.value}}.
+              </span>
+              <input id="service_id"
+                     class="form-control"
+                     type="text"
+                     formControlName="service_id">
+            </div>
             <span class="invalid-feedback"
                   *ngIf="serviceForm.showError('service_id', frm, 'required')"
                   i18n>This field is required.</span>
                      id="unmanaged"
                      type="checkbox"
                      formControlName="unmanaged">
-              <label class="custom-control-label"
+              <label class="custom-control-label m-0"
                      for="unmanaged"
                      i18n>Unmanaged</label>
-              <cd-helper i18n>If set to true, the orchestrator will not start nor stop any daemon associated with this service.
-                 Placement and all other properties will be ignored.</cd-helper>
+              <cd-help-text i18n>If Unmanaged is selected, the orchestrator will not stop or stop any daemons associated with this service. Placement and all other properties will be ignored.</cd-help-text>
             </div>
           </div>
         </div>
           </div>
         </div>
 
-        <!-- count -->
+        <!-- Count -->
         <div *ngIf="!serviceForm.controls.unmanaged.value"
              class="form-group row">
           <label class="cd-col-form-label"
                  for="count">
             <span i18n>Count</span>
-            <cd-helper i18n>Only that number of daemons will be created.</cd-helper>
           </label>
           <div class="cd-col-form-input">
             <input id="count"
                    type="number"
                    formControlName="count"
                    min="1">
+            <cd-help-text i18n>Number of deamons that will be deployed</cd-help-text>
             <span class="invalid-feedback"
                   *ngIf="serviceForm.showError('count', frm, 'min')"
                   i18n>The value must be at least 1.</span>
index 4f71abcec7a7d3f2e1db2923e250baddd4103bbf..db1e7851c2e4adc44b12f82db6d1498f9f45e1b9 100644 (file)
@@ -387,6 +387,33 @@ x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
       });
     });
 
+    describe('should test service nvmeof', () => {
+      beforeEach(() => {
+        formHelper.setValue('service_type', 'nvmeof');
+        formHelper.setValue('service_id', 'svc');
+        formHelper.setValue('pool', 'xyz');
+      });
+
+      it('should submit nvmeof', () => {
+        component.onSubmit();
+        expect(cephServiceService.create).toHaveBeenCalledWith({
+          service_type: 'nvmeof',
+          service_id: 'svc',
+          placement: {},
+          unmanaged: false,
+          pool: 'xyz'
+        });
+      });
+
+      it('should throw error when there is no service id', () => {
+        formHelper.expectErrorChange('service_id', '', 'required');
+      });
+
+      it('should throw error when there is no pool', () => {
+        formHelper.expectErrorChange('pool', '', 'required');
+      });
+    });
+
     describe('should test service smb', () => {
       beforeEach(() => {
         formHelper.setValue('service_type', 'smb');
@@ -608,6 +635,15 @@ x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
         expect(serviceType.disabled).toBeTruthy();
         expect(serviceId.disabled).toBeTruthy();
       });
+
+      it('should not edit pools for nvmeof service', () => {
+        component.serviceType = 'nvmeof';
+        formHelper.setValue('service_type', 'nvmeof');
+        component.ngOnInit();
+        fixture.detectChanges();
+        const poolId = fixture.debugElement.query(By.css('#pool')).nativeElement;
+        expect(poolId.disabled).toBeTruthy();
+      });
     });
   });
 });
index c0f66ed33626f14d8e27728202552827b018fea0..6142f7457c224badee5fe8acedb84558a87eb620 100644 (file)
@@ -7,12 +7,14 @@ import { NgbActiveModal, NgbModalRef, NgbTypeahead } from '@ng-bootstrap/ng-boot
 import _ from 'lodash';
 import { forkJoin, merge, Observable, Subject, Subscription } from 'rxjs';
 import { debounceTime, distinctUntilChanged, filter, map } from 'rxjs/operators';
+import { Pool } from '~/app/ceph/pool/pool';
 import { CreateRgwServiceEntitiesComponent } from '~/app/ceph/rgw/create-rgw-service-entities/create-rgw-service-entities.component';
 import { RgwRealm, RgwZonegroup, RgwZone } from '~/app/ceph/rgw/models/rgw-multisite';
 
 import { CephServiceService } from '~/app/shared/api/ceph-service.service';
 import { HostService } from '~/app/shared/api/host.service';
 import { PoolService } from '~/app/shared/api/pool.service';
+import { RbdService } from '~/app/shared/api/rbd.service';
 import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
 import { RgwRealmService } from '~/app/shared/api/rgw-realm.service';
 import { RgwZoneService } from '~/app/shared/api/rgw-zone.service';
@@ -68,7 +70,8 @@ export class ServiceFormComponent extends CdForm implements OnInit {
   labels: string[];
   labelClick = new Subject<string>();
   labelFocus = new Subject<string>();
-  pools: Array<object>;
+  pools: Array<Pool>;
+  rbdPools: Array<Pool>;
   services: Array<CephServiceSpec> = [];
   pageURL: string;
   serviceList: CephServiceSpec[];
@@ -94,6 +97,7 @@ export class ServiceFormComponent extends CdForm implements OnInit {
     private formBuilder: CdFormBuilder,
     private hostService: HostService,
     private poolService: PoolService,
+    private rbdService: RbdService,
     private router: Router,
     private taskWrapperService: TaskWrapperService,
     public timerService: TimerService,
@@ -145,6 +149,9 @@ export class ServiceFormComponent extends CdForm implements OnInit {
           CdValidators.requiredIf({
             service_type: 'iscsi'
           }),
+          CdValidators.requiredIf({
+            service_type: 'nvmeof'
+          }),
           CdValidators.requiredIf({
             service_type: 'ingress'
           }),
@@ -176,11 +183,15 @@ export class ServiceFormComponent extends CdForm implements OnInit {
       count: [null, [CdValidators.number(false)]],
       unmanaged: [false],
       // iSCSI
+      // NVMe/TCP
       pool: [
         null,
         [
           CdValidators.requiredIf({
             service_type: 'iscsi'
+          }),
+          CdValidators.requiredIf({
+            service_type: 'nvmeof'
           })
         ]
       ],
@@ -457,8 +468,9 @@ export class ServiceFormComponent extends CdForm implements OnInit {
     this.hostService.getLabels().subscribe((resp: string[]) => {
       this.labels = resp;
     });
-    this.poolService.getList().subscribe((resp: Array<object>) => {
+    this.poolService.getList().subscribe((resp: Pool[]) => {
       this.pools = resp;
+      this.rbdPools = this.pools.filter(this.rbdService.isRBDPool);
     });
 
     if (this.editing) {
@@ -495,12 +507,14 @@ export class ServiceFormComponent extends CdForm implements OnInit {
                 this.serviceForm.get('ssl_key').setValue(response[0].spec?.ssl_key);
               }
               break;
+            case 'nvmeof':
+              this.serviceForm.get('pool').setValue(response[0].spec.pool);
+              break;
             case 'rgw':
               this.serviceForm
                 .get('rgw_frontend_port')
                 .setValue(response[0].spec?.rgw_frontend_port);
-              this.getServiceIds(
-                'rgw',
+              this.setRgwFields(
                 response[0].spec?.rgw_realm,
                 response[0].spec?.rgw_zonegroup,
                 response[0].spec?.rgw_zone
@@ -595,7 +609,7 @@ export class ServiceFormComponent extends CdForm implements OnInit {
     }
   }
 
-  getDefaultsEntities(
+  getDefaultsEntitiesForRgw(
     defaultRealmId: string,
     defaultZonegroupId: string,
     defaultZoneId: string
@@ -625,100 +639,169 @@ export class ServiceFormComponent extends CdForm implements OnInit {
     };
   }
 
-  getServiceIds(
-    selectedServiceType: string,
-    realm_name?: string,
-    zonegroup_name?: string,
-    zone_name?: string
-  ) {
+  getDefaultPlacementCount(serviceType: string) {
+    /**
+     * `defaults` from src/pybind/mgr/cephadm/module.py
+     */
+    switch (serviceType) {
+      case 'mon':
+        this.serviceForm.get('count').setValue(5);
+        break;
+      case 'mgr':
+      case 'mds':
+      case 'rgw':
+      case 'ingress':
+      case 'rbd-mirror':
+        this.serviceForm.get('count').setValue(2);
+        break;
+      case 'iscsi':
+      case 'nvmeof':
+      case 'cephfs-mirror':
+      case 'nfs':
+      case 'grafana':
+      case 'alertmanager':
+      case 'prometheus':
+      case 'loki':
+      case 'container':
+      case 'snmp-gateway':
+      case 'elastic-serach':
+      case 'jaeger-collector':
+      case 'jaeger-query':
+      case 'smb':
+        this.serviceForm.get('count').setValue(1);
+        break;
+    }
+  }
+
+  setRgwFields(realm_name?: string, zonegroup_name?: string, zone_name?: string) {
+    const observables = [
+      this.rgwRealmService.getAllRealmsInfo(),
+      this.rgwZonegroupService.getAllZonegroupsInfo(),
+      this.rgwZoneService.getAllZonesInfo()
+    ];
+    this.sub = forkJoin(observables).subscribe(
+      (multisiteInfo: [object, object, object]) => {
+        this.multisiteInfo = multisiteInfo;
+        this.realmList =
+          this.multisiteInfo[0] !== undefined && this.multisiteInfo[0].hasOwnProperty('realms')
+            ? this.multisiteInfo[0]['realms']
+            : [];
+        this.zonegroupList =
+          this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
+            ? this.multisiteInfo[1]['zonegroups']
+            : [];
+        this.zoneList =
+          this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
+            ? this.multisiteInfo[2]['zones']
+            : [];
+        this.realmNames = this.realmList.map((realm) => {
+          return realm['name'];
+        });
+        this.zonegroupNames = this.zonegroupList.map((zonegroup) => {
+          return zonegroup['name'];
+        });
+        this.zoneNames = this.zoneList.map((zone) => {
+          return zone['name'];
+        });
+        this.defaultRealmId = multisiteInfo[0]['default_realm'];
+        this.defaultZonegroupId = multisiteInfo[1]['default_zonegroup'];
+        this.defaultZoneId = multisiteInfo[2]['default_zone'];
+        this.defaultsInfo = this.getDefaultsEntitiesForRgw(
+          this.defaultRealmId,
+          this.defaultZonegroupId,
+          this.defaultZoneId
+        );
+        if (!this.editing) {
+          this.serviceForm.get('realm_name').setValue(this.defaultsInfo['defaultRealmName']);
+          this.serviceForm
+            .get('zonegroup_name')
+            .setValue(this.defaultsInfo['defaultZonegroupName']);
+          this.serviceForm.get('zone_name').setValue(this.defaultsInfo['defaultZoneName']);
+        } else {
+          if (realm_name && !this.realmNames.includes(realm_name)) {
+            const realm = new RgwRealm();
+            realm.name = realm_name;
+            this.realmList.push(realm);
+          }
+          if (zonegroup_name && !this.zonegroupNames.includes(zonegroup_name)) {
+            const zonegroup = new RgwZonegroup();
+            zonegroup.name = zonegroup_name;
+            this.zonegroupList.push(zonegroup);
+          }
+          if (zone_name && !this.zoneNames.includes(zone_name)) {
+            const zone = new RgwZone();
+            zone.name = zone_name;
+            this.zoneList.push(zone);
+          }
+          if (zonegroup_name === undefined && zone_name === undefined) {
+            zonegroup_name = 'default';
+            zone_name = 'default';
+          }
+          this.serviceForm.get('realm_name').setValue(realm_name);
+          this.serviceForm.get('zonegroup_name').setValue(zonegroup_name);
+          this.serviceForm.get('zone_name').setValue(zone_name);
+        }
+        if (this.realmList.length === 0) {
+          this.showRealmCreationForm = true;
+        } else {
+          this.showRealmCreationForm = false;
+        }
+      },
+      (_error) => {
+        const defaultZone = new RgwZone();
+        defaultZone.name = 'default';
+        const defaultZonegroup = new RgwZonegroup();
+        defaultZonegroup.name = 'default';
+        this.zoneList.push(defaultZone);
+        this.zonegroupList.push(defaultZonegroup);
+      }
+    );
+  }
+
+  setNvmeofServiceId(): void {
+    const defaultRbdPool: string = this.rbdPools.find((p: Pool) => p.pool_name === 'rbd')
+      ?.pool_name;
+    if (defaultRbdPool) {
+      this.serviceForm.get('pool').setValue(defaultRbdPool);
+      this.serviceForm.get('service_id').setValue(defaultRbdPool);
+    }
+  }
+
+  requiresServiceId(serviceType: string) {
+    return ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceType);
+  }
+
+  setServiceId(serviceId: string): void {
+    const requiresServiceId: boolean = this.requiresServiceId(serviceId);
+    if (requiresServiceId && serviceId === 'nvmeof') {
+      this.setNvmeofServiceId();
+    } else if (requiresServiceId) {
+      this.serviceForm.get('service_id').setValue(null);
+    } else {
+      this.serviceForm.get('service_id').setValue(serviceId);
+    }
+  }
+
+  onServiceTypeChange(selectedServiceType: string) {
+    this.setServiceId(selectedServiceType);
+
     this.serviceIds = this.serviceList
       ?.filter((service) => service['service_type'] === selectedServiceType)
       .map((service) => service['service_id']);
 
+    this.getDefaultPlacementCount(selectedServiceType);
+
     if (selectedServiceType === 'rgw') {
-      const observables = [
-        this.rgwRealmService.getAllRealmsInfo(),
-        this.rgwZonegroupService.getAllZonegroupsInfo(),
-        this.rgwZoneService.getAllZonesInfo()
-      ];
-      this.sub = forkJoin(observables).subscribe(
-        (multisiteInfo: [object, object, object]) => {
-          this.multisiteInfo = multisiteInfo;
-          this.realmList =
-            this.multisiteInfo[0] !== undefined && this.multisiteInfo[0].hasOwnProperty('realms')
-              ? this.multisiteInfo[0]['realms']
-              : [];
-          this.zonegroupList =
-            this.multisiteInfo[1] !== undefined &&
-            this.multisiteInfo[1].hasOwnProperty('zonegroups')
-              ? this.multisiteInfo[1]['zonegroups']
-              : [];
-          this.zoneList =
-            this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
-              ? this.multisiteInfo[2]['zones']
-              : [];
-          this.realmNames = this.realmList.map((realm) => {
-            return realm['name'];
-          });
-          this.zonegroupNames = this.zonegroupList.map((zonegroup) => {
-            return zonegroup['name'];
-          });
-          this.zoneNames = this.zoneList.map((zone) => {
-            return zone['name'];
-          });
-          this.defaultRealmId = multisiteInfo[0]['default_realm'];
-          this.defaultZonegroupId = multisiteInfo[1]['default_zonegroup'];
-          this.defaultZoneId = multisiteInfo[2]['default_zone'];
-          this.defaultsInfo = this.getDefaultsEntities(
-            this.defaultRealmId,
-            this.defaultZonegroupId,
-            this.defaultZoneId
-          );
-          if (!this.editing) {
-            this.serviceForm.get('realm_name').setValue(this.defaultsInfo['defaultRealmName']);
-            this.serviceForm
-              .get('zonegroup_name')
-              .setValue(this.defaultsInfo['defaultZonegroupName']);
-            this.serviceForm.get('zone_name').setValue(this.defaultsInfo['defaultZoneName']);
-          } else {
-            if (realm_name && !this.realmNames.includes(realm_name)) {
-              const realm = new RgwRealm();
-              realm.name = realm_name;
-              this.realmList.push(realm);
-            }
-            if (zonegroup_name && !this.zonegroupNames.includes(zonegroup_name)) {
-              const zonegroup = new RgwZonegroup();
-              zonegroup.name = zonegroup_name;
-              this.zonegroupList.push(zonegroup);
-            }
-            if (zone_name && !this.zoneNames.includes(zone_name)) {
-              const zone = new RgwZone();
-              zone.name = zone_name;
-              this.zoneList.push(zone);
-            }
-            if (zonegroup_name === undefined && zone_name === undefined) {
-              zonegroup_name = 'default';
-              zone_name = 'default';
-            }
-            this.serviceForm.get('realm_name').setValue(realm_name);
-            this.serviceForm.get('zonegroup_name').setValue(zonegroup_name);
-            this.serviceForm.get('zone_name').setValue(zone_name);
-          }
-          if (this.realmList.length === 0) {
-            this.showRealmCreationForm = true;
-          } else {
-            this.showRealmCreationForm = false;
-          }
-        },
-        (_error) => {
-          const defaultZone = new RgwZone();
-          defaultZone.name = 'default';
-          const defaultZonegroup = new RgwZonegroup();
-          defaultZonegroup.name = 'default';
-          this.zoneList.push(defaultZone);
-          this.zonegroupList.push(defaultZonegroup);
-        }
-      );
+      this.setRgwFields();
+    }
+  }
+
+  onBlockPoolChange() {
+    const selectedBlockPool = this.serviceForm.get('pool').value;
+    if (selectedBlockPool) {
+      this.serviceForm.get('service_id').setValue(selectedBlockPool);
+    } else {
+      this.serviceForm.get('service_id').setValue(null);
     }
   }
 
@@ -730,6 +813,10 @@ export class ServiceFormComponent extends CdForm implements OnInit {
     switch (serviceType) {
       case 'ingress':
         this.serviceForm.get('backend_service').disable();
+        break;
+      case 'nvmeof':
+        this.serviceForm.get('pool').disable();
+        break;
     }
   }
 
@@ -780,19 +867,16 @@ export class ServiceFormComponent extends CdForm implements OnInit {
       placement: {},
       unmanaged: values['unmanaged']
     };
-    let svcId: string;
     if (serviceType === 'rgw') {
       serviceSpec['rgw_realm'] = values['realm_name'] ? values['realm_name'] : null;
       serviceSpec['rgw_zonegroup'] =
         values['zonegroup_name'] !== 'default' ? values['zonegroup_name'] : null;
       serviceSpec['rgw_zone'] = values['zone_name'] !== 'default' ? values['zone_name'] : null;
-      svcId = values['service_id'];
-    } else {
-      svcId = values['service_id'];
     }
-    const serviceId: string = svcId;
+
+    const serviceId: string = values['service_id'];
     let serviceName: string = serviceType;
-    if (_.isString(serviceId) && !_.isEmpty(serviceId)) {
+    if (_.isString(serviceId) && !_.isEmpty(serviceId) && serviceId !== serviceType) {
       serviceName = `${serviceType}.${serviceId}`;
       serviceSpec['service_id'] = serviceId;
     }
@@ -814,6 +898,7 @@ export class ServiceFormComponent extends CdForm implements OnInit {
         }
         break;
 
+      case 'nvmeof':
       case 'iscsi':
         serviceSpec['pool'] = values['pool'];
         break;
@@ -947,7 +1032,7 @@ export class ServiceFormComponent extends CdForm implements OnInit {
       size: 'lg'
     });
     this.bsModalRef.componentInstance.submitAction.subscribe(() => {
-      this.getServiceIds('rgw');
+      this.setRgwFields();
     });
   }
 }