ui: add a provider for primary storage when adding zone wizard (#6429)

Fixes #6088

* add provider in creating primary storage when adding new zone

* add custom protocol for SolidFire/PowerFlex provider

* set the custom protocol option available with the rest of the protocol options

* fixes indexOf error & auto-select protocol

* set server=localhost with SharedMountPoint protocol
diff --git a/ui/src/views/infra/zone/StaticInputsForm.vue b/ui/src/views/infra/zone/StaticInputsForm.vue
index 0c23a3a..5eb535f 100644
--- a/ui/src/views/infra/zone/StaticInputsForm.vue
+++ b/ui/src/views/infra/zone/StaticInputsForm.vue
@@ -35,7 +35,7 @@
           :name="field.key"
           :ref="field.key"
           :label="$t(field.title)"
-          v-if="isDisplayInput(field.display)"
+          v-if="isDisplayInput(field)"
           v-bind="formItemLayout"
           :has-feedback="field.switch ? false : true">
           <a-select
@@ -61,6 +61,11 @@
             v-model:checked="form[field.key]"
             v-focus="index === 0"
           />
+          <a-checkbox
+            v-else-if="field.checkbox"
+            v-model:checked="form[field.key]"
+            v-focus="index === 0">
+          </a-checkbox>
           <a-input
             v-else-if="field.password"
             type="password"
@@ -137,6 +142,11 @@
         const fieldsChanged = toRaw(changedFields)
         this.$emit('fieldsChanged', fieldsChanged)
       }
+    },
+    'prefillContent.provider' (val) {
+      if (['SolidFire', 'PowerFlex'].includes(val)) {
+        this.form.primaryStorageProtocol = 'custom'
+      }
     }
   },
   methods: {
@@ -148,17 +158,17 @@
     fillValue () {
       this.fields.forEach(field => {
         this.setRules(field)
-        const fieldExists = this.isDisplayInput(field.display)
+        const fieldExists = this.isDisplayInput(field)
         if (!fieldExists) {
           return
         }
-        if (field.key === 'agentUserName' && !this.getPrefilled(field.key)) {
+        if (field.key === 'agentUserName' && !this.getPrefilled(field)) {
           this.form[field.key] = 'Oracle'
         } else {
-          if (field.switch) {
+          if (field.switch || field.checkbox) {
             this.form[field.key] = this.isChecked(field)
           } else {
-            this.form[field.key] = this.getPrefilled(field.key)
+            this.form[field.key] = this.getPrefilled(field)
           }
         }
       })
@@ -179,8 +189,8 @@
         })
       }
     },
