]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Add support for iSCSI's multi backstores (UI) 26575/head
authorTiago Melo <tmelo@suse.com>
Wed, 20 Feb 2019 10:58:54 +0000 (10:58 +0000)
committerTiago Melo <tmelo@suse.com>
Wed, 27 Feb 2019 12:25:38 +0000 (12:25 +0000)
Fixes: https://tracker.ceph.com/issues/38286
Signed-off-by: Tiago Melo <tmelo@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.ts
src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf

index b855256394cee4035ed5336f93aa76e1cb20102e..339a3c94e3302029a4e111b7b933f3c53086133b 100644 (file)
@@ -24,20 +24,35 @@ describe('IscsiTargetDetailsComponent', () => {
     component.settings = {
       config: { minimum_gateways: 2 },
       disk_default_controls: {
-        hw_max_sectors: 1024,
-        max_data_area_mb: 8
+        'backstore:1': {
+          hw_max_sectors: 1024,
+          max_data_area_mb: 8
+        },
+        'backstore:2': {
+          hw_max_sectors: 1024,
+          max_data_area_mb: 8
+        }
       },
       target_default_controls: {
         cmdsn_depth: 128,
         dataout_timeout: 20
-      }
+      },
+      backstores: ['backstore:1', 'backstore:2'],
+      default_backstore: 'backstore:1'
     };
     component.selection = new CdTableSelection();
     component.selection.selected = [
       {
         target_iqn: 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw',
         portals: [{ host: 'node1', ip: '192.168.100.201' }],
-        disks: [{ pool: 'rbd', image: 'disk_1', controls: { hw_max_sectors: 1 } }],
+        disks: [
+          {
+            pool: 'rbd',
+            image: 'disk_1',
+            backstore: 'backstore:1',
+            controls: { hw_max_sectors: 1 }
+          }
+        ],
         clients: [
           {
             client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
@@ -74,7 +89,7 @@ describe('IscsiTargetDetailsComponent', () => {
     expect(component.data).toBeUndefined();
     expect(component.metadata).toEqual({
       'client_iqn.1994-05.com.redhat:rh7-client': { user: 'myiscsiusername' },
-      disk_rbd_disk_1: { hw_max_sectors: 1 },
+      disk_rbd_disk_1: { backstore: 'backstore:1', controls: { hw_max_sectors: 1 } },
       root: { dataout_timeout: 2 }
     });
     expect(component.tree).toEqual({
@@ -153,7 +168,8 @@ describe('IscsiTargetDetailsComponent', () => {
       component.onNodeSelected(node);
       expect(component.data).toEqual([
         { current: 1, default: 1024, displayName: 'hw_max_sectors' },
-        { current: 8, default: 8, displayName: 'max_data_area_mb' }
+        { current: 8, default: 8, displayName: 'max_data_area_mb' },
+        { current: 'backstore:1', default: 'backstore:1', displayName: 'backstore' }
       ]);
     });
 
index aa8878ada274952fdd4fa91c4733e722e8d4f961..814dc44b9f58e7f8ae3b83a5e148b1dea24e76de 100644 (file)
@@ -100,7 +100,11 @@ export class IscsiTargetDetailsComponent implements OnChanges, OnInit {
     const disks = [];
     _.forEach(this.selectedItem.disks, (disk) => {
       const id = 'disk_' + disk.pool + '_' + disk.image;
-      this.metadata[id] = disk.controls;
+      this.metadata[id] = {
+        controls: disk.controls,
+        backstore: disk.backstore
+      };
+
       disks.push({
         value: `${disk.pool}/${disk.image}`,
         id: id
@@ -235,13 +239,18 @@ export class IscsiTargetDetailsComponent implements OnChanges, OnInit {
         });
       } else if (e.node.id.toString().startsWith('disk_')) {
         this.columns[2].isHidden = false;
-        this.data = _.map(this.settings.disk_default_controls, (value, key) => {
+        this.data = _.map(this.settings.disk_default_controls[tempData.backstore], (value, key) => {
           return {
             displayName: key,
             default: value,
-            current: tempData[key] || value
+            current: !_.isUndefined(tempData.controls[key]) ? tempData.controls[key] : value
           };
         });
+        this.data.push({
+          displayName: 'backstore',
+          default: this.settings.default_backstore,
+          current: tempData.backstore
+        });
       } else {
         this.columns[2].isHidden = true;
         this.data = _.map(tempData, (value, key) => {
index 750173873ae7fcfba678f188894ff3299bad0302..6c3b33634067924425e3e03d06fc9a8542a07aa0 100644 (file)
                 </span>
 
               </div>
-              <span class="help-block"
-                    *ngIf="hasAdvancedSettings(imagesSettings[image])"
-                    i18n>This image has modified settings.</span>
+
+              <span class="help-block">
+                <ng-container *ngIf="backstores.length > 1"
+                              i18n>Backstore: {{ imagesSettings[image].backstore }}.&nbsp;</ng-container>
+
+                <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
+                              i18n>This image has modified settings.</ng-container>
+              </span>
             </ng-container>
 
             <span class="help-block"
index f5f820f5e8480858c71e8305c151d8d9577cacee..adc769758883d39edffc956fa888cc82b89562b1 100644 (file)
@@ -20,15 +20,21 @@ describe('IscsiTargetFormComponent', () => {
   const SETTINGS = {
     config: { minimum_gateways: 2 },
     disk_default_controls: {
-      hw_max_sectors: 1024,
-      osd_op_timeout: 30,
-      qfull_timeout: 5
+      'backstore:1': {
+        hw_max_sectors: 1024,
+        osd_op_timeout: 30
+      },
+      'backstore:2': {
+        qfull_timeout: 5
+      }
     },
     target_default_controls: {
       cmdsn_depth: 128,
       dataout_timeout: 20,
       immediate_data: 'Yes'
-    }
+    },
+    backstores: ['backstore:1', 'backstore:2'],
+    default_backstore: 'backstore:1'
   };
 
   const LIST_TARGET = [
@@ -177,7 +183,12 @@ describe('IscsiTargetFormComponent', () => {
   it('should prepare data when selecting an image', () => {
     expect(component.imagesSettings).toEqual({});
     component.onImageSelection({ option: { name: 'rbd/disk_1', selected: true } });
-    expect(component.imagesSettings).toEqual({ 'rbd/disk_1': {} });
+    expect(component.imagesSettings).toEqual({
+      'rbd/disk_1': {
+        backstore: 'backstore:1',
+        'backstore:1': {}
+      }
+    });
   });
 
   it('should clean data when removing an image', () => {
@@ -197,7 +208,12 @@ describe('IscsiTargetFormComponent', () => {
     component.onImageSelection({ option: { name: 'rbd/disk_1', selected: false } });
 
     expect(component.groups.controls[0].value).toEqual({ disks: [], group_id: 'foo', members: [] });
-    expect(component.imagesSettings).toEqual({ 'rbd/disk_1': {} });
+    expect(component.imagesSettings).toEqual({
+      'rbd/disk_1': {
+        backstore: 'backstore:1',
+        'backstore:1': {}
+      }
+    });
   });
 
   describe('should test initiators', () => {
@@ -332,7 +348,7 @@ describe('IscsiTargetFormComponent', () => {
             luns: []
           }
         ],
-        disks: [{ controls: {}, image: 'disk_1', pool: 'rbd' }],
+        disks: [{ backstore: 'backstore:1', controls: {}, image: 'disk_1', pool: 'rbd' }],
         groups: [
           { disks: [{ image: 'disk_1', pool: 'rbd' }], group_id: 'foo', members: ['iqn.initiator'] }
         ],
@@ -360,9 +376,13 @@ describe('IscsiTargetFormComponent', () => {
             luns: []
           }
         ],
-        disks: [{ controls: {}, image: 'disk_1', pool: 'rbd' }],
+        disks: [{ backstore: 'backstore:1', controls: {}, image: 'disk_1', pool: 'rbd' }],
         groups: [
-          { disks: [{ image: 'disk_1', pool: 'rbd' }], group_id: 'foo', members: ['iqn.initiator'] }
+          {
+            disks: [{ image: 'disk_1', pool: 'rbd' }],
+            group_id: 'foo',
+            members: ['iqn.initiator']
+          }
         ],
         portals: [
           { host: 'node1', ip: '192.168.100.201' },
index ee7205018fff61c643d99c8c7aa21178ea4cbfbb..a765d499d53bca21cfc73fed82c4821fb201d341 100644 (file)
@@ -29,6 +29,8 @@ export class IscsiTargetFormComponent implements OnInit {
   minimum_gateways = 1;
   target_default_controls: any;
   disk_default_controls: any;
+  backstores: string[];
+  default_backstore: string;
 
   isEdit = false;
   target_iqn: string;
@@ -129,6 +131,8 @@ export class IscsiTargetFormComponent implements OnInit {
       this.minimum_gateways = data[3].config.minimum_gateways;
       this.target_default_controls = data[3].target_default_controls;
       this.disk_default_controls = data[3].disk_default_controls;
+      this.backstores = data[3].backstores;
+      this.default_backstore = data[3].default_backstore;
 
       this.createForm();
 
@@ -178,7 +182,11 @@ export class IscsiTargetFormComponent implements OnInit {
     _.forEach(res.disks, (disk) => {
       const id = `${disk.pool}/${disk.image}`;
       disks.push(id);
-      this.imagesSettings[id] = disk.controls;
+      this.imagesSettings[id] = {
+        backstore: disk.backstore
+      };
+      this.imagesSettings[id][disk.backstore] = disk.controls;
+
       this.onImageSelection({ option: { name: id, selected: true } });
     });
     this.targetForm.patchValue({
@@ -268,7 +276,10 @@ export class IscsiTargetFormComponent implements OnInit {
 
     if (option.selected) {
       if (!this.imagesSettings[option.name]) {
-        this.imagesSettings[option.name] = {};
+        this.imagesSettings[option.name] = {
+          backstore: this.default_backstore
+        };
+        this.imagesSettings[option.name][this.default_backstore] = {};
       }
 
       _.forEach(this.imagesInitiatorSelections, (selections, i) => {
@@ -507,10 +518,12 @@ export class IscsiTargetFormComponent implements OnInit {
     // Disks
     formValue.disks.forEach((disk) => {
       const imageSplit = disk.split('/');
+      const backstore = this.imagesSettings[disk].backstore;
       request.disks.push({
         pool: imageSplit[0],
         image: imageSplit[1],
-        controls: this.imagesSettings[disk]
+        backstore: backstore,
+        controls: this.imagesSettings[disk][backstore]
       });
     });
 
@@ -607,7 +620,8 @@ export class IscsiTargetFormComponent implements OnInit {
     const initialState = {
       imagesSettings: this.imagesSettings,
       image: image,
-      disk_default_controls: this.disk_default_controls
+      disk_default_controls: this.disk_default_controls,
+      backstores: this.backstores
     };
 
     this.modalRef = this.modalService.show(IscsiTargetImageSettingsModalComponent, {
index 27b13dcb61c9995a6f127baf91b9bd216b3fd46e..ff1e54d5e09f3d4ed90f15df33fd5fa256c32de3 100644 (file)
@@ -5,40 +5,55 @@
   </ng-container>
 
   <ng-container class="modal-content">
-    <form name="settingsForm"
-          class="form"
-          #formDir="ngForm"
-          [formGroup]="settingsForm"
-          novalidate>
-      <div class="modal-body">
-        <p class="alert-warning"
-           i18n>Changing these parameters from their default values is usually not necessary.</p>
+    <div class="modal-body">
+      <p class="alert-warning"
+         i18n>Changing these parameters from their default values is usually not necessary.</p>
 
-        <div class="form-group row"
-             *ngFor="let setting of disk_default_controls | keyvalue"
-             [ngClass]="{'has-error': settingsForm.showError(setting.key, formDir)}">
-          <div class="col-sm-12">
-            <label class="control-label"
-                   for="{{ setting.key }}">{{ setting.key }}</label>
-            <input type="number"
-                   class="form-control"
-                   [formControlName]="setting.key">
-            <span class="help-block">{{ helpText[setting.key]?.help }}</span>
-          </div>
+      <!-- BACKSTORE -->
+      <div class="form-group row"
+           *ngIf="backstores.length > 1">
+        <div class="col-sm-12">
+          <label class="control-label"
+                 i18n>Backstore</label>
+          <select id="backstore"
+                  name="backstore"
+                  class="form-control"
+                  [(ngModel)]="model.backstore">
+            <option *ngFor="let bs of backstores"
+                    [value]="bs">{{ bs }}</option>
+          </select>
         </div>
       </div>
 
-      <div class="modal-footer">
-        <div class="button-group text-right">
-          <cd-submit-button i18n
-                            [form]="settingsForm"
-                            (submitAction)="save()">Confirm</cd-submit-button>
-          <button i18n
-                  type="button"
-                  class="btn btn-sm btn-default"
-                  (click)="modalRef.hide()">Cancel</button>
-        </div>
+      <!-- CONTROLS -->
+      <ng-container *ngFor="let bs of backstores">
+        <ng-container *ngIf="model.backstore === bs">
+          <div class="form-group row"
+               *ngFor="let setting of disk_default_controls[bs] | keyvalue">
+            <div class="col-sm-12">
+              <label class="control-label"
+                     for="{{ setting.key }}">{{ setting.key }}</label>
+              <input type="number"
+                     class="form-control"
+                     [(ngModel)]="model[bs][setting.key]">
+              <span class="help-block">{{ helpText[setting.key]?.help }}</span>
+            </div>
+          </div>
+        </ng-container>
+      </ng-container>
+    </div>
+
+    <div class="modal-footer">
+      <div class="button-group text-right">
+        <button class="btn btn-sm btn-primary"
+                (click)="save()"
+                i18n>Confirm</button>
+
+        <button i18n
+                type="button"
+                class="btn btn-sm btn-default"
+                (click)="modalRef.hide()">Cancel</button>
       </div>
-    </form>
+    </div>
   </ng-container>
 </cd-modal>
index 440736da8261adcb57901926d881de8d18c947a2..1f8d8c7c03b9b80eace7d7e47602ce958fe360c1 100644 (file)
@@ -1,6 +1,6 @@
 import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ReactiveFormsModule } from '@angular/forms';
+import { FormsModule } from '@angular/forms';
 
 import { BsModalRef } from 'ngx-bootstrap/modal';
 
@@ -14,7 +14,7 @@ describe('IscsiTargetImageSettingsModalComponent', () => {
 
   configureTestBed({
     declarations: [IscsiTargetImageSettingsModalComponent],
-    imports: [SharedModule, ReactiveFormsModule, HttpClientTestingModule],
+    imports: [SharedModule, FormsModule, HttpClientTestingModule],
     providers: [BsModalRef, i18nProviders]
   });
 
@@ -22,12 +22,19 @@ describe('IscsiTargetImageSettingsModalComponent', () => {
     fixture = TestBed.createComponent(IscsiTargetImageSettingsModalComponent);
     component = fixture.componentInstance;
 
-    component.imagesSettings = { 'rbd/disk_1': {} };
+    component.imagesSettings = { 'rbd/disk_1': { backstore: 'backstore:1', 'backstore:1': {} } };
     component.image = 'rbd/disk_1';
     component.disk_default_controls = {
-      foo: 1,
-      bar: 2
+      'backstore:1': {
+        foo: 1,
+        bar: 2
+      },
+      'backstore:2': {
+        baz: 3
+      }
     };
+    component.backstores = ['backstore:1', 'backstore:2'];
+
     component.ngOnInit();
     fixture.detectChanges();
   });
@@ -36,20 +43,26 @@ describe('IscsiTargetImageSettingsModalComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  it('should fill the settingsForm', () => {
-    expect(component.settingsForm.value).toEqual({
-      foo: null,
-      bar: null
+  it('should fill the model', () => {
+    expect(component.model).toEqual({
+      backstore: 'backstore:1',
+      'backstore:1': {},
+      'backstore:2': {}
     });
   });
 
   it('should save changes to imagesSettings', () => {
-    component.settingsForm.patchValue({ foo: 1234 });
-    expect(component.imagesSettings).toEqual({ 'rbd/disk_1': {} });
+    component.model['backstore:1'] = { foo: 1234 };
+    expect(component.imagesSettings).toEqual({
+      'rbd/disk_1': { backstore: 'backstore:1', 'backstore:1': {} }
+    });
     component.save();
     expect(component.imagesSettings).toEqual({
       'rbd/disk_1': {
-        foo: 1234
+        backstore: 'backstore:1',
+        'backstore:1': {
+          foo: 1234
+        }
       }
     });
   });
index 758a34daf0b26bc1032141edf9c75710f7edb49b..310942a590ab707ef5ddd9ec9779af11b709bcef 100644 (file)
@@ -1,11 +1,9 @@
 import { Component, OnInit } from '@angular/core';
-import { FormControl } from '@angular/forms';
 
 import * as _ from 'lodash';
 import { BsModalRef } from 'ngx-bootstrap/modal';
 
 import { IscsiService } from '../../../shared/api/iscsi.service';
-import { CdFormGroup } from '../../../shared/forms/cd-form-group';
 
 @Component({
   selector: 'cd-iscsi-target-image-settings-modal',
@@ -16,33 +14,32 @@ export class IscsiTargetImageSettingsModalComponent implements OnInit {
   image: string;
   imagesSettings: any;
   disk_default_controls: any;
+  backstores: any;
 
-  settingsForm: CdFormGroup;
+  model: any;
   helpText: any;
 
   constructor(public modalRef: BsModalRef, public iscsiService: IscsiService) {}
 
   ngOnInit() {
-    const fg = {};
-    const currentSettings = this.imagesSettings[this.image];
     this.helpText = this.iscsiService.imageAdvancedSettings;
 
-    _.forIn(this.disk_default_controls, (_value, key) => {
-      fg[key] = new FormControl(currentSettings[key]);
+    this.model = _.cloneDeep(this.imagesSettings[this.image]);
+    _.forEach(this.backstores, (backstore) => {
+      this.model[backstore] = this.model[backstore] || {};
     });
-
-    this.settingsForm = new CdFormGroup(fg);
   }
 
   save() {
+    const backstore = this.model.backstore;
     const settings = {};
-    _.forIn(this.settingsForm.value, (value, key) => {
+    _.forIn(this.model[backstore], (value, key) => {
       if (!(value === '' || value === null)) {
         settings[key] = value;
       }
     });
-
-    this.imagesSettings[this.image] = settings;
+    this.imagesSettings[this.image]['backstore'] = backstore;
+    this.imagesSettings[this.image][backstore] = settings;
     this.imagesSettings = { ...this.imagesSettings };
     this.modalRef.hide();
   }
index 420c0fe79ad7998f95421aa231ced51de3319ab4..06120545c4526da043222c550f9d9e0014ab9f42 100644 (file)
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">341</context>
+          <context context-type="linenumber">346</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">479</context>
+          <context context-type="linenumber">484</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi/iscsi.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">544</context>
+          <context context-type="linenumber">549</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/rbd-form/rbd-form.component.html</context>
         <source>Changing these parameters from their default values is usually not necessary.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html</context>
-          <context context-type="linenumber">15</context>
+          <context context-type="linenumber">10</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html</context>
           <context context-type="linenumber">13</context>
         </context-group>
+      </trans-unit><trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+        <source>Backstore</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html</context>
+          <context context-type="linenumber">17</context>
+        </context-group>
       </trans-unit><trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
         <source>Confirm</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html</context>
-          <context context-type="linenumber">35</context>
+          <context context-type="linenumber">50</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html</context>
         <source>Cancel</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html</context>
-          <context context-type="linenumber">39</context>
+          <context context-type="linenumber">55</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">209</context>
+          <context context-type="linenumber">214</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">231</context>
+          <context context-type="linenumber">236</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">266</context>
+          <context context-type="linenumber">271</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">291</context>
+          <context context-type="linenumber">296</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">326</context>
+          <context context-type="linenumber">331</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">213</context>
+          <context context-type="linenumber">218</context>
         </context-group>
       </trans-unit><trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
         <source>An IQN has the following notation &apos;iqn.$year-$month.$reversedAddress:$definedName&apos;</source>
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
           <context context-type="linenumber">106</context>
         </context-group>
+      </trans-unit><trans-unit id="6c1c7f516d021abaf155aab1e9c2fe96e2c4ff40" datatype="html">
+        <source>Backstore: <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore }}"/>. </source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
+          <context context-type="linenumber">147</context>
+        </context-group>
       </trans-unit><trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
         <source>This image has modified settings.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">146</context>
+          <context context-type="linenumber">150</context>
         </context-group>
       </trans-unit><trans-unit id="107c84e820909b44fe258673938a68ced1bbff72" datatype="html">
         <source>At least 1 image is required.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">151</context>
+          <context context-type="linenumber">156</context>
         </context-group>
       </trans-unit><trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
         <source>Add image</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">161</context>
+          <context context-type="linenumber">166</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">371</context>
+          <context context-type="linenumber">376</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">506</context>
+          <context context-type="linenumber">511</context>
         </context-group>
       </trans-unit><trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
         <source>Initiators</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">174</context>
+          <context context-type="linenumber">179</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">437</context>
+          <context context-type="linenumber">442</context>
         </context-group>
       </trans-unit><trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
         <source>Initiator</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">181</context>
+          <context context-type="linenumber">186</context>
         </context-group>
       </trans-unit><trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
         <source>Client IQN</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">194</context>
+          <context context-type="linenumber">199</context>
         </context-group>
       </trans-unit><trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
         <source>Initiator IQN needs to be unique.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">205</context>
+          <context context-type="linenumber">210</context>
         </context-group>
       </trans-unit><trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
         <source>User</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">223</context>
+          <context context-type="linenumber">228</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html</context>
                         can only contain letters, &apos;.&apos;, &apos;@&apos;, &apos;-&apos;, &apos;_&apos; or &apos;:&apos;.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">235</context>
+          <context context-type="linenumber">240</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">295</context>
+          <context context-type="linenumber">300</context>
         </context-group>
       </trans-unit><trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
         <source>Password</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">245</context>
+          <context context-type="linenumber">250</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html</context>
                         and can only contain letters, &apos;@&apos;, &apos;-&apos; or &apos;_&apos;.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">270</context>
+          <context context-type="linenumber">275</context>
         </context-group>
       </trans-unit><trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
         <source>Mutual User</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">281</context>
+          <context context-type="linenumber">286</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html</context>
         <source>Mutual Password</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">305</context>
+          <context context-type="linenumber">310</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html</context>
                         can only contain letters, &apos;@&apos;, &apos;-&apos; or &apos;_&apos;.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">330</context>
+          <context context-type="linenumber">335</context>
         </context-group>
       </trans-unit><trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
         <source>Initiator belongs to a group. Images will be configure in the group.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">361</context>
+          <context context-type="linenumber">366</context>
         </context-group>
       </trans-unit><trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
         <source>No items added.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">384</context>
+          <context context-type="linenumber">389</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">521</context>
+          <context context-type="linenumber">526</context>
         </context-group>
       </trans-unit><trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
         <source>Add initiator</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">389</context>
+          <context context-type="linenumber">394</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">465</context>
+          <context context-type="linenumber">470</context>
         </context-group>
       </trans-unit><trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
         <source>Groups</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">403</context>
+          <context context-type="linenumber">408</context>
         </context-group>
       </trans-unit><trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
         <source>Group</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">410</context>
+          <context context-type="linenumber">415</context>
         </context-group>
       </trans-unit><trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
         <source>Name</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">422</context>
+          <context context-type="linenumber">427</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/rbd-form/rbd-form.component.html</context>
         <source>Add group</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">526</context>
+          <context context-type="linenumber">531</context>
         </context-group>
       </trans-unit><trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
         <source>Submit</source>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-form/iscsi-target-form.component.html</context>
-          <context context-type="linenumber">539</context>
+          <context context-type="linenumber">544</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html</context>