You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2020/06/18 10:21:38 UTC
[cloudstack-primate] branch master updated: network: Acquire public
IP address does not give IP selection option (#423)
This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack-primate.git
The following commit(s) were added to refs/heads/master by this push:
new fc98b5c network: Acquire public IP address does not give IP selection option (#423)
fc98b5c is described below
commit fc98b5c48ac04c572049a8c73375788e4cca29e5
Author: Hoang Nguyen <ho...@unitech.vn>
AuthorDate: Thu Jun 18 17:21:28 2020 +0700
network: Acquire public IP address does not give IP selection option (#423)
Fixes #392
---
src/locales/en.json | 1 +
src/views/network/IpAddressesTab.vue | 226 ++++++++++++++++++++++++-----------
2 files changed, 155 insertions(+), 72 deletions(-)
diff --git a/src/locales/en.json b/src/locales/en.json
index 7d7c04e..cfc8212 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -2142,6 +2142,7 @@
"message.acquire.new.ip": "Please confirm that you would like to acquire a new IP for this network.",
"message.acquire.new.ip.vpc": "Please confirm that you would like to acquire a new IP for this VPC.",
"message.acquire.public.ip": "Please select a zone from which you want to acquire your new IP from.",
+"message.action.acquire.ip": "Please confirm that you want to acquire new IP",
"message.action.cancel.maintenance": "Your host has been successfully canceled for maintenance. This process can take up to several minutes.",
"message.action.cancel.maintenance.mode": "Please confirm that you want to cancel this maintenance.",
"message.action.change.service.warning.for.instance": "Your instance must be stopped before attempting to change its current service offering.",
diff --git a/src/views/network/IpAddressesTab.vue b/src/views/network/IpAddressesTab.vue
index 12fec6e..f08982c 100644
--- a/src/views/network/IpAddressesTab.vue
+++ b/src/views/network/IpAddressesTab.vue
@@ -16,75 +16,105 @@
// under the License.
<template>
- <a-spin :spinning="fetchLoading">
- <a-button :disabled="!('associateIpAddress' in $store.getters.apis)" type="dashed" icon="plus" style="width: 100%; margin-bottom: 15px" @click="acquireIpAddress">
- {{ $t('label.acquire.new.ip') }}
- </a-button>
- <div v-if="$route.path.startsWith('/vpc')">
- Select Tier:
- <a-select
- style="width: 40%; margin-left: 15px;margin-bottom: 15px"
- :loading="fetchLoading"
- defaultActiveFirstOption
- :value="vpcTier"
- @change="handleTierSelect"
- >
- <a-select-option key="all" value="">
- {{ $t('label.view.all') }}
- </a-select-option>
- <a-select-option v-for="network in networksList" :key="network.id" :value="network.id">
- {{ network.name }}
- </a-select-option>
- </a-select>
- </div>
- <a-table
- size="small"
- style="overflow-y: auto"
- :columns="columns"
- :dataSource="ips"
- :rowKey="item => item.id"
- :pagination="false" >
- <template slot="ipaddress" slot-scope="text, record">
- <router-link :to="{ path: '/publicip/' + record.id }" >{{ text }} </router-link>
- <a-tag v-if="record.issourcenat === true">source-nat</a-tag>
- </template>
-
- <template slot="state" slot-scope="text, record">
- <status :text="record.state" displayText />
- </template>
-
- <template slot="virtualmachineid" slot-scope="text, record">
- <a-icon type="desktop" v-if="record.virtualmachineid" />
- <router-link :to="{ path: '/vm/' + record.virtualmachineid }" > {{ record.virtualmachinename || record.virtualmachineid }} </router-link>
- </template>
-
- <template slot="associatednetworkname" slot-scope="text, record">
- <router-link :to="{ path: '/guestnetwork/' + record.associatednetworkid }" > {{ record.associatednetworkname || record.associatednetworkid }} </router-link>
- </template>
-
- <template slot="action" slot-scope="text, record">
- <a-button
- v-if="record.issourcenat !== true"
- type="danger"
- icon="delete"
- shape="circle"
- :disabled="!('disassociateIpAddress' in $store.getters.apis)"
- @click="releaseIpAddress(record)" />
- </template>
- </a-table>
- <a-divider/>
- <a-pagination
- class="row-element pagination"
- size="small"
- :current="page"
- :pageSize="pageSize"
- :total="totalIps"
- :showTotal="total => `Total ${total} items`"
- :pageSizeOptions="['10', '20', '40', '80', '100']"
- @change="changePage"
- @showSizeChange="changePageSize"
- showSizeChanger/>
- </a-spin>
+ <div>
+ <a-spin :spinning="fetchLoading">
+ <a-button
+ :disabled="!('associateIpAddress' in $store.getters.apis)"
+ type="dashed"
+ icon="plus"
+ style="width: 100%; margin-bottom: 15px"
+ @click="onShowAcquireIp">
+ {{ $t('label.acquire.new.ip') }}
+ </a-button>
+ <div v-if="$route.path.startsWith('/vpc')">
+ Select Tier:
+ <a-select
+ style="width: 40%; margin-left: 15px;margin-bottom: 15px"
+ :loading="fetchLoading"
+ defaultActiveFirstOption
+ :value="vpcTier"
+ @change="handleTierSelect"
+ >
+ <a-select-option key="all" value="">
+ {{ $t('label.view.all') }}
+ </a-select-option>
+ <a-select-option v-for="network in networksList" :key="network.id" :value="network.id">
+ {{ network.name }}
+ </a-select-option>
+ </a-select>
+ </div>
+ <a-table
+ size="small"
+ style="overflow-y: auto"
+ :columns="columns"
+ :dataSource="ips"
+ :rowKey="item => item.id"
+ :pagination="false" >
+ <template slot="ipaddress" slot-scope="text, record">
+ <router-link :to="{ path: '/publicip/' + record.id }" >{{ text }} </router-link>
+ <a-tag v-if="record.issourcenat === true">source-nat</a-tag>
+ </template>
+
+ <template slot="state" slot-scope="text, record">
+ <status :text="record.state" displayText />
+ </template>
+
+ <template slot="virtualmachineid" slot-scope="text, record">
+ <a-icon type="desktop" v-if="record.virtualmachineid" />
+ <router-link :to="{ path: '/vm/' + record.virtualmachineid }" > {{ record.virtualmachinename || record.virtualmachineid }} </router-link>
+ </template>
+
+ <template slot="associatednetworkname" slot-scope="text, record">
+ <router-link :to="{ path: '/guestnetwork/' + record.associatednetworkid }" > {{ record.associatednetworkname || record.associatednetworkid }} </router-link>
+ </template>
+
+ <template slot="action" slot-scope="text, record">
+ <a-button
+ v-if="record.issourcenat !== true"
+ type="danger"
+ icon="delete"
+ shape="circle"
+ :disabled="!('disassociateIpAddress' in $store.getters.apis)"
+ @click="releaseIpAddress(record)" />
+ </template>
+ </a-table>
+ <a-divider/>
+ <a-pagination
+ class="row-element pagination"
+ size="small"
+ :current="page"
+ :pageSize="pageSize"
+ :total="totalIps"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="changePage"
+ @showSizeChange="changePageSize"
+ showSizeChanger/>
+ </a-spin>
+ <a-modal
+ v-if="showAcquireIp"
+ :visible="showAcquireIp"
+ :title="$t('label.acquire.new.ip')"
+ :closable="true"
+ @cancel="onCloseModal"
+ @ok="acquireIpAddress"
+ centered
+ width="450px">
+ <a-spin :spinning="acquireLoading">
+ <a-alert :message="$t('message.action.acquire.ip')" type="warning" />
+ <a-form-item :label="$t('label.ipaddress')">
+ <a-select
+ style="width: 100%;"
+ showSearch
+ v-model="acquireIp">
+ <a-select-option
+ v-for="ip in listPublicIpAddress"
+ :key="ip.ipaddress">{{ ip.ipaddress }}</a-select-option>
+ </a-select>
+ </a-form-item>
+ </a-spin>
+ </a-modal>
+ </div>
</template>
<script>
import { api } from '@/api'
@@ -142,7 +172,11 @@ export default {
title: '',
scopedSlots: { customRender: 'action' }
}
- ]
+ ],
+ showAcquireIp: false,
+ acquireLoading: false,
+ acquireIp: null,
+ listPublicIpAddress: []
}
},
mounted () {
@@ -181,6 +215,21 @@ export default {
this.fetchLoading = false
})
},
+ fetchListPublicIpAddress () {
+ return new Promise((resolve, reject) => {
+ const params = {
+ zoneid: this.resource.zoneid,
+ domainid: this.resource.domainid,
+ account: this.resource.account,
+ forvirtualnetwork: true,
+ allocatedonly: false
+ }
+ api('listPublicIpAddresses', params).then(json => {
+ const listPublicIps = json.listpublicipaddressesresponse.publicipaddress || []
+ resolve(listPublicIps)
+ }).catch(reject)
+ })
+ },
handleTierSelect (tier) {
this.vpcTier = tier
this.fetchData()
@@ -205,7 +254,9 @@ export default {
} else {
params.networkid = this.resource.id
}
- this.fetchLoading = true
+ params.ipaddress = this.acquireIp
+ this.acquireLoading = true
+
api('associateIpAddress', params).then(response => {
this.$pollJob({
jobId: response.associateipaddressresponse.jobid,
@@ -221,12 +272,14 @@ export default {
catchMessage: 'Error encountered while fetching async job result'
})
}).catch(error => {
- this.fetchLoading = false
this.$notification.error({
message: `Error ${error.response.status}`,
description: error.response.data.errorresponse.errortext,
duration: 0
})
+ }).finally(() => {
+ this.acquireLoading = false
+ this.onCloseModal()
})
},
releaseIpAddress (ip) {
@@ -255,6 +308,35 @@ export default {
duration: 0
})
})
+ },
+ async onShowAcquireIp () {
+ this.showAcquireIp = true
+ this.acquireLoading = true
+ this.listPublicIpAddress = []
+
+ try {
+ const listPublicIpAddress = await this.fetchListPublicIpAddress()
+ listPublicIpAddress.forEach(item => {
+ if (item.state === 'Free') {
+ this.listPublicIpAddress.push({
+ ipaddress: item.ipaddress
+ })
+ }
+ })
+ this.listPublicIpAddress.sort(function (a, b) {
+ if (a.ipaddress < b.ipaddress) { return -1 }
+ if (a.ipaddress > b.ipaddress) { return 1 }
+ return 0
+ })
+ this.acquireIp = this.listPublicIpAddress && this.listPublicIpAddress.length > 0 ? this.listPublicIpAddress[0].ipaddress : null
+ this.acquireLoading = false
+ } catch (e) {
+ this.acquireLoading = false
+ this.$notifyError(e)
+ }
+ },
+ onCloseModal () {
+ this.showAcquireIp = false
}
}
}