Explorar o código

Update storage mapping default behaviour

Auto select the server's storage config default in 'Default Storage'
field, found in Wizard target options and Edit Replica target options.

When creating a replica, don't send any storage mapping data to the
server, if its target mapping is 'Default'.

When editing a replica, if a target storage mapping is changed to
'Default', send the 'Default Storage' as the target mapping.

In Wizard Summary page, show only the storage mappings that are actually
sent to the server.
Sergiu Miclea %!s(int64=6) %!d(string=hai) anos
pai
achega
05f53fc9dc

+ 5 - 4
src/components/organisms/EditReplica/EditReplica.jsx

@@ -259,10 +259,11 @@ class EditReplica extends React.Component<Props, State> {
       source: this.state.sourceData,
       source: this.state.sourceData,
       destination: this.state.destinationData,
       destination: this.state.destinationData,
       network: this.state.selectedNetworks.length > 0 ? this.getSelectedNetworks() : [],
       network: this.state.selectedNetworks.length > 0 ? this.getSelectedNetworks() : [],
-      storage: this.state.destinationData.default_storage || this.state.storageMap.length > 0 ? this.getStorageMap() : [],
+      storage: this.state.storageMap,
     }
     }
     if (this.props.type === 'replica') {
     if (this.props.type === 'replica') {
-      replicaStore.update(this.props.replica, this.props.destinationEndpoint, updateData).then(() => {
+      let storageConfigDefault = this.getFieldValue('destination', 'default_storage') || endpointStore.storageConfigDefault
+      replicaStore.update(this.props.replica, this.props.destinationEndpoint, updateData, storageConfigDefault).then(() => {
         this.props.onRequestClose()
         this.props.onRequestClose()
         this.props.onUpdateComplete(`/replica/executions/${this.props.replica.id}`)
         this.props.onUpdateComplete(`/replica/executions/${this.props.replica.id}`)
       }).catch(() => {
       }).catch(() => {
@@ -360,7 +361,7 @@ class EditReplica extends React.Component<Props, State> {
     this.state.storageMap.forEach(mapping => {
     this.state.storageMap.forEach(mapping => {
       let fieldName = mapping.type === 'backend' ? 'storage_backend_identifier' : 'id'
       let fieldName = mapping.type === 'backend' ? 'storage_backend_identifier' : 'id'
       let existingMapping = storageMap.find(m => m.type === mapping.type &&
       let existingMapping = storageMap.find(m => m.type === mapping.type &&
-        m.source[fieldName] === mapping.source[fieldName]
+        m.source[fieldName] === String(mapping.source[fieldName])
       )
       )
       if (existingMapping) {
       if (existingMapping) {
         existingMapping.target = mapping.target
         existingMapping.target = mapping.target
@@ -388,6 +389,7 @@ class EditReplica extends React.Component<Props, State> {
         fields={fields}
         fields={fields}
         hasStorageMap={type === 'source' ? false : this.hasStorageMap()}
         hasStorageMap={type === 'source' ? false : this.hasStorageMap()}
         storageBackends={endpointStore.storageBackends}
         storageBackends={endpointStore.storageBackends}
+        storageConfigDefault={endpointStore.storageConfigDefault}
         onChange={(f, v) => { this.handleFieldChange(type, f, v) }}
         onChange={(f, v) => { this.handleFieldChange(type, f, v) }}
         oneColumnStyle={{ marginTop: '-16px', display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center' }}
         oneColumnStyle={{ marginTop: '-16px', display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center' }}
         columnStyle={{ marginRight: 0 }}
         columnStyle={{ marginRight: 0 }}
@@ -412,7 +414,6 @@ class EditReplica extends React.Component<Props, State> {
         storageBackends={endpointStore.storageBackends}
         storageBackends={endpointStore.storageBackends}
         instancesDetails={this.props.instancesDetails}
         instancesDetails={this.props.instancesDetails}
         storageMap={this.getStorageMap()}
         storageMap={this.getStorageMap()}
-        defaultStorage={this.getFieldValue('destination', 'default_storage')}
         onChange={(s, t, type) => { this.handleStorageChange(s, t, type) }}
         onChange={(s, t, type) => { this.handleStorageChange(s, t, type) }}
       />
       />
     )
     )

+ 7 - 1
src/components/organisms/WizardOptions/WizardOptions.jsx

@@ -81,6 +81,7 @@ type Props = {
   useAdvancedOptions?: boolean,
   useAdvancedOptions?: boolean,
   hasStorageMap: boolean,
   hasStorageMap: boolean,
   storageBackends?: StorageBackend[],
   storageBackends?: StorageBackend[],
+  storageConfigDefault?: string,
   onAdvancedOptionsToggle?: (showAdvanced: boolean) => void,
   onAdvancedOptionsToggle?: (showAdvanced: boolean) => void,
   wizardType: string,
   wizardType: string,
   loading?: boolean,
   loading?: boolean,
@@ -145,7 +146,12 @@ class WizardOptions extends React.Component<Props> {
     }
     }
 
 
     if (this.props.hasStorageMap && this.props.useAdvancedOptions && this.props.storageBackends && this.props.storageBackends.length > 0) {
     if (this.props.hasStorageMap && this.props.useAdvancedOptions && this.props.storageBackends && this.props.storageBackends.length > 0) {
-      fieldsSchema.push({ name: 'default_storage', type: 'string', enum: this.props.storageBackends.map(s => s.name) })
+      fieldsSchema.push({
+        name: 'default_storage',
+        type: 'string',
+        enum: this.props.storageBackends.map(s => s.name),
+        default: this.props.storageConfigDefault,
+      })
     }
     }
 
 
     return fieldsSchema
     return fieldsSchema

+ 1 - 8
src/components/organisms/WizardPageContent/WizardPageContent.jsx

@@ -355,6 +355,7 @@ class WizardPageContent extends React.Component<Props, State> {
             useAdvancedOptions={this.state.useAdvancedOptions}
             useAdvancedOptions={this.state.useAdvancedOptions}
             hasStorageMap={this.props.hasStorageMap}
             hasStorageMap={this.props.hasStorageMap}
             storageBackends={this.props.endpointStore.storageBackends}
             storageBackends={this.props.endpointStore.storageBackends}
+            storageConfigDefault={this.props.endpointStore.storageConfigDefault}
             wizardType={this.props.type}
             wizardType={this.props.type}
             onAdvancedOptionsToggle={useAdvancedOptions => { this.handleAdvancedOptionsToggle(useAdvancedOptions) }}
             onAdvancedOptionsToggle={useAdvancedOptions => { this.handleAdvancedOptionsToggle(useAdvancedOptions) }}
           />
           />
@@ -378,7 +379,6 @@ class WizardPageContent extends React.Component<Props, State> {
             storageBackends={this.props.endpointStore.storageBackends}
             storageBackends={this.props.endpointStore.storageBackends}
             instancesDetails={this.props.instanceStore.instancesDetails}
             instancesDetails={this.props.instanceStore.instancesDetails}
             storageMap={this.props.storageMap}
             storageMap={this.props.storageMap}
-            defaultStorage={String(this.props.wizardData.destOptions ? this.props.wizardData.destOptions.default_storage : '')}
             onChange={this.props.onStorageChange}
             onChange={this.props.onStorageChange}
           />
           />
         )
         )
@@ -404,13 +404,6 @@ class WizardPageContent extends React.Component<Props, State> {
             storageMap={this.props.storageMap}
             storageMap={this.props.storageMap}
             wizardType={this.props.type}
             wizardType={this.props.type}
             instancesDetails={this.props.instanceStore.instancesDetails}
             instancesDetails={this.props.instanceStore.instancesDetails}
-            defaultStorage={
-              this.props.endpointStore.storageBackends.find(
-                s => this.props.wizardData.destOptions ?
-                  s.name === this.props.wizardData.destOptions.default_storage :
-                  false
-              )
-            }
           />
           />
         )
         )
         break
         break

+ 2 - 3
src/components/organisms/WizardStorage/WizardStorage.jsx

@@ -143,7 +143,6 @@ export type Props = {
   storageBackends: StorageBackend[],
   storageBackends: StorageBackend[],
   instancesDetails: Instance[],
   instancesDetails: Instance[],
   storageMap: ?StorageMap[],
   storageMap: ?StorageMap[],
-  defaultStorage: ?string,
   onChange: (sourceStorage: Disk, targetStorage: StorageBackend, type: 'backend' | 'disk') => void,
   onChange: (sourceStorage: Disk, targetStorage: StorageBackend, type: 'backend' | 'disk') => void,
 }
 }
 @observer
 @observer
@@ -184,8 +183,8 @@ class WizardStorage extends React.Component<Props> {
               }
               }
               return false
               return false
             }).map(i => i.instance_name)
             }).map(i => i.instance_name)
-            let selectedItem = storageMap && storageMap.find(s => s.type === type && s.source[diskFieldName] === disk[diskFieldName])
-            selectedItem = selectedItem ? selectedItem.target : storageItems.find(i => i.name === this.props.defaultStorage)
+            let selectedItem = storageMap && storageMap.find(s => s.type === type && String(s.source[diskFieldName]) === String(disk[diskFieldName]))
+            selectedItem = selectedItem ? selectedItem.target : null
             return (
             return (
               <StorageItem key={disk[diskFieldName]}>
               <StorageItem key={disk[diskFieldName]}>
                 <StorageImage backend={type === 'backend'} />
                 <StorageImage backend={type === 'backend'} />

+ 7 - 4
src/components/organisms/WizardSummary/WizardSummary.jsx

@@ -144,7 +144,6 @@ type Props = {
   schedules: Schedule[],
   schedules: Schedule[],
   storageMap: StorageMap[],
   storageMap: StorageMap[],
   instancesDetails: Instance[],
   instancesDetails: Instance[],
-  defaultStorage: ?StorageBackend,
 }
 }
 @observer
 @observer
 class WizardSummary extends React.Component<Props> {
 class WizardSummary extends React.Component<Props> {
@@ -297,7 +296,6 @@ class WizardSummary extends React.Component<Props> {
             if (
             if (
               optionName === 'execute_now' ||
               optionName === 'execute_now' ||
               optionName === 'separate_vm' ||
               optionName === 'separate_vm' ||
-              optionName === 'default_storage' ||
               !data.destOptions || data.destOptions[optionName] == null
               !data.destOptions || data.destOptions[optionName] == null
             ) {
             ) {
               return null
               return null
@@ -323,7 +321,7 @@ class WizardSummary extends React.Component<Props> {
     let storageMap = this.props.storageMap.filter(mapping => mapping.type === type)
     let storageMap = this.props.storageMap.filter(mapping => mapping.type === type)
     let disks = getDisks(this.props.instancesDetails, type)
     let disks = getDisks(this.props.instancesDetails, type)
 
 
-    if (disks.length === 0 || (storageMap.length === 0 && !this.props.defaultStorage)) {
+    if (disks.length === 0 || storageMap.length === 0) {
       return null
       return null
     }
     }
     let fieldName = type === 'backend' ? 'storage_backend_identifier' : 'id'
     let fieldName = type === 'backend' ? 'storage_backend_identifier' : 'id'
@@ -333,12 +331,17 @@ class WizardSummary extends React.Component<Props> {
       if (diskMapped) {
       if (diskMapped) {
         return { source: diskMapped.source, target: diskMapped.target }
         return { source: diskMapped.source, target: diskMapped.target }
       }
       }
-      return { source: disk, target: this.props.defaultStorage }
+      return { source: disk, target: null }
     })
     })
 
 
     fullStorageMap.sort((m1, m2) => String(m1.source[fieldName]).localeCompare(String(m2.source[fieldName])))
     fullStorageMap.sort((m1, m2) => String(m1.source[fieldName]).localeCompare(String(m2.source[fieldName])))
+    fullStorageMap = fullStorageMap.filter(fsm => fsm.target && fsm.target.id)
     let title = type === 'backend' ? 'Storage Backend Mapping' : 'Disk Mapping'
     let title = type === 'backend' ? 'Storage Backend Mapping' : 'Disk Mapping'
 
 
+    if (fullStorageMap.length === 0) {
+      return null
+    }
+
     return (
     return (
       <Section>
       <Section>
         <SectionTitle>{title}</SectionTitle>
         <SectionTitle>{title}</SectionTitle>

+ 4 - 4
src/plugins/endpoint/default/OptionsSchemaPlugin.js

@@ -137,7 +137,7 @@ export default class OptionsSchemaParser {
     return payload
     return payload
   }
   }
 
 
-  static getStorageMap(defaultStorage: ?string, storageMap: ?StorageMap[]) {
+  static getStorageMap(defaultStorage: ?string, storageMap: ?StorageMap[], configDefault?: ?string) {
     if (!defaultStorage && !storageMap) {
     if (!defaultStorage && !storageMap) {
       return null
       return null
     }
     }
@@ -152,7 +152,7 @@ export default class OptionsSchemaParser {
     }
     }
 
 
     storageMap.forEach(mapping => {
     storageMap.forEach(mapping => {
-      if (mapping.target.id === null) {
+      if (mapping.target.id === null && !configDefault) {
         return
         return
       }
       }
 
 
@@ -162,7 +162,7 @@ export default class OptionsSchemaParser {
         }
         }
         payload.backend_mappings.push({
         payload.backend_mappings.push({
           source: mapping.source.storage_backend_identifier,
           source: mapping.source.storage_backend_identifier,
-          destination: mapping.target.name,
+          destination: mapping.target.id === null ? configDefault : mapping.target.name,
         })
         })
       } else {
       } else {
         if (!payload.disk_mappings) {
         if (!payload.disk_mappings) {
@@ -170,7 +170,7 @@ export default class OptionsSchemaParser {
         }
         }
         payload.disk_mappings.push({
         payload.disk_mappings.push({
           disk_id: mapping.source.id.toString(),
           disk_id: mapping.source.id.toString(),
-          destination: mapping.target.name,
+          destination: mapping.target.id === null ? configDefault : mapping.target.name,
         })
         })
       }
       }
     })
     })

+ 4 - 4
src/sources/ReplicaSource.js

@@ -160,7 +160,7 @@ class ReplicaSource {
     }).then(response => response.data.execution)
     }).then(response => response.data.execution)
   }
   }
 
 
-  static update(replica: MainItem, destinationEndpoint: Endpoint, updateData: UpdateData): Promise<Execution> {
+  static update(replica: MainItem, destinationEndpoint: Endpoint, updateData: UpdateData, storageConfigDefault: string): Promise<Execution> {
     const parser = OptionsSchemaPlugin[destinationEndpoint.type] || OptionsSchemaPlugin.default
     const parser = OptionsSchemaPlugin[destinationEndpoint.type] || OptionsSchemaPlugin.default
     let payload = { replica: {} }
     let payload = { replica: {} }
 
 
@@ -180,9 +180,9 @@ class ReplicaSource {
       payload.replica.source_environment = parser.getDestinationEnv(updateData.source, replica.source_environment)
       payload.replica.source_environment = parser.getDestinationEnv(updateData.source, replica.source_environment)
     }
     }
 
 
-    if (updateData.storage.length > 0) {
-      payload.replica.storage_mappings = parser.getStorageMap(
-        updateData.destination && updateData.destination.default_storage, updateData.storage)
+    let defaultStorage = updateData.destination && updateData.destination.default_storage
+    if (defaultStorage || updateData.storage.length > 0) {
+      payload.replica.storage_mappings = parser.getStorageMap(defaultStorage, updateData.storage, storageConfigDefault)
     }
     }
 
 
     return Api.send({
     return Api.send({

+ 2 - 0
src/stores/EndpointStore.js

@@ -41,6 +41,7 @@ class EndpointStore {
   @observable connectionsInfoLoading = false
   @observable connectionsInfoLoading = false
   @observable storageBackends: StorageBackend[] = []
   @observable storageBackends: StorageBackend[] = []
   @observable storageLoading: boolean = false
   @observable storageLoading: boolean = false
+  @observable storageConfigDefault: string = ''
 
 
   @action getEndpoints(options?: { showLoading: boolean }) {
   @action getEndpoints(options?: { showLoading: boolean }) {
     if (options && options.showLoading) {
     if (options && options.showLoading) {
@@ -185,6 +186,7 @@ class EndpointStore {
     this.storageLoading = true
     this.storageLoading = true
     return EndpointSource.loadStorage(endpointId, data).then(storage => {
     return EndpointSource.loadStorage(endpointId, data).then(storage => {
       this.storageBackends = storage.storage_backends
       this.storageBackends = storage.storage_backends
+      this.storageConfigDefault = storage.config_default || ''
       this.storageLoading = false
       this.storageLoading = false
     }).catch(ex => {
     }).catch(ex => {
       this.storageLoading = false
       this.storageLoading = false

+ 2 - 2
src/stores/ReplicaStore.js

@@ -163,8 +163,8 @@ class ReplicaStore {
     this.replicaDetails = null
     this.replicaDetails = null
   }
   }
 
 
-  @action update(replica: MainItem, destinationEndpoint: Endpoint, updateData: UpdateData) {
-    return ReplicaSource.update(replica, destinationEndpoint, updateData)
+  @action update(replica: MainItem, destinationEndpoint: Endpoint, updateData: UpdateData, storageConfigDefault: string) {
+    return ReplicaSource.update(replica, destinationEndpoint, updateData, storageConfigDefault)
   }
   }
 }
 }
 
 

+ 1 - 1
src/stores/WizardStore.js

@@ -101,7 +101,7 @@ class WizardStore {
   @action updateStorage(storage: StorageMap) {
   @action updateStorage(storage: StorageMap) {
     let diskFieldName = storage.type === 'backend' ? 'storage_backend_identifier' : 'id'
     let diskFieldName = storage.type === 'backend' ? 'storage_backend_identifier' : 'id'
     this.storageMap = this.storageMap
     this.storageMap = this.storageMap
-      .filter(n => n.type !== storage.type || n.source[diskFieldName] !== storage.source[diskFieldName])
+      .filter(n => n.type !== storage.type || String(n.source[diskFieldName]) !== String(storage.source[diskFieldName]))
     this.storageMap.push(storage)
     this.storageMap.push(storage)
   }
   }