Jelajahi Sumber

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 6 tahun lalu
induk
melakukan
05f53fc9dc

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

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

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

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

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

@@ -143,7 +143,6 @@ export type Props = {
   storageBackends: StorageBackend[],
   instancesDetails: Instance[],
   storageMap: ?StorageMap[],
-  defaultStorage: ?string,
   onChange: (sourceStorage: Disk, targetStorage: StorageBackend, type: 'backend' | 'disk') => void,
 }
 @observer
@@ -184,8 +183,8 @@ class WizardStorage extends React.Component<Props> {
               }
               return false
             }).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 (
               <StorageItem key={disk[diskFieldName]}>
                 <StorageImage backend={type === 'backend'} />

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

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

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

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

+ 2 - 0
src/stores/EndpointStore.js

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

+ 2 - 2
src/stores/ReplicaStore.js

@@ -163,8 +163,8 @@ class ReplicaStore {
     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) {
     let diskFieldName = storage.type === 'backend' ? 'storage_backend_identifier' : 'id'
     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)
   }