-    getPrefilled (key) {
-      return this.prefillContent?.[key] || null
+    getPrefilled (field) {
+      return this.prefillContent?.[field.key] || field.value || undefined
     },
     handleSubmit () {
       this.formRef.value.validate().then(() => {
@@ -207,7 +217,11 @@
         return Promise.resolve()
       }
     },
-    isDisplayInput (conditions) {
+    isDisplayInput (field) {
+      if (!field.display && !field.hidden) {
+        return true
+      }
+      const conditions = field.display || field.hidden
       if (!conditions || Object.keys(conditions).length === 0) {
         return true
       }
@@ -218,10 +232,19 @@
           const fieldVal = this.form[key]
             ? this.form[key]
             : (this.prefillContent?.[key] || null)
-          if (Array.isArray(condition) && !condition.includes(fieldVal)) {
-            isShow = false
-          } else if (!Array.isArray(condition) && fieldVal !== condition) {
-            isShow = false
+
+          if (field.hidden) {
+            if (Array.isArray(condition) && condition.includes(fieldVal)) {
+              isShow = false
+            } else if (!Array.isArray(condition) && fieldVal === condition) {
+              isShow = false
+            }
+          } else if (field.display) {
+            if (Array.isArray(condition) && !condition.includes(fieldVal)) {
+              isShow = false
+            } else if (!Array.isArray(condition) && fieldVal !== condition) {
+              isShow = false
+            }
           }
         }
       })
diff --git a/ui/src/views/infra/zone/ZoneWizardAddResources.vue b/ui/src/views/infra/zone/ZoneWizardAddResources.vue
index 8a52ec9..ab05a99 100644
--- a/ui/src/views/infra/zone/ZoneWizardAddResources.vue
+++ b/ui/src/views/infra/zone/ZoneWizardAddResources.vue
@@ -500,6 +500,81 @@
           }
         },
         {
+          title: 'label.provider',
+          key: 'provider',
+          placeHolder: 'message.error.select',
+          value: 'DefaultPrimary',
+          select: true,
+          required: true,
+          options: this.primaryStorageProviders
+        },
+        {
+          title: 'label.ismanaged',
+          key: 'managed',
+          checkbox: true,
+          hidden: {
+            provider: ['DefaultPrimary', 'PowerFlex', 'Linstor']
+          }
+        },
+        {
+          title: 'label.capacitybytes',
+          key: 'capacityBytes',
+          hidden: {
+            provider: ['DefaultPrimary', 'PowerFlex', 'Linstor']
+          }
+        },
+        {
+          title: 'label.capacityiops',
+          key: 'capacityIops',
+          hidden: {
+            provider: ['DefaultPrimary', 'PowerFlex', 'Linstor']
+          }
+        },
+        {
+          title: 'label.url',
+          key: 'url',
+          hidden: {
+            provider: ['DefaultPrimary', 'PowerFlex', 'Linstor']
+          }
+        },
+        {
+          title: 'label.powerflex.gateway',
+          key: 'powerflexGateway',
+          required: true,
+          placeHolder: 'message.error.input.value',
+          display: {
+            provider: 'PowerFlex'
+          }
+        },
+        {
+          title: 'label.powerflex.gateway.username',
+          key: 'powerflexGatewayUsername',
+          required: true,
+          placeHolder: 'message.error.input.value',
+          display: {
+            provider: 'PowerFlex'
+          }
+        },
+        {
+          title: 'label.powerflex.gateway.password',
+          key: 'powerflexGatewayPassword',
+          required: true,
+          placeHolder: 'message.error.input.value',
+          password: true,
+          display: {
+            provider: 'PowerFlex'
+          }
+        },
+        {
+          title: 'label.powerflex.storage.pool',
+          key: 'powerflexStoragePool',
+          required: true,
+          placeHolder: 'message.error.input.value',
+          display: {
+            provider: 'PowerFlex'
+          }
+        },
+        {
           title: 'label.storage.tags',
           key: 'primaryStorageTags',
           placeHolder: 'message.error.storage.tags',
@@ -721,9 +796,10 @@
       currentHypervisor: null,
       primaryStorageScopes: [],
       primaryStorageProtocols: [],
+      primaryStorageProviders: [],
       storageProviders: [],
       currentStep: null,
-      options: ['primaryStorageScope', 'primaryStorageProtocol', 'provider']
+      options: ['primaryStorageScope', 'primaryStorageProtocol', 'provider', 'primaryStorageProvider']
     }
   },
   created () {
@@ -750,6 +826,17 @@
       }
     }
   },
+  watch: {
+    'prefillContent.provider' (newVal, oldVal) {
+      if (['SolidFire', 'PowerFlex'].includes(newVal) && !['SolidFire', 'PowerFlex'].includes(oldVal)) {
+        this.$emit('fieldsChanged', { primaryStorageProtocol: undefined })
+      } else if (!['SolidFire', 'PowerFlex'].includes(newVal) && ['SolidFire', 'PowerFlex'].includes(oldVal)) {
+        this.$emit('fieldsChanged', { primaryStorageProtocol: undefined })
+      }
+
+      this.fetchProtocol()
+    }
+  },
   methods: {
     nextPressed () {
       if (this.currentStep === this.steps.length - 1) {
@@ -800,6 +887,9 @@
         case 'provider':
           this.fetchProvider()
           break
+        case 'primaryStorageProvider':
+          this.fetchPrimaryStorageProvider()
+          break
         default:
           break
       }
@@ -912,6 +1002,7 @@
         })
       }
 
