// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

<template>
  <div v-if="!isLaunchZone">
    <a-card class="ant-form-text card-waiting-launch">
      <check-circle-two-tone
        twoToneColor="#52c41a"
        style="font-size: 20px;"/>
      {{ $t(description.waiting) }}
    </a-card>
    <div class="form-action">
      <a-button class="button-prev" @click="handleBack">
        {{ $t('label.previous') }}
      </a-button>
      <a-button class="button-next" type="primary" @click="handleSubmit">
        <rocket-outlined /> {{ $t('label.launch.zone') }}
      </a-button>
    </div>
  </div>
  <div v-else>
    <a-card class="ant-form-text card-launch-description">
      {{ $t(description.launching) }}
    </a-card>
    <a-card
      id="launch-content"
      class="ant-form-text card-launch-content">
      <a-steps
        size="small"
        direction="vertical"
        :current="currentStep"
      >
        <a-step
          v-for="(step, index) in steps"
          :key="index"
          :title="$t(step.title)"
          :status="step.status">
          <template #icon>
            <LoadingOutlined v-if="step.status===status.PROCESS" />
            <CloseCircleOutlined v-else-if="step.status===status.FAILED" />
          </template>
          <template #description>
            <a-card
              class="step-error"
              v-if="step.status===status.FAILED"
            >
              <div><strong>{{ $t('label.error.something.went.wrong.please.correct.the.following') }}:</strong></div>
              <div>{{ messageError }}</div>
            </a-card>
          </template>
        </a-step>
      </a-steps>
    </a-card>
    <div class="form-action">
      <a-button
        v-if="processStatus==='finish'"
        class="button-next"
        type="primary"
        :loading="loading"
        @click="enableZoneAction"
      >
        <template #icon><play-circle-outlined /></template>
        {{ $t('label.action.enable.zone') }}
      </a-button>
      <a-button
        v-if="processStatus==='error'"
        class="button-next"
        type="primary"
        @click="handleFixesError"
      >{{ $t('label.fix.errors') }}</a-button>
    </div>
  </div>
</template>

<script>
import { api } from '@/api'

const BASIC_ZONE = 'Basic'
const ADVANCED_ZONE = 'Advanced'
const STATUS_PROCESS = 'process'
const STATUS_FINISH = 'finish'
const STATUS_FAILED = 'error'