+      protocols.push({ id: 'custom', description: 'custom' })
       this.primaryStorageProtocols = protocols
     },
     async fetchConfigurationSwitch () {
@@ -956,6 +1047,13 @@
         this.storageProviders = storageProviders
       })
     },
+    fetchPrimaryStorageProvider () {
+      this.primaryStorageProviders = []
+      api('listStorageProviders', { type: 'primary' }).then(json => {
+        this.primaryStorageProviders = json.liststorageprovidersresponse.dataStoreProvider || []
+        this.primaryStorageProviders.map((item, idx) => { this.primaryStorageProviders[idx].id = item.name })
+      })
+    },
     submitLaunchZone () {
       this.$emit('submitLaunchZone')
     },
diff --git a/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue b/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue
index 377afe7..3630ddb 100644
--- a/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue
+++ b/ui/src/views/infra/zone/ZoneWizardLaunchZone.vue
@@ -1276,6 +1276,7 @@
       params.clusterid = this.stepData.clusterReturned.id
       params.name = this.prefillContent?.primaryStorageName || null
       params.scope = this.prefillContent?.primaryStorageScope || null
+      params.provider = this.prefillContent.provider
 
       if (params.scope === 'zone') {
         const hypervisor = this.prefillContent.hypervisor
@@ -1324,6 +1325,7 @@
         }
         url = this.ocfs2URL(server, path)
       } else if (protocol === 'SharedMountPoint') {
+        server = 'localhost'
         let path = this.prefillContent?.primaryStoragePath || ''
         if (path.substring(0, 1) !== '/') {
           path = '/' + path
@@ -1356,7 +1358,7 @@
         if (protocol === 'datastorecluster') {
           url = this.datastoreclusterURL('dummy', path)
         }
-      } else {
+      } else if (protocol === 'iscsi') {
         let iqn = this.prefillContent?.primaryStorageTargetIQN || ''
         if (iqn.substring(0, 1) !== '/') {
           iqn = '/' + iqn
@@ -1366,6 +1368,27 @@
       }
 
       params.url = url
+      if (this.prefillContent.provider !== 'DefaultPrimary' && this.prefillContent.provider !== 'PowerFlex') {
+        if (this.prefillContent.managed) {
+          params.managed = true
+        } else {
+          params.managed = false
+        }
+        if (this.prefillContent.capacityBytes && this.prefillContent.capacityBytes.length > 0) {
+          params.capacityBytes = this.prefillContent.capacityBytes.split(',').join('')
+        }
+        if (this.prefillContent.capacityIops && this.prefillContent.capacityIops.length > 0) {
+          params.capacityIops = this.prefillContent.capacityIops.split(',').join('')
+        }
+        if (this.prefillContent.url && this.prefillContent.url.length > 0) {
+          params.url = this.prefillContent.url
+        }
+      }
+      if (this.prefillContent.provider === 'PowerFlex') {
+        params.url = this.powerflexURL(this.prefillContent.powerflexGateway, this.prefillContent.powerflexGatewayUsername,
+          this.prefillContent.powerflexGatewayPassword, this.prefillContent.powerflexStoragePool)
+      }
+
       params.tags = this.prefillContent?.primaryStorageTags || ''
 
       try {
@@ -2168,6 +2191,11 @@
         url = server + iqn + '/' + lun
       }
       return url
+    },
+    powerflexURL (gateway, username, password, pool) {
+      var url = 'powerflex://' + encodeURIComponent(username) + ':' + encodeURIComponent(password) + '@' +
+       gateway + '/' + encodeURIComponent(pool)
+      return url
     }
   }
 }