export default {
  props: {
    prefillContent: {
      type: Object,
      default: function () {
        return {}
      }
    },
    launchZone: {
      type: Boolean,
      default: false
    },
    launchData: {
      type: Object,
      default () {
        return {}
      }
    },
    stepChild: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      description: {
        waiting: 'message.launch.zone',
        launching: 'message.please.wait.while.zone.is.being.created'
      },
      nsx: false,
      isLaunchZone: false,
      processStatus: null,
      messageError: '',
      currentStep: 0,
      advZoneConfiguredVirtualRouterCount: 0,
      steps: [],
      stepData: {},
      status: {
        PROCESS: STATUS_PROCESS,
        FAILED: STATUS_FAILED,
        FINISH: STATUS_FINISH
      },
      loading: false
    }
  },
  updated () {
    const launchElm = this.$el.querySelector('#launch-content')
    if (launchElm) {
      launchElm.scrollTop = launchElm.scrollHeight
    }
  },
  computed: {
    zoneType () {
      return this.prefillContent?.zoneType || null
    },
    isBasicZone () {
      return this.zoneType === BASIC_ZONE
    },
    isAdvancedZone () {
      return this.zoneType === ADVANCED_ZONE
    },
    isDedicated () {
      return this.prefillContent?.isDedicated || false
    },
    sgEnabled () {
      return this.prefillContent?.securityGroupsEnabled || false
    },
    isEdgeZone () {
      return this.prefillContent?.zoneSuperType === 'Edge' || false
    },
    havingNetscaler () {
      return this.prefillContent?.networkOfferingSelected?.havingNetscaler || false
    },
    havingSG () {
      return this.prefillContent?.networkOfferingSelected?.havingSG || false
    },
    havingEIP () {
      return this.prefillContent?.networkOfferingSelected?.havingEIP || false
    },
    havingELB () {
      return this.prefillContent?.networkOfferingSelected?.havingELB || false
    },
    selectedBaremetalProviders () {
      return this.prefillContent?.networkOfferingSelected?.selectedBaremetalProviders || []
    },
    physicalNetworks () {
      const tungstenNetworks = this.prefillContent.physicalNetworks.filter(network => network.isolationMethod === 'TF')
      if (tungstenNetworks && tungstenNetworks.length > 0) {
        return tungstenNetworks
      }

      return this.prefillContent.physicalNetworks
    }
  },
  mounted () {
    if (this.launchZone) {
      this.processStatus = STATUS_PROCESS
      this.stepData = this.launchData
      if (this.stepChild === 'publicTraffic') {
        this.stepData.returnedPublicTraffic = []
        this.stepData.stepMove = this.stepData.stepMove.filter(item => item.indexOf('createPublicVlanIpRange') === -1)
      }
      if (this.stepChild === 'storageTraffic') {
        this.stepData.tasks = []
        this.stepData.stepMove = this.stepData.stepMove.filter(item => item.indexOf('createStorageNetworkIpRange') === -1)
      }
      // this.handleSubmit()
    }
  },
  methods: {
    addStep (title, step) {
      this.steps.push({
        index: this.currentStep,
        title,
        step,
        status: STATUS_PROCESS
      })
      this.setStepStatus(STATUS_PROCESS)
    },
    setStepStatus (status) {
      const index = this.steps.findIndex(step => step.index === this.currentStep)
      this.steps[index].status = status
      this.nsx = false
    },
    handleBack (e) {
      this.$emit('backPressed')
    },
    async handleSubmit () {
      this.isLaunchZone = true
      this.advZoneConfiguredVirtualRouterCount = 0
      this.processStatus = STATUS_PROCESS
      if (!this.stepData.stepMove) {
        this.stepData.stepMove = []
      }
      await this.stepAddZone()
    },
    handleFixesError () {
      const stepError = this.steps.filter(step => step.index === this.currentStep)
      if (stepError && stepError.length > 0) {
        const step = stepError[0].step
        this.$emit('stepError', step, this.stepData)
      }
    },
    trafficLabelParam (trafficTypeID, physicalNetworkIndex) {
      const hypervisor = this.prefillContent.hypervisor
      physicalNetworkIndex = this.isAdvancedZone ? physicalNetworkIndex : 0
      let physicalNetwork = []
      let trafficConfig = null
      if (this.prefillContent.physicalNetworks) {
        physicalNetwork = this.prefillContent.physicalNetworks[physicalNetworkIndex].traffics.filter(traffic => traffic.type === trafficTypeID)
        trafficConfig = physicalNetwork.length > 0 ? physicalNetwork[0] : null
      }
      let trafficLabel
      if (trafficConfig !== null) {
        if ('label' in trafficConfig) {
          trafficLabel = trafficConfig.label
        } else {
          trafficLabel = ''

          if ('vSwitchName' in trafficConfig) {
            trafficLabel += trafficConfig.vSwitchName
          }
          if ('vlanId' in trafficConfig) {
            if (trafficLabel.length > 0) {
              trafficLabel += ','
            }
            trafficLabel += trafficConfig.vlanId || ''
          }
          if ('vSwitchType' in trafficConfig) {
            if (trafficLabel.length > 0) {
              trafficLabel += ','
            }
            trafficLabel += trafficConfig.vSwitchType
          }

          if (trafficLabel.length === 0) {
            trafficLabel = null
          } else if (trafficLabel.length >= 1) {
            if (trafficLabel.charAt(trafficLabel.length - 1) === ',') {
              trafficLabel = trafficLabel.substring(0, trafficLabel.length - 1)
            }
          }
        }
      }

      let hypervisorAttr
      switch (hypervisor) {
        case 'XenServer':
          hypervisorAttr = 'xennetworklabel'
          break
        case 'KVM':
          hypervisorAttr = 'kvmnetworklabel'
          break
        case 'VMware':
          hypervisorAttr = 'vmwarenetworklabel'
          break
        case 'Hyperv':
          hypervisorAttr = 'hypervnetworklabel'
          break
        case 'BareMetal':
          hypervisorAttr = 'baremetalnetworklabel'
          break
        case 'Ovm':
          hypervisorAttr = 'ovmnetworklabel'
          break
        case 'LXC':
          hypervisorAttr = 'lxcnetworklabel'
          break
        case 'Ovm3':
          hypervisorAttr = 'ovm3networklabel'
          break
      }
      const trafficLabelParams = {}
      if (trafficLabel) {
        trafficLabelParams[hypervisorAttr] = trafficLabel
      }

      return trafficLabelParams
    },
    async stepAddZone () {
      this.addStep('message.creating.zone', 'stepAddZone')

      const guestcidraddress = this.prefillContent?.guestcidraddress || null
      const params = {}
      params.networktype = this.zoneType

      if (this.isBasicZone) {
        if (this.havingSG) {
          params.securitygroupenabled = true
        } else {
          params.securitygroupenabled = false
        }
      } else {
        if (!this.sgEnabled) {
          params.securitygroupenabled = false
          if (guestcidraddress != null && guestcidraddress.length > 0) {
            params.guestcidraddress = guestcidraddress
          }
        } else {
          params.securitygroupenabled = true
        }
      }
      params.name = this.prefillContent?.name
      params.localstorageenabled = this.prefillContent?.localstorageenabled || false
      params.dns1 = this.prefillContent.ipv4Dns1
      params.dns2 = this.prefillContent?.ipv4Dns2 || null
      params.ip6dns1 = this.prefillContent?.ipv6Dns1 || null
      params.ip6dns2 = this.prefillContent?.ipv6Dns2 || null
      params.internaldns1 = this.prefillContent?.internalDns1 || null
      params.internaldns2 = this.prefillContent?.internalDns2 || null
      params.domain = this.prefillContent?.networkDomain || null
      params.isedge = this.isEdgeZone

      try {
        if (!this.stepData.stepMove.includes('createZone')) {
          this.stepData.zoneReturned = await this.createZone(params)
          this.stepData.stepMove.push('createZone')
        }
        await this.stepDedicateZone()
        await this.stepAddPhysicalNetworks()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepDedicateZone () {
      if (!this.isDedicated || this.stepData.stepMove.includes('dedicateZone')) {
        return
      }

      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.dedicate.zone', 'dedicateZone')

      const params = {}
      params.zoneid = this.stepData.zoneReturned.id
      params.domainid = this.prefillContent?.domainId || null
      params.account = this.prefillContent?.account || null

      try {
        await this.dedicateZone(params)
        this.stepData.stepMove.push('dedicateZone')
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepAddPhysicalNetworks () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.creating.physical.networks', 'physicalNetwork')

      const params = {}
      params.zoneid = this.stepData.zoneReturned.id

      if (this.isBasicZone) {
        const requestedTrafficTypeCount = this.prefillContent.physicalNetworks[0].traffics.length
        this.stepData.requestedTrafficTypeCount = requestedTrafficTypeCount
        this.stepData.returnedTrafficTypes = this.stepData?.returnedTrafficTypes || []
        this.stepData.physicalNetworkReturned = this.stepData?.physicalNetworkReturned || {}

        if (this.prefillContent.physicalNetworks && this.prefillContent.physicalNetworks.length > 0) {
          params.name = this.prefillContent.physicalNetworks[0].name
        } else {
          params.name = 'PhysicalNetworkInBasicZone'
        }

        try {
          if (!this.stepData.stepMove.includes('createPhysicalNetwork')) {
            const physicalNetworkResult = await this.createPhysicalNetwork(params)
            this.stepData.physicalNetworkReturned = physicalNetworkResult.jobresult.physicalnetwork
            this.stepData.stepMove.push('createPhysicalNetwork')
          }

          if (!this.stepData.stepMove.includes('Guest')) {
            const guestTrafficResult = await this.addTrafficType('Guest')
            this.stepData.returnedTrafficTypes.push(guestTrafficResult.jobresult.traffictype)
            this.stepData.stepMove.push('Guest')
          }

          if (!this.stepData.stepMove.includes('Management')) {
            const managementTrafficResult = await this.addTrafficType('Management')
            this.stepData.returnedTrafficTypes.push(managementTrafficResult.jobresult.traffictype)
            this.stepData.stepMove.push('Management')
          }

          if (!this.stepData.stepMove.includes('Storage')) {
            // addTrafficType Storage
            const storageEx = this.prefillContent.physicalNetworks[0].traffics.filter(traffic => traffic.type === 'storage')
            if (storageEx && storageEx.length > 0) {
              const storageTrafficResult = await this.addTrafficType('Storage')
              this.stepData.returnedTrafficTypes.push(storageTrafficResult.jobresult.traffictype)
              this.stepData.stepMove.push('Storage')
            }
          }

          if (!this.stepData.stepMove.includes('Public')) {
            if (this.havingSG && this.havingEIP && this.havingELB) {
              const publicTrafficResult = await this.addTrafficType('Public')
              this.stepData.returnedTrafficTypes.push(publicTrafficResult.jobresult.traffictype)
            }
            this.stepData.stepMove.push('Public')
          }

          if (this.stepData.returnedTrafficTypes.length === requestedTrafficTypeCount) {
            this.stepData.physicalNetworkReturned.returnedTrafficTypes = this.stepData.returnedTrafficTypes
            await this.stepConfigurePhysicalNetwork()
          }
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      } else {
        this.stepData.physicalNetworksReturned = this.stepData?.physicalNetworksReturned || []
        this.stepData.physicalNetworkItem = this.stepData?.physicalNetworkItem || {}
        let physicalNetworkReturned = {}

        if (this.stepData.physicalNetworksReturned.length === this.prefillContent.physicalNetworks.length) {
          await this.stepConfigurePhysicalNetwork()
          return
        }

        for (let index = 0; index < this.prefillContent.physicalNetworks.length; index++) {
          const physicalNetwork = this.prefillContent.physicalNetworks[index]
          params.name = physicalNetwork.name

          if (physicalNetwork.isolationMethod) {
            params.isolationmethods = physicalNetwork.isolationMethod
          }
          if (physicalNetwork.tags) {
            params.tags = physicalNetwork.tags
          }

          try {
            if (!this.stepData.stepMove.includes('createPhysicalNetwork' + index)) {
              const physicalNetworkResult = await this.createPhysicalNetwork(params)
              physicalNetworkReturned = physicalNetworkResult.jobresult.physicalnetwork
              this.stepData.physicalNetworkReturned = physicalNetworkReturned
              this.stepData.physicalNetworkItem['createPhysicalNetwork' + index] = physicalNetworkReturned
              this.stepData.stepMove.push('createPhysicalNetwork' + index)

              if (physicalNetwork.isolationMethod === 'TF' &&
                physicalNetwork.traffics.findIndex(traffic => traffic.type === 'public') > -1) {
                this.stepData.isTungstenZone = true
                this.stepData.tungstenPhysicalNetworkId = physicalNetworkReturned.id
              }
              if (physicalNetwork.isolationMethod === 'NSX' &&
                physicalNetwork.traffics.findIndex(traffic => traffic.type === 'public' || traffic.type === 'guest') > -1) {
                this.stepData.isNsxZone = true
                this.stepData.tungstenPhysicalNetworkId = physicalNetworkReturned.id
              }
            } else {
              this.stepData.physicalNetworkReturned = this.stepData.physicalNetworkItem['createPhysicalNetwork' + index]
            }
            if (physicalNetwork.traffics.findIndex(traffic => traffic.type === 'guest') > -1) {
              this.stepData.guestPhysicalNetworkId = physicalNetworkReturned.id
            }
          } catch (e) {
            this.messageError = e
            this.processStatus = STATUS_FAILED
            this.setStepStatus(STATUS_FAILED)
            break
          }

          let advCountTrafficReturn = 0

          for (let key = 0; key < physicalNetwork.traffics.length; key++) {
            const traffic = physicalNetwork.traffics[key]

            try {
              if (!this.stepData.stepMove.includes('addTrafficType' + index + key)) {
                if (traffic.type === 'public') {
                  await this.addTrafficType('Public', index)
                } else if (traffic.type === 'management') {
                  await this.addTrafficType('Management', index)
                } else if (traffic.type === 'guest') {
                  await this.addTrafficType('Guest', index)
                } else if (traffic.type === 'storage') {
                  await this.addTrafficType('Storage', index)
                }
                this.stepData.stepMove.push('addTrafficType' + index + key)
              }

              advCountTrafficReturn++
            } catch (e) {
              this.messageError = e
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              break
            }

            if (advCountTrafficReturn === physicalNetwork.traffics.length) {
              if (Object.keys(physicalNetworkReturned).length > 0) {
                this.stepData.physicalNetworksReturned.push(physicalNetworkReturned)
              }

              if (this.stepData.physicalNetworksReturned.length === this.prefillContent.physicalNetworks.length) {
                await this.stepConfigurePhysicalNetwork()
              }
            }
          }
        }
      }
    },
    async stepConfigurePhysicalNetwork () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.configuring.physical.networks', 'physicalNetwork')

      if (this.isBasicZone) {
        const updPhysicalParams = {}
        updPhysicalParams.state = 'Enabled'
        updPhysicalParams.id = this.stepData.physicalNetworkReturned.id

        try {
          if (!this.stepData.stepMove.includes('updatePhysicalNetwork')) {
            await this.updatePhysicalNetwork(updPhysicalParams)
            this.stepData.stepMove.push('updatePhysicalNetwork')
          }

          if (!this.stepData.stepMove.includes('basicVirtualRouter')) {
            const listNetworkParams = {}
            listNetworkParams.name = 'VirtualRouter'
            listNetworkParams.physicalNetworkId = this.stepData.physicalNetworkReturned.id

            const providerId = await this.listNetworkServiceProviders(listNetworkParams)
            const virtualRouterElementId = await this.listVirtualRouterElements(providerId)
            await this.configureVirtualRouterElement(virtualRouterElementId)
            await this.updateNetworkServiceProvider(providerId)
            this.stepData.stepMove.push('basicVirtualRouter')
          }

          for (let i = 0; i < this.selectedBaremetalProviders.length; i++) {
            if (!this.stepData.stepMove.includes('basicVirtualRouter' + i)) {
              const listParams = {}
              listParams.name = this.selectedBaremetalProviders[i]
              listParams.physicalNetworkId = this.stepData.physicalNetworkReturned.id

              const providerId = await this.listNetworkServiceProviders(listParams, 'BaremetalProvider')
              if (providerId !== null) {
                await this.updateNetworkServiceProvider(providerId)
              }
              this.stepData.stepMove.push('basicVirtualRouter' + i)
            }
          }

          // need to Enable security group provider first
          if (this.havingSG) {
            await this.stepEnableSecurityGroupProvider()
          } else {
            await this.stepAddNetscalerProvider()
          }
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      } else if (this.isAdvancedZone) {
        for (let index = 0; index < this.stepData.physicalNetworksReturned.length; index++) {
          const physicalNetwork = this.stepData.physicalNetworksReturned[index]

          if (!this.stepData.stepMove.includes('advUpdatePhysicalNetwork' + physicalNetwork.id)) {
            const updPhysicalParams = {}
            updPhysicalParams.state = 'Enabled'
            updPhysicalParams.id = physicalNetwork.id

            try {
              await this.updatePhysicalNetwork(updPhysicalParams)
              this.stepData.stepMove.push('advUpdatePhysicalNetwork' + physicalNetwork.id)
            } catch (e) {
              this.messageError = e
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              break
            }
          }

          // ***** Virtual Router ***** (begin) *****
          if (!this.stepData.stepMove.includes('advVirtualRouter' + physicalNetwork.id)) {
            const listParams = {}
            listParams.name = 'VirtualRouter'
            listParams.physicalNetworkId = physicalNetwork.id

            try {
              const providerId = await this.listNetworkServiceProviders(listParams)
              const elementId = await this.listVirtualRouterElements(providerId)
              await this.configureVirtualRouterElement(elementId)
              await this.updateNetworkServiceProvider(providerId)
              this.stepData.stepMove.push('advVirtualRouter' + physicalNetwork.id)
            } catch (e) {
              this.messageError = e
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              break
            }
          }

          this.advZoneConfiguredVirtualRouterCount++

          // ***** Virtual Router ***** (end) *****

          // ***** Ovs ***** (begin) *****
          this.configOvs(physicalNetwork)
          // ***** Ovs ***** (end) *****
          // ***** Internal LB ***** (begin) *****
          this.configInternalLBVM(physicalNetwork)
          // ***** Internal LB ***** (end) *****

          try {
            // Advanced SG-disabled zone
            if (!this.sgEnabled && !this.isEdgeZone) {
              // ***** VPC Virtual Router ***** (begin) *****
              await this.configVpcVirtualRouter(physicalNetwork)
              // ***** VPC Virtual Router ***** (end) *****
            } else if (this.sgEnabled && !this.isEdgeZone) {
              this.stepData.physicalNetworkReturned = physicalNetwork
              await this.stepEnableSecurityGroupProvider()
            }
          } catch (e) {
            this.messageError = e
            this.processStatus = STATUS_FAILED
            this.setStepStatus(STATUS_FAILED)
            break
          }

          if (this.advZoneConfiguredVirtualRouterCount === this.stepData.physicalNetworksReturned.length) {
            if (!this.sgEnabled) {
              await this.stepAddPod()
            } else {
              await this.stepAddGuestNetwork()
            }
          }
        }
      }
    },
    async configOvs (physicalNetwork) {
      if (this.isEdgeZone || this.stepData.stepMove.includes('configOvs' + physicalNetwork.id)) {
        return
      }

      const listParams = {}
      listParams.name = 'Ovs'
      listParams.physicalNetworkId = physicalNetwork.id

      const ovsProviderId = await this.listNetworkServiceProviders(listParams, 'ovsProvider')
      if (ovsProviderId !== null) {
        const ovsElementId = await this.listOvsElements(ovsProviderId)
        if (ovsElementId != null) {
          await this.configureOvsElement(ovsElementId)
          await this.updateNetworkServiceProvider(ovsProviderId)
        }
      }

      this.stepData.stepMove.push('configOvs' + physicalNetwork.id)
    },
    async configInternalLBVM (physicalNetwork) {
      if (this.isEdgeZone || this.stepData.stepMove.includes('configInternalLBVM' + physicalNetwork.id)) {
        return
      }

      const listParams = {}
      listParams.name = 'Internallbvm'
      listParams.physicalNetworkId = physicalNetwork.id

      const internalLbProviderId = await this.listNetworkServiceProviders(listParams, 'configInternalLBVM')
      if (internalLbProviderId !== null) {
        const internalLbElementId = await this.listInternalLoadBalancerElements(internalLbProviderId)
        if (internalLbElementId !== null) {
          await this.configureInternalLoadBalancerElement(internalLbElementId)
          await this.updateNetworkServiceProvider(internalLbProviderId)
        }
      }

      this.stepData.stepMove.push('configInternalLBVM' + physicalNetwork.id)
    },
    async configVpcVirtualRouter (physicalNetwork) {
      const listParams = {}
      listParams.name = 'VpcVirtualRouter'
      listParams.physicalNetworkId = physicalNetwork.id

      try {
        if (!this.stepData.stepMove.includes('configVpcVirtualRouter' + physicalNetwork.id)) {
          const providerId = await this.listNetworkServiceProviders(listParams)
          const elementId = await this.listVirtualRouterElements(providerId)
          await this.configureVirtualRouterElement(elementId)
          await this.updateNetworkServiceProvider(providerId)

          this.stepData.stepMove.push('configVpcVirtualRouter' + physicalNetwork.id)
        }
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepAddNetscalerProvider () {
      if (this.havingNetscaler) {
        this.setStepStatus(STATUS_FINISH)
        this.currentStep++
        this.addStep('message.adding.Netscaler.provider', 'netscaler')

        const params = {}
        params.name = 'Netscaler'
        params.physicalnetworkid = this.stepData.physicalNetworkReturned.id

        try {
          if (!this.stepData.stepMove.includes('addNetworkServiceProvider')) {
            const addResult = await this.addNetworkServiceProvider(params)
            this.stepData.netscalerProviderReturned = addResult.jobresult.networkserviceprovider
            this.stepData.stepMove.push('addNetworkServiceProvider')
          }
          await this.stepAddNetscalerDevice()
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      } else {
        await this.stepAddGuestNetwork()
      }
    },
    async stepAddNetscalerDevice () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.adding.Netscaler.device', 'netscaler')

      const params = {}
      params.physicalnetworkid = this.stepData.physicalNetworkReturned.id
      params.username = this.prefillContent?.netscalerUsername || null
      params.password = this.prefillContent?.netscalerPassword || null
      params.networkdevicetype = this.prefillContent?.netscalerType || null
      params.gslbprovider = this.prefillContent?.gslbprovider || false
      params.gslbproviderpublicip = this.prefillContent?.gslbproviderpublicip || null
      params.gslbproviderprivateip = this.prefillContent?.gslbproviderprivateip || null

      const url = []
      const ip = this.prefillContent.netscalerIp
      url.push('https://' + ip)
      let isQuestionMarkAdded = false
      const publicInterface = this.prefillContent?.publicinterface || null
      if (publicInterface != null && publicInterface.length > 0) {
        if (!isQuestionMarkAdded) {
          url.push('?')
          isQuestionMarkAdded = true
        } else {
          url.push('&')
        }
        url.push('publicinterface=' + publicInterface)
      }

      const privateInterface = this.prefillContent?.privateinterface || null
      if (privateInterface != null && privateInterface.length > 0) {
        if (!isQuestionMarkAdded) {
          url.push('?')
          isQuestionMarkAdded = true
        } else {
          url.push('&')
        }
        url.push('privateinterface=' + publicInterface)
      }

      const numretries = this.prefillContent?.numretries || null
      if (numretries != null && numretries.length > 0) {
        if (!isQuestionMarkAdded) {
          url.push('?')
          isQuestionMarkAdded = true
        } else {
          url.push('&')
        }
        url.push('numretries=' + numretries)
      }

      const capacity = this.prefillContent?.capacity || null
      if (capacity != null && capacity.length > 0) {
        if (!isQuestionMarkAdded) {
          url.push('?')
          isQuestionMarkAdded = true
        } else {
          url.push('&')
        }
        url.push('lbdevicecapacity=' + capacity)
      }

      params.url = encodeURIComponent(url.join(''))

      try {
        if (!this.stepData.stepMove.includes('addNetscalerLoadBalancer')) {
          const addResult = await this.addNetscalerLoadBalancer(params)
          this.stepData.netscalerProviderReturned.netScalerLoadBalancer = addResult.jobresult.netscalerloadbalancer
          this.stepData.stepMove.push('addNetscalerLoadBalancer')
        }
        if (!this.stepData.stepMove.includes('netUpdateNetwork')) {
          await this.updateNetworkServiceProvider(this.stepData.netscalerProviderReturned.id, 'netscalerProvider')
          this.stepData.stepMove.push('netUpdateNetwork')
        }
        await this.stepAddGuestNetwork()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepAddPod () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.creating.pod', 'pod')

      const params = {}
      params.zoneId = this.stepData.zoneReturned.id
      params.name = this.prefillContent?.podName || null
      if (this.isEdgeZone) {
        params.name = 'Pod-' + this.stepData.zoneReturned.name
      }
      params.gateway = this.prefillContent?.podReservedGateway || null
      params.netmask = this.prefillContent?.podReservedNetmask || null
      params.startIp = this.prefillContent?.podReservedStartIp || null
      params.endIp = this.prefillContent?.podReservedStopIp || null

      try {
        if (!this.stepData.stepMove.includes('createPod')) {
          this.stepData.podReturned = await this.createPod(params)
          this.stepData.stepMove.push('createPod')
        }
        await this.stepConfigurePublicTraffic('message.configuring.public.traffic', 'publicTraffic', 0)
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepAddGuestNetwork () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.creating.guest.network', 'guestTraffic')

      const params = {}
      params.zoneid = this.stepData.zoneReturned.id
      params.name = 'defaultGuestNetwork'
      params.displaytext = 'defaultGuestNetwork'
      params.networkofferingid = this.prefillContent?.networkOfferingSelected?.id || null

      if (this.isAdvancedZone && this.sgEnabled) {
        params.gateway = this.prefillContent?.guestGateway || null
        params.netmask = this.prefillContent?.guestNetmask || null
        params.startip = this.prefillContent?.guestStartIp || null
        params.endip = this.prefillContent?.guestStopIp || null
        params.vlan = this.prefillContent?.guestVlan || null
      }

      try {
        if (!this.stepData.stepMove.includes('createNetwork')) {
          this.stepData.networkReturned = await this.createNetwork(params)
          this.stepData.stepMove.push('createNetwork')
        }
        await this.stepAddPod()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepConfigurePublicTraffic (message, trafficType, idx) {
      if (
        (this.isBasicZone &&
          (this.havingSG && this.havingEIP && this.havingELB)) ||
        (this.isAdvancedZone && !this.sgEnabled && !this.isEdgeZone)) {
        this.setStepStatus(STATUS_FINISH)
        this.currentStep++
        this.addStep(message, trafficType)
        if (trafficType === 'nsxPublicTraffic') {
          this.nsx = false
        }

        let stopNow = false
        this.stepData.returnedPublicTraffic = this.stepData?.returnedPublicTraffic || []
        let publicIpRanges = this.prefillContent['public-ipranges']
        publicIpRanges = publicIpRanges.filter(item => item.fornsx === (idx === 1))
        for (let index = 0; index < publicIpRanges.length; index++) {
          const publicVlanIpRange = publicIpRanges[index]
          let isExisting = false

          this.stepData.returnedPublicTraffic.forEach(publicVlan => {
            if (publicVlan.vlan === publicVlanIpRange.vlan &&
              publicVlan.startIp === publicVlanIpRange.startIp &&
              publicVlan.netmask === publicVlanIpRange.netmask &&
              publicVlan.gateway === publicVlanIpRange.gateway) {
              isExisting = true
              return false
            }
          })

          if (isExisting) {
            continue
          }

          const params = {}
          params.zoneId = this.stepData.zoneReturned.id
          if (publicVlanIpRange.vlan && publicVlanIpRange.vlan.length > 0) {
            params.vlan = publicVlanIpRange.vlan
          } else if (publicVlanIpRange.fornsx) {
            params.vlan = null
          } else {
            params.vlan = 'untagged'
          }
          params.gateway = publicVlanIpRange.gateway
          params.netmask = publicVlanIpRange.netmask
          params.startip = publicVlanIpRange.startIp
          params.endip = publicVlanIpRange.endIp
          params.fornsx = publicVlanIpRange.fornsx
          params.forsystemvms = publicVlanIpRange.forsystemvms

          if (this.isBasicZone) {
            params.forVirtualNetwork = true
          } else if (this.isAdvancedZone) {
            if (!this.sgEnabled) {
              params.forVirtualNetwork = true
            } else {
              params.forVirtualNetwork = false
            }
          }

          try {
            if (!this.stepData.stepMove.includes('createPublicVlanIpRange' + idx + index)) {
              const vlanIpRangeItem = await this.createVlanIpRange(params)
              this.stepData.returnedPublicTraffic.push(vlanIpRangeItem)
              this.stepData.stepMove.push('createPublicVlanIpRange' + idx + index)
            }
          } catch (e) {
            this.messageError = e
            this.processStatus = STATUS_FAILED
            this.setStepStatus(STATUS_FAILED)
            stopNow = true
          }
          if (stopNow) {
            break
          }
        }

        if (stopNow) {
          return
        }

        if (idx === 0) {
          await this.stepConfigurePublicTraffic('message.configuring.nsx.public.traffic', 'nsxPublicTraffic', 1)
        } else {
          if (this.stepData.isTungstenZone) {
            await this.stepCreateTungstenFabricPublicNetwork()
          } else if (this.stepData.isNsxZone) {
            await this.stepAddNsxController()
          } else {
            await this.stepConfigureStorageTraffic()
          }
        }
      } else if (this.isAdvancedZone && this.sgEnabled) {
        if (this.stepData.isTungstenZone) {
          await this.stepCreateTungstenFabricPublicNetwork()
        } else {
          await this.stepConfigureStorageTraffic()
        }
      } else {
        if (this.prefillContent.physicalNetworks) {
          const storageExists = this.prefillContent.physicalNetworks[0].traffics.filter(traffic => traffic.type === 'storage')
          if (storageExists && storageExists.length > 0) {
            await this.stepConfigureStorageTraffic()
          } else {
            await this.stepConfigureGuestTraffic()
          }
        }
      }
    },
    async stepCreateTungstenFabricPublicNetwork () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.create.tungsten.public.network', 'tungsten')
      if (this.stepData.stepMove.includes('tungsten')) {
        await this.stepConfigureStorageTraffic()
        return
      }
      try {
        if (!this.stepData.stepMove.includes('createTungstenFabricProvider')) {
          const providerParams = {}
          providerParams.tungstenproviderhostname = this.prefillContent?.tungstenHostname || ''
          providerParams.name = this.prefillContent?.tungstenName || ''
          providerParams.zoneid = this.stepData.zoneReturned.id
          providerParams.tungstenproviderport = this.prefillContent?.tungstenPort || ''
          providerParams.tungstengateway = this.prefillContent?.tungstenGateway || ''
          providerParams.tungstenprovidervrouterport = this.prefillContent?.tungstenVrouter || ''
          providerParams.tungstenproviderintrospectport = this.prefillContent?.tungstenIntrospectPort || ''
          await this.createTungstenFabricProvider(providerParams)
          this.stepData.stepMove.push('createTungstenFabricProvider')
        }
        if (!this.stepData.stepMove.includes('configTungstenFabricService')) {
          const configParams = {}
          configParams.zoneid = this.stepData.zoneReturned.id
          configParams.physicalnetworkid = this.stepData.tungstenPhysicalNetworkId
          await this.configTungstenFabricService(configParams)
          this.stepData.stepMove.push('configTungstenFabricService')
        }
        if (!this.stepData.stepMove.includes('createTungstenFabricManagementNetwork')) {
          const networkParams = {}
          networkParams.podId = this.stepData.podReturned.id
          await this.createTungstenFabricManagementNetwork(networkParams)
          this.stepData.stepMove.push('createTungstenFabricManagementNetwork')
        }
        if (!this.sgEnabled) {
          if (!this.stepData.stepMove.includes('createTungstenFabricPublicNetwork')) {
            const publicParams = {}
            publicParams.zoneId = this.stepData.zoneReturned.id
            await this.createTungstenFabricPublicNetwork(publicParams)
            this.stepData.stepMove.push('createTungstenFabricPublicNetwork')
          }
        }
        this.stepData.stepMove.push('tungsten')
        await this.stepConfigureStorageTraffic()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepAddNsxController () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.add.nsx.controller', 'nsx')
      if (this.stepData.stepMove.includes('nsx')) {
        await this.stepConfigureStorageTraffic()
        return
      }
      try {
        if (!this.stepData.stepMove.includes('addNsxController')) {
          const providerParams = {}
          providerParams.name = this.prefillContent?.nsxName || ''
          providerParams.nsxproviderhostname = this.prefillContent?.nsxHostname || ''
          providerParams.nsxproviderport = this.prefillContent?.nsxPort || ''
          providerParams.username = this.prefillContent?.username || ''
          providerParams.password = this.prefillContent?.password || ''
          providerParams.zoneid = this.stepData.zoneReturned.id
          providerParams.tier0gateway = this.prefillContent?.tier0Gateway || ''
          providerParams.edgecluster = this.prefillContent?.edgeCluster || ''
          providerParams.transportzone = this.prefillContent?.transportZone || ''

          await this.addNsxController(providerParams)
          this.stepData.stepMove.push('addNsxController')
        }
        this.stepData.stepMove.push('nsx')
        await this.stepConfigureStorageTraffic()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepConfigureStorageTraffic () {
      let targetNetwork = false
      this.prefillContent.physicalNetworks.forEach(physicalNetwork => {
        const storageEx = physicalNetwork.traffics.filter(traffic => traffic.type === 'storage')
        if (storageEx && storageEx.length > 0) {
          targetNetwork = true
          return false
        }
      })

      if (!targetNetwork && !this.isNsxZone) {
        await this.stepConfigureGuestTraffic()
        return
      }

      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.configuring.storage.traffic', 'storageTraffic')

      this.stepData.tasks = this.stepData?.tasks || []
      await this.prefillContent['storage-ipranges'].map(async (storageIpRange, index) => {
        const params = {}
        params.vlan = storageIpRange.vlan
        params.gateway = storageIpRange.gateway
        params.netmask = storageIpRange.netmask
        params.startip = storageIpRange.startIp
        params.endip = storageIpRange.endIp
        if (!params.vlan || params.vlan.length === 0) {
          delete params.vlan
        }
        params.zoneid = this.stepData.zoneReturned.id
        params.podid = this.stepData.podReturned.id

        try {
          if (!this.stepData.stepMove.includes('createStorageNetworkIpRange' + index)) {
            const createStorageItem = await this.createStorageNetworkIpRange(params)
            this.stepData.tasks.push(createStorageItem)
            this.stepData.stepMove.push('createStorageNetworkIpRange' + index)
          }
        } catch (e) {
          this.stepData.tasks.push({
            error: true,
            message: e
          })
        }
      })

      const taskTimer = setInterval(() => {
        const completedTasks = this.stepData.tasks.filter(item => item.complete || item.error)
        const errorTasks = this.stepData.tasks.filter(item => item.error)

        if (completedTasks.length === this.prefillContent['storage-ipranges'].length) {
          clearInterval(taskTimer)

          if (errorTasks.length) {
            this.messageError = 'configureStorageTraffic. Error: ' + errorTasks[0].message
            this.processStatus = STATUS_FAILED
            this.setStepStatus(STATUS_FAILED)
            return
          }

          this.stepConfigureGuestTraffic()
          return
        }

        if (this.stepData.tasks.length === this.prefillContent['storage-ipranges'].length) {
          this.stepData.tasks.forEach(async (task) => {
            if (task.error) {
              return true
            }

            const jobResult = await this.pollJob(task.jobid)

            if (jobResult.jobstatus === 1) {
              task.complete = true
            } else if (jobResult.jobstatus === 2) {
              task.error = true
              task.message = jobResult.jobresult.errortext
            }

            return true
          })
        }

        return true
      }, 1000)

      return true
    },
    async stepConfigureGuestTraffic () {
      if (this.prefillContent.skipGuestTrafficStep) {
        await this.stepAddCluster()
        return
      }

      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.configuring.guest.traffic', 'guestTraffic')

      if (this.isBasicZone) {
        const params = {}
        params.podid = this.stepData.podReturned.id
        params.networkid = this.stepData.networkReturned.id
        params.gateway = this.prefillContent?.guestGateway || null
        params.netmask = this.prefillContent?.guestNetmask || null
        params.startip = this.prefillContent?.guestStartIp || null
        params.endip = this.prefillContent?.guestStopIp || null
        params.forVirtualNetwork = false

        try {
          if (!this.stepData.stepMove.includes('createGuestVlanIpRange')) {
            this.stepData.returnedGuestNetwork = await this.createVlanIpRange(params)
            this.stepData.stepMove.push('createGuestVlanIpRange')
          }

          const hypervisor = this.prefillContent.hypervisor
          if (hypervisor === 'BareMetal') {
            await this.stepComplete()
          } else {
            await this.stepAddCluster()
          }
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      } else if (this.isAdvancedZone) {
        const physicalNetworksHavingGuestIncludingVlan = []
        await this.prefillContent.physicalNetworks.map(async (network) => {
          if (this.prefillContent.vlanRangeStart) {
            physicalNetworksHavingGuestIncludingVlan.push(network)
          }
        })

        if (physicalNetworksHavingGuestIncludingVlan.length === 0) {
          await this.stepAddCluster()
        } else {
          let updatedCount = 0

          for (let index = 0; index < physicalNetworksHavingGuestIncludingVlan.length; index++) {
            let vlan = null

            if (!this.prefillContent.vlanRangeEnd || !this.prefillContent.vlanRangeEnd) {
              vlan = this.prefillContent.vlanRangeStart
            } else {
              vlan = [this.prefillContent.vlanRangeStart, this.prefillContent.vlanRangeEnd].join('-')
            }

            const updateParams = {}
            updateParams.id = this.stepData.guestPhysicalNetworkId
            updateParams.vlan = vlan

            try {
              if (!this.stepData.stepMove.includes('advGuestUpdatePhysicalNetwork' + index)) {
                await this.updatePhysicalNetwork(updateParams)
                this.stepData.stepMove.push('advGuestUpdatePhysicalNetwork' + index)
              }
              updatedCount++
              if (updatedCount === physicalNetworksHavingGuestIncludingVlan.length) {
                await this.stepAddCluster()
              }
            } catch (e) {
              this.messageError = e
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              break
            }
          }
        }
      }
    },
    async stepAddCluster () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.creating.cluster', 'clusterResource')

      const hypervisor = this.prefillContent.hypervisor
      const params = {}
      params.zoneId = this.stepData.zoneReturned.id
      params.hypervisor = hypervisor
      let clusterType = null

      if (hypervisor === 'VMware') {
        clusterType = 'ExternalManaged'
      } else {
        clusterType = 'CloudManaged'
      }
      params.clustertype = clusterType
      params.podId = this.stepData.podReturned.id
      let clusterName = this.prefillContent?.clusterName || null
      if (!clusterName && this.isEdgeZone) {
        clusterName = 'Cluster-' + this.stepData.zoneReturned.name
      }
      params.arch = this.prefillContent?.arch || null

      if (hypervisor === 'VMware') {
        params.username = this.prefillContent?.vCenterUsername || null
        params.password = this.prefillContent?.vCenterPassword || null
        params.vsmipaddress = this.prefillContent?.vsmipaddress || null
        params.vsmusername = this.prefillContent?.vsmusername || null
        params.vsmpassword = this.prefillContent?.vsmpassword || null

        const hostname = this.prefillContent?.vCenterHost || null
        const dcName = this.prefillContent?.vCenterDatacenter || null
        let url = null
        if (hostname.indexOf('http://') === -1) {
          url = ['http://', hostname].join('')
        } else {
          url = hostname
        }

        url += '/' + dcName + '/' + clusterName
        params.url = url
        clusterName = hostname + '/' + dcName + '/' + clusterName
      }
      params.clustername = clusterName

      if (hypervisor === 'VMware') {
        const vmwareData = {}
        vmwareData.zoneId = this.stepData.zoneReturned.id
        vmwareData.username = this.prefillContent?.vCenterUsername || null
        vmwareData.password = this.prefillContent?.vCenterPassword || null
        vmwareData.name = this.prefillContent?.vCenterDatacenter || null
        vmwareData.vcenter = this.prefillContent?.vCenterHost || null

        try {
          if (!this.stepData.stepMove.includes('addVmwareDc')) {
            this.stepData.vmWareResult = await this.addVmwareDc(vmwareData)
            this.stepData.stepMove.push('addVmwareDc')
          }

          if (this.stepData.vmWareResult.id !== null) {
            if (!this.stepData.stepMove.includes('addCluster')) {
              this.stepData.clusterReturned = await this.addCluster(params)
              this.stepData.stepMove.push('addCluster')
            }
            await this.stepAddPrimaryStorage()
          }
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      } else {
        try {
          if (!this.stepData.stepMove.includes('addCluster')) {
            this.stepData.clusterReturned = await this.addCluster(params)
            this.stepData.stepMove.push('addCluster')
          }
          await this.stepAddHost()
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      }
    },
    async stepAddHost () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.adding.host', 'hostResource')

      const hostData = {}
      const hostPassword = this.prefillContent?.authmethod !== 'password' ? '' : (this.prefillContent?.hostPassword || null)
      hostData.zoneid = this.stepData.zoneReturned.id
      hostData.podid = this.stepData.podReturned.id
      hostData.clusterid = this.stepData.clusterReturned.id
      hostData.hypervisor = this.stepData.clusterReturned.hypervisortype
      hostData.clustertype = this.stepData.clusterReturned.clustertype
      hostData.hosttags = this.prefillContent?.hostTags || ''
      hostData.username = this.prefillContent?.hostUserName || null
      hostData.password = hostPassword
      const hostname = this.prefillContent?.hostName || null
      let url = null
      if (hostname.indexOf('http://') === -1) {
        url = ['http://', hostname].join('')
      } else {
        url = hostname
      }
      hostData.url = url
      const hypervisor = this.prefillContent.hypervisor

      if (hypervisor === 'Ovm') {
        hostData.agentusername = this.prefillContent?.agentUserName || null
        hostData.agentpassword = this.prefillContent?.agentPassword || null
      }

      if (this.prefillContent.localstorageenabledforsystemvm) {
        const configParams = {}
        configParams.name = 'system.vm.use.local.storage'
        configParams.value = true
        configParams.zoneid = this.stepData.zoneReturned.id

        try {
          await this.updateConfiguration(configParams)
          this.stepData.returnedHost = await this.addHost(hostData)
          await this.stepAddPrimaryStorage()
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      } else {
        try {
          this.stepData.returnedHost = await this.addHost(hostData)
          await this.stepAddPrimaryStorage()
        } catch (e) {
          this.messageError = e
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        }
      }
    },
    async stepAddPrimaryStorage () {
      if (this.prefillContent.localstorageenabled &&
        this.prefillContent.localstorageenabledforsystemvm) {
        await this.stepAddSecondaryStorage()
        return
      }
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.creating.primary.storage', 'primaryResource')

      const params = {}
      params.zoneid = this.stepData.zoneReturned.id
      params.podId = this.stepData.podReturned.id
      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
        if (hypervisor !== undefined) {
          params.hypervisor = hypervisor
        } else if (this.stepData.clusterReturned.hypervisortype !== undefined) {
          params.hypervisor = this.stepData.clusterReturned.hypervisortype
        }
      }

      var server = this.prefillContent?.primaryStorageServer || null
      let url = ''
      const protocol = this.prefillContent.primaryStorageProtocol

      if (protocol === 'nfs') {
        let path = this.prefillContent?.primaryStoragePath || ''
        if (path.substring(0, 1) !== '/') {
          path = '/' + path
        }
        url = this.nfsURL(server, path)
        params['details[0].nfsmountopts'] = this.prefillContent.primaryStorageNFSMountOptions
      } else if (protocol === 'SMB') {
        let path = this.prefillContent?.primaryStoragePath || ''
        if (path.substring(0, 1) !== '/') {
          path = '/' + path
        }
        url = this.smbURL(server, path)
        params['details[0].user'] = this.prefillContent?.primaryStorageSMBUsername || null
        params['details[0].password'] = this.prefillContent?.primaryStorageSMBPassword || null
        params['details[0].domain'] = this.prefillContent?.primaryStorageSMBDomain || null
      } else if (protocol === 'PreSetup') {
        let path = ''
        if (this.stepData.clusterReturned.hypervisortype === 'XenServer') {
          path = this.prefillContent?.primaryStorageSRLabel || ''
          server = 'localhost'
        } else {
          path = this.prefillContent?.primaryStoragePath || ''
        }
        if (path.substring(0, 1) !== '/') {
          path = '/' + path
        }
        url = this.presetupURL(server, path)
      } else if (protocol === 'ocfs2') {
        let path = this.prefillContent?.primaryStoragePath || ''
        if (path.substring(0, 1) !== '/') {
          path = '/' + path
        }
        url = this.ocfs2URL(server, path)
      } else if (protocol === 'SharedMountPoint') {
        server = 'localhost'
        let path = this.prefillContent?.primaryStoragePath || ''
        if (path.substring(0, 1) !== '/') {
          path = '/' + path
        }
        url = this.sharedMountPointURL(server, path)
      } else if (protocol === 'clvm') {
        let vg = this.prefillContent?.primaryStorageVolumeGroup || ''
        if (vg.substring(0, 1) !== '/') {
          vg = '/' + vg
        }
        url = this.clvmURL(vg)
      } else if (protocol === 'rbd') {
        const rbdmonitor = this.prefillContent?.primaryStorageRADOSMonitor || ''
        const rbdpool = this.prefillContent?.primaryStorageRADOSPool || ''
        const rbdid = this.prefillContent?.primaryStorageRADOSUser || ''
        const rbdsecret = this.prefillContent?.primaryStorageRADOSSecret || ''
        url = this.rbdURL(rbdmonitor, rbdpool, rbdid, rbdsecret)
      } else if (protocol === 'Linstor') {
        url = this.linstorURL(server)
        params.provider = 'Linstor'
        params['details[0].resourceGroup'] = this.prefillContent.primaryStorageLinstorResourceGroup
      } else if (protocol === 'vmfs' || protocol === 'datastorecluster') {
        let path = this.prefillContent.primaryStorageVmfsDatacenter
        if (path.substring(0, 1) !== '/') {
          path = '/' + path
        }
        path += '/' + this.prefillContent.primaryStorageVmfsDatastore
        if (protocol === 'vmfs') {
          url = this.vmfsURL('dummy', path)
        }
        if (protocol === 'datastorecluster') {
          url = this.datastoreclusterURL('dummy', path)
        }
      } else if (protocol === 'iscsi') {
        let iqn = this.prefillContent?.primaryStorageTargetIQN || ''
        if (iqn.substring(0, 1) !== '/') {
          iqn = '/' + iqn
        }
        const lun = this.prefillContent?.primaryStorageLUN || ''
        url = this.iscsiURL(server, iqn, lun)
      }

      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 {
        if (!this.stepData.stepMove.includes('createStoragePool')) {
          this.stepData.primaryStorageRetunred = await this.createStoragePool(params)
          this.stepData.stepMove.push('createStoragePool')
        }
        await this.stepAddSecondaryStorage()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepAddSecondaryStorage () {
      if (!this.prefillContent.secondaryStorageProvider ||
      this.prefillContent.secondaryStorageProvider.length === 0) {
        await this.stepComplete()
        return
      }
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.creating.secondary.storage', 'secondaryResource')

      const params = {}
      params.name = this.prefillContent?.secondaryStorageName || null
      if (this.prefillContent.secondaryStorageProvider === 'NFS') {
        const nfsServer = this.prefillContent.secondaryStorageServer
        const path = this.prefillContent.secondaryStoragePath
        const url = this.nfsURL(nfsServer, path)

        params.provider = this.prefillContent.secondaryStorageProvider
        params.zoneid = this.stepData.zoneReturned.id
        params.url = url
      } else if (this.prefillContent.secondaryStorageProvider === 'SMB') {
        const nfsServer = this.prefillContent.secondaryStorageServer
        const path = this.prefillContent.secondaryStoragePath
        const url = this.smbURL(nfsServer, path)

        params.provider = this.prefillContent.secondaryStorageProvider
        params.zoneid = this.stepData.zoneReturned.id
        params.url = url
        params['details[0].key'] = 'user'
        params['details[0].value'] = this.prefillContent.secondaryStorageSMBUsername
        params['details[1].key'] = 'password'
        params['details[1].value'] = this.prefillContent.secondaryStorageSMBPassword
        params['details[2].key'] = 'domain'
        params['details[2].value'] = this.prefillContent.secondaryStorageSMBDomain
      } else if (this.prefillContent.secondaryStorageProvider === 'S3') {
        params.provider = this.prefillContent.secondaryStorageProvider
        params['details[0].key'] = 'accesskey'
        params['details[0].value'] = this.prefillContent.secondaryStorageAccessKey
        params['details[1].key'] = 'secretkey'
        params['details[1].value'] = this.prefillContent.secondaryStorageSecretKey
        params['details[2].key'] = 'bucket'
        params['details[2].value'] = this.prefillContent.secondaryStorageBucket
        params['details[3].key'] = 'usehttps'
        params['details[3].value'] = this.prefillContent?.secondaryStorageHttps || false

        let index = 4
        if (this.prefillContent.secondaryStorageEndpoint &&
          this.prefillContent.secondaryStorageEndpoint.length > 0) {
          params['details[' + index.toString() + '].key'] = 'endpoint'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageEndpoint
          index++
        }
        if (this.prefillContent.secondaryStorageConnectionTimeout &&
          this.prefillContent.secondaryStorageConnectionTimeout.length > 0) {
          params['details[' + index.toString() + '].key'] = 'connectiontimeout'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageConnectionTimeout
          index++
        }
        if (this.prefillContent.secondaryStorageMaxError &&
          this.prefillContent.secondaryStorageMaxError.length > 0) {
          params['details[' + index.toString() + '].key'] = 'maxerrorretry'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageMaxError
          index++
        }
        if (this.prefillContent.secondaryStorageSocketTimeout &&
          this.prefillContent.secondaryStorageSocketTimeout.length > 0) {
          params['details[' + index.toString() + '].key'] = 'sockettimeout'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageSocketTimeout
          index++
        }
      } else if (this.prefillContent.secondaryStorageProvider === 'Swift') {
        params.provider = this.prefillContent.secondaryStorageProvider
        params.url = this.prefillContent.secondaryStorageURL

        let index = 0
        if (this.prefillContent.secondaryStorageAccount &&
          this.prefillContent.secondaryStorageAccount.length > 0) {
          params['details[' + index.toString() + '].key'] = 'account'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageAccount
          index++
        }
        if (this.prefillContent.secondaryStorageUsername &&
          this.prefillContent.secondaryStorageUsername.length > 0) {
          params['details[' + index.toString() + '].key'] = 'username'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageUsername
          index++
        }
        if (this.prefillContent.secondaryStorageKey &&
          this.prefillContent.secondaryStorageKey.length > 0) {
          params['details[' + index.toString() + '].key'] = 'key'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStorageKey
          index++
        }
        if (this.prefillContent.secondaryStoragePolicy &&
          this.prefillContent.secondaryStoragePolicy.value.length > 0) {
          params['details[' + index.toString() + '].key'] = 'storagepolicy'
          params['details[' + index.toString() + '].value'] = this.prefillContent.secondaryStoragePolicy
          index++
        }
      }

      try {
        if (!this.stepData.stepMove.includes('addImageStore')) {
          await this.addImageStore(params)
          this.stepData.stepMove.push('addImageStore')
        }

        if (this.prefillContent.secondaryStorageNFSStaging && this.prefillContent.secondaryStorageNFSStaging) {
          const nfsServer = this.prefillContent.secondaryStorageNFSServer
          const path = this.prefillContent.secondaryStorageNFSPath
          const url = this.nfsURL(nfsServer, path)

          const nfsParams = {}
          nfsParams.provider = 'nfs'
          nfsParams.zoneid = this.stepData.zoneReturned.id
          nfsParams.url = url

          if (!this.stepData.stepMove.includes('createSecondaryStagingStore')) {
            await this.createSecondaryStagingStore(nfsParams)
            this.stepData.stepMove.push('createSecondaryStagingStore')
          }
        }

        await this.stepComplete()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    async stepEnableSecurityGroupProvider () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.enabling.security.group.provider', 'stepZone')

      const listNetworkParams = {}
      listNetworkParams.name = 'SecurityGroupProvider'
      listNetworkParams.physicalNetworkId = this.stepData.physicalNetworkReturned.id

      try {
        if (!this.stepData.stepMove.includes('enableSecurityGroupProvider' + this.stepData.physicalNetworkReturned.id)) {
          const securityGroupProviderId = await this.listNetworkServiceProviders(listNetworkParams)
          await this.updateNetworkServiceProvider(securityGroupProviderId, 'enableSecurityGroupProvider')
          this.stepData.stepMove.push('enableSecurityGroupProvider' + this.stepData.physicalNetworkReturned.id)
        }

        await this.stepAddNetscalerProvider()
      } catch (e) {
        this.messageError = e
        this.processStatus = STATUS_FAILED
        this.setStepStatus(STATUS_FAILED)
      }
    },
    stepComplete () {
      this.setStepStatus(STATUS_FINISH)
      this.currentStep++
      this.addStep('message.zone.creation.complete', 'stepComplete')
      this.setStepStatus(STATUS_FINISH)
      this.processStatus = STATUS_FINISH
    },
    async enableZoneAction () {
      const params = {}
      params.allocationstate = 'Enabled'
      params.id = this.stepData.zoneReturned.id
      this.loading = true

      try {
        await this.enableZone(params)
        await this.$message.success('Success')
        this.loading = false
        this.steps = []
        this.$emit('closeAction')
        this.$emit('refresh-data')
      } catch (e) {
        this.loading = false
        await this.$notification.error({
          message: this.$t('message.request.failed'),
          description: e
        })
      }
    },
    async pollJob (jobId) {
      return new Promise(resolve => {
        const asyncJobInterval = setInterval(() => {
          api('queryAsyncJobResult', { jobId }).then(async json => {
            const result = json.queryasyncjobresultresponse
            if (result.jobstatus === 0) {
              return
            }

            clearInterval(asyncJobInterval)
            resolve(result)
          })
        }, 1000)
      })
    },
    createZone (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createZone', args).then(json => {
          const zone = json.createzoneresponse.zone
          resolve(zone)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    dedicateZone (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('dedicateZone', args).then(json => {
          resolve()
        }).catch(error => {
          message = error.response.headers['x-description']
          resolve(message)
        })
      })
    },
    async createPhysicalNetwork (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createPhysicalNetwork', args).then(async json => {
          const jobId = json.createphysicalnetworkresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `createPhysicalNetwork ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: ` + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addTrafficType (trafficType, index) {
      const getTrafficParams = this.trafficLabelParam(trafficType.toLowerCase(), index)
      let params = {}

      params.trafficType = trafficType
      params.physicalnetworkid = this.stepData.physicalNetworkReturned.id
      params = { ...params, ...getTrafficParams }

      return new Promise((resolve, reject) => {
        let message = ''

        api('addTrafficType', params).then(async json => {
          const jobId = json.addtraffictyperesponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              this.setStepStatus(STATUS_FAILED)
              message = `${this.$t('message.failed.to.add')} ` + trafficType +
                ` ${this.$t('message.traffic.type.to.basic.zone')}. ${this.$t('label.error')}: ` +
                result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    updatePhysicalNetwork (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('updatePhysicalNetwork', args).then(async json => {
          const jobId = json.updatephysicalnetworkresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `updatePhysicalNetwork ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: ` + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    listNetworkServiceProviders (params, type) {
      return new Promise((resolve, reject) => {
        let providerId = null
        let message = ''

        api('listNetworkServiceProviders', params).then(json => {
          const items = json.listnetworkserviceprovidersresponse.networkserviceprovider
          if (items != null && items.length > 0) {
            providerId = items[0].id
          }
          if (!type && providerId == null) {
            message = this.$t('message.listnsp.not.return.providerid')
            reject(message)
            return
          }
          resolve(providerId)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    listVirtualRouterElements (virtualRouterProviderId) {
      return new Promise((resolve, reject) => {
        let virtualRouterElementId = null
        let message = ''

        api('listVirtualRouterElements', { nspid: virtualRouterProviderId }).then(json => {
          const items = json.listvirtualrouterelementsresponse.virtualrouterelement
          if (items != null && items.length > 0) {
            virtualRouterElementId = items[0].id
          }
          if (virtualRouterElementId === null) {
            message = this.$t('message.virtual.router.not.return.elementid')
            reject(message)
            return
          }
          resolve(virtualRouterElementId)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    configureVirtualRouterElement (virtualRouterElementId) {
      return new Promise((resolve, reject) => {
        let message = ''
        const params = {}
        params.enabled = true
        params.id = virtualRouterElementId

        api('configureVirtualRouterElement', params).then(async json => {
          const jobId = json.configurevirtualrouterelementresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `configureVirtualRouterElement ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: ` + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    updateNetworkServiceProvider (providerId, type) {
      return new Promise((resolve, reject) => {
        let message = ''
        const params = {}

        params.id = providerId
        params.state = 'Enabled'

        api('updateNetworkServiceProvider', params).then(async json => {
          const jobId = json.updatenetworkserviceproviderresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `updateNetworkServiceProvider ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: `
              switch (type) {
                case 'netscalerProvider':
                  message = `${this.$t('message.enable.netsacler.provider.failed')}. ${this.$t('label.error')}: `
                  break
                case 'enableSecurityGroupProvider':
                  message = `${this.$t('message.enable.securitygroup.provider.failed')}. ${this.$t('label.error')}: `
                  break
              }
              message += result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    listOvsElements (ovsProviderId) {
      return new Promise((resolve, reject) => {
        let message = ''
        let ovsElementId = null

        api('listOvsElements', { nspid: ovsProviderId }).then(json => {
          const items = json.listovselementsresponse.ovselement
          if (items != null && items.length > 0) {
            ovsElementId = items[0].id
          }
          resolve(ovsElementId)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    configureOvsElement (ovsElementId) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('configureOvsElement', { enabled: true, id: ovsElementId }).then(async json => {
          const jobId = json.configureovselementresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `configureOvsElement ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: ` + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    listInternalLoadBalancerElements (internalLbProviderId) {
      return new Promise((resolve, reject) => {
        let internalLbElementId = null
        let message = ''

        api('listInternalLoadBalancerElements', { nspid: internalLbProviderId }).then(json => {
          const items = json.listinternalloadbalancerelementsresponse.internalloadbalancerelement
          if (items != null && items.length > 0) {
            internalLbElementId = items[0].id
          }
          if (internalLbElementId == null) {
            message = this.$t('message.interloadbalance.not.return.elementid')
            reject(message)
            return
          }
          resolve(internalLbElementId)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    configureInternalLoadBalancerElement (internalLbElementId) {
      return new Promise((resolve, reject) => {
        let message = ''
        api('configureInternalLoadBalancerElement', { enabled: true, id: internalLbElementId }).then(async json => {
          const jobId = json.configureinternalloadbalancerelementresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `configureVirtualRouterElement ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: ` + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addNetworkServiceProvider (arg) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('addNetworkServiceProvider', arg).then(async json => {
          const jobId = json.addnetworkserviceproviderresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = `addNetworkServiceProvider&name=Netscaler ${this.$t('label.failed').toLowerCase()}. ${this.$t('label.error')}: ` + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createNetwork (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createNetwork', args).then(json => {
          const returnedGuestNetwork = json.createnetworkresponse.network
          resolve(returnedGuestNetwork)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createPod (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createPod', args).then(json => {
          const returnedPod = json.createpodresponse.pod
          resolve(returnedPod)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createVlanIpRange (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createVlanIpRange', args).then(json => {
          const item = json.createvlaniprangeresponse.vlan
          resolve(item)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createStorageNetworkIpRange (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createStorageNetworkIpRange', args).then(async json => {
          const jobId = json.createstoragenetworkiprangeresponse.jobid
          resolve({
            jobid: jobId,
            complete: false
          })
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addVmwareDc (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('addVmwareDc', {}, 'POST', args).then(json => {
          const item = json.addvmwaredcresponse.vmwaredc
          resolve(item)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addCluster (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('addCluster', args, 'POST').then(json => {
          const result = json.addclusterresponse.cluster[0]
          resolve(result)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addHost (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('addHost', {}, 'POST', args).then(json => {
          const result = json.addhostresponse.host[0]
          resolve(result)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    updateConfiguration (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('updateConfiguration', args).then(json => {
          resolve()
        }).catch(error => {
          message = error.response.headers['x-description']
          if (message.includes('is already in the database')) {
            resolve()
          } else {
            reject(message)
          }
        })
      })
    },
    createStoragePool (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createStoragePool', args).then(json => {
          const result = json.createstoragepoolresponse.storagepool
          resolve(result)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addImageStore (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('addImageStore', args).then(json => {
          const result = json.addimagestoreresponse.secondarystorage
          resolve(result)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createSecondaryStagingStore (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('createSecondaryStagingStore', args).then(json => {
          const result = json.addimagestoreresponse.secondarystorage
          resolve(result)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addNetscalerLoadBalancer (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('addNetscalerLoadBalancer', {}, 'POST', args).then(async json => {
          const jobId = json.addnetscalerloadbalancerresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              message = 'addNetscalerDevice ' + result.jobresult.errortext
              reject(message)
              return
            }
            resolve(result)
          }
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    enableZone (args) {
      return new Promise((resolve, reject) => {
        let message = ''

        api('updateZone', args).then(json => {
          const result = json.updatezoneresponse.zone
          resolve(result)
        }).catch(error => {
          message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createTungstenFabricProvider (args) {
      return new Promise((resolve, reject) => {
        api('createTungstenFabricProvider', {}, 'POST', args).then(json => {
          resolve()
        }).catch(error => {
          const message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    addNsxController (args) {
      return new Promise((resolve, reject) => {
        api('addNsxController', {}, 'POST', args).then(json => {
          resolve()
        }).catch(error => {
          const message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    configTungstenFabricService (args) {
      return new Promise((resolve, reject) => {
        api('configTungstenFabricService', {}, 'POST', args).then(json => {
          resolve()
        }).catch(error => {
          const message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createTungstenFabricManagementNetwork (args) {
      return new Promise((resolve, reject) => {
        api('createTungstenFabricManagementNetwork', args).then(json => {
          resolve()
        }).catch(error => {
          const message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    createTungstenFabricPublicNetwork (args) {
      return new Promise((resolve, reject) => {
        api('createTungstenFabricPublicNetwork', args).then(json => {
          resolve()
        }).catch(error => {
          const message = error.response.headers['x-description']
          reject(message)
        })
      })
    },
    nfsURL (server, path) {
      let url = null
      if (path.substring(0, 1) !== '/') {
        path = '/' + path
      }
      if (server.indexOf('://') === -1) {
        url = 'nfs://' + server + path
      } else {
        url = server + path
      }
      return url
    },
    smbURL (server, path, smbUsername, smbPassword, smbDomain) {
      let url = ''
      if (path.substring(0, 1) !== '/') {
        path = '/' + path
      }
      if (server.indexOf('://') === -1) {
        url += 'cifs://'
      }
      url += (server + path)
      return url
    },
    presetupURL (server, path) {
      let url = null
      if (server.indexOf('://') === -1) {
        url = 'presetup://' + server + path
      } else {
        url = server + path
      }
      return url
    },
    ocfs2URL (server, path) {
      let url = null
      if (server.indexOf('://') === -1) {
        url = 'ocfs2://' + server + path
      } else {
        url = server + path
      }
      return url
    },
    sharedMountPointURL (server, path) {
      let url = ''
      if (server.indexOf('://') === -1) {
        url = 'SharedMountPoint://' + server + path
      } else {
        url = server + path
      }
      return url
    },
    rbdURL (monitor, pool, id, secret) {
      let url
      secret = secret.replace(/\+/g, '-')
      secret = secret.replace(/\//g, '_')
      if (id != null && secret != null) {
        monitor = id + ':' + secret + '@' + monitor
      }
      if (pool.substring(0, 1) !== '/') {
        pool = '/' + pool
      }
      if (monitor.indexOf('://') === -1) {
        url = 'rbd://' + monitor + pool
      } else {
        url = monitor + pool
      }

      return url
    },
    clvmURL (vgname) {
      let url = ''
      if (vgname.indexOf('://') === -1) {
        url = 'clvm://localhost/' + vgname
      } else {
        url = vgname
      }
      return url
    },
    vmfsURL (server, path) {
      let url = ''
      if (server.indexOf('://') === -1) {
        url = 'vmfs://' + server + path
      } else {
        url = server + path
      }
      return url
    },
    linstorURL (server) {
      var url
      if (server.indexOf('://') === -1) {
        url = 'http://' + server
      } else {
        url = server
      }
      return url
    },
    datastoreclusterURL (server, path) {
      var url
      if (server.indexOf('://') === -1) {
        url = 'datastorecluster://' + server + path
      } else {
        url = server + path
      }
      return url
    },
    iscsiURL (server, iqn, lun) {
      let url = ''
      if (server.indexOf('://') === -1) {
        url = 'iscsi://' + server + iqn + '/' + lun
      } else {
        url = server + iqn + '/' + lun
      }
      return url
    },
    powerflexURL (gateway, username, password, pool) {
      var url = 'powerflex://' + encodeURIComponent(username) + ':' + encodeURIComponent(password) + '@' +
       gateway + '/' + encodeURIComponent(pool)
      return url
    }
  }
}
</script>

<style scoped lang="less">
  .card-waiting-launch {
    text-align: center;
    margin: 10px 0;
    width: 100%;
    padding: 20px;
    font-size: 20px;
  }

  .card-launch-description {
    text-align: justify;
    margin: 10px 0;
    width: 100%;
    padding: 0;
  }

  .card-launch-content {
    text-align: justify;
    margin: 10px 0;
    width: 100%;
    font-size: 15px;
    max-height: 45vh;
    overflow-y: auto;
  }

  :deep(.step-error) {
    color: #f5222d;
    margin-top: 20px;

    :deep(.ant-card-body) {
      padding: 15px;
      text-align: justify;
    }
  }
</style>
