Skip to content
This repository was archived by the owner on Jan 20, 2021. It is now read-only.

Commit 3dc4cc4

Browse files
Hoang Nguyenustcweizhou
authored andcommitted
network: Acquire public IP address does not give IP selection option (#423)
Fixes #392
1 parent 865d7a2 commit 3dc4cc4

2 files changed

Lines changed: 155 additions & 72 deletions

File tree

src/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,6 +2142,7 @@
21422142
"message.acquire.new.ip": "Please confirm that you would like to acquire a new IP for this network.",
21432143
"message.acquire.new.ip.vpc": "Please confirm that you would like to acquire a new IP for this VPC.",
21442144
"message.acquire.public.ip": "Please select a zone from which you want to acquire your new IP from.",
2145+
"message.action.acquire.ip": "Please confirm that you want to acquire new IP",
21452146
"message.action.cancel.maintenance": "Your host has been successfully canceled for maintenance. This process can take up to several minutes.",
21462147
"message.action.cancel.maintenance.mode": "Please confirm that you want to cancel this maintenance.",
21472148
"message.action.change.service.warning.for.instance": "Your instance must be stopped before attempting to change its current service offering.",

src/views/network/IpAddressesTab.vue

Lines changed: 154 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,75 +16,105 @@
1616
// under the License.
1717

1818
<template>
19-
<a-spin :spinning="fetchLoading">
20-
<a-button :disabled="!('associateIpAddress' in $store.getters.apis)" type="dashed" icon="plus" style="width: 100%; margin-bottom: 15px" @click="acquireIpAddress">
21-
{{ $t('label.acquire.new.ip') }}
22-
</a-button>
23-
<div v-if="$route.path.startsWith('/vpc')">
24-
Select Tier:
25-
<a-select
26-
style="width: 40%; margin-left: 15px;margin-bottom: 15px"
27-
:loading="fetchLoading"
28-
defaultActiveFirstOption
29-
:value="vpcTier"
30-
@change="handleTierSelect"
31-
>
32-
<a-select-option key="all" value="">
33-
{{ $t('label.view.all') }}
34-
</a-select-option>
35-
<a-select-option v-for="network in networksList" :key="network.id" :value="network.id">
36-
{{ network.name }}
37-
</a-select-option>
38-
</a-select>
39-
</div>
40-
<a-table
41-
size="small"
42-
style="overflow-y: auto"
43-
:columns="columns"
44-
:dataSource="ips"
45-
:rowKey="item => item.id"
46-
:pagination="false" >
47-
<template slot="ipaddress" slot-scope="text, record">
48-
<router-link :to="{ path: '/publicip/' + record.id }" >{{ text }} </router-link>
49-
<a-tag v-if="record.issourcenat === true">source-nat</a-tag>
50-
</template>
51-
52-
<template slot="state" slot-scope="text, record">
53-
<status :text="record.state" displayText />
54-
</template>
55-
56-
<template slot="virtualmachineid" slot-scope="text, record">
57-
<a-icon type="desktop" v-if="record.virtualmachineid" />
58-
<router-link :to="{ path: '/vm/' + record.virtualmachineid }" > {{ record.virtualmachinename || record.virtualmachineid }} </router-link>
59-
</template>
60-
61-
<template slot="associatednetworkname" slot-scope="text, record">
62-
<router-link :to="{ path: '/guestnetwork/' + record.associatednetworkid }" > {{ record.associatednetworkname || record.associatednetworkid }} </router-link>
63-
</template>
64-
65-
<template slot="action" slot-scope="text, record">
66-
<a-button
67-
v-if="record.issourcenat !== true"
68-
type="danger"
69-
icon="delete"
70-
shape="circle"
71-
:disabled="!('disassociateIpAddress' in $store.getters.apis)"
72-
@click="releaseIpAddress(record)" />
73-
</template>
74-
</a-table>
75-
<a-divider/>
76-
<a-pagination
77-
class="row-element pagination"
78-
size="small"
79-
:current="page"
80-
:pageSize="pageSize"
81-
:total="totalIps"
82-
:showTotal="total => `Total ${total} items`"
83-
:pageSizeOptions="['10', '20', '40', '80', '100']"
84-
@change="changePage"
85-
@showSizeChange="changePageSize"
86-
showSizeChanger/>
87-
</a-spin>
19+
<div>
20+
<a-spin :spinning="fetchLoading">
21+
<a-button
22+
:disabled="!('associateIpAddress' in $store.getters.apis)"
23+
type="dashed"
24+
icon="plus"
25+
style="width: 100%; margin-bottom: 15px"
26+
@click="onShowAcquireIp">
27+
{{ $t('label.acquire.new.ip') }}
28+
</a-button>
29+
<div v-if="$route.path.startsWith('/vpc')">
30+
Select Tier:
31+
<a-select
32+
style="width: 40%; margin-left: 15px;margin-bottom: 15px"
33+
:loading="fetchLoading"
34+
defaultActiveFirstOption
35+
:value="vpcTier"
36+
@change="handleTierSelect"
37+
>
38+
<a-select-option key="all" value="">
39+
{{ $t('label.view.all') }}
40+
</a-select-option>
41+
<a-select-option v-for="network in networksList" :key="network.id" :value="network.id">
42+
{{ network.name }}
43+
</a-select-option>
44+
</a-select>
45+
</div>
46+
<a-table
47+
size="small"
48+
style="overflow-y: auto"
49+
:columns="columns"
50+
:dataSource="ips"
51+
:rowKey="item => item.id"
52+
:pagination="false" >
53+
<template slot="ipaddress" slot-scope="text, record">
54+
<router-link :to="{ path: '/publicip/' + record.id }" >{{ text }} </router-link>
55+
<a-tag v-if="record.issourcenat === true">source-nat</a-tag>
56+
</template>
57+
58+
<template slot="state" slot-scope="text, record">
59+
<status :text="record.state" displayText />
60+
</template>
61+
62+
<template slot="virtualmachineid" slot-scope="text, record">
63+
<a-icon type="desktop" v-if="record.virtualmachineid" />
64+
<router-link :to="{ path: '/vm/' + record.virtualmachineid }" > {{ record.virtualmachinename || record.virtualmachineid }} </router-link>
65+
</template>
66+
67+
<template slot="associatednetworkname" slot-scope="text, record">
68+
<router-link :to="{ path: '/guestnetwork/' + record.associatednetworkid }" > {{ record.associatednetworkname || record.associatednetworkid }} </router-link>
69+
</template>
70+
71+
<template slot="action" slot-scope="text, record">
72+
<a-button
73+
v-if="record.issourcenat !== true"
74+
type="danger"
75+
icon="delete"
76+
shape="circle"
77+
:disabled="!('disassociateIpAddress' in $store.getters.apis)"
78+
@click="releaseIpAddress(record)" />
79+
</template>
80+
</a-table>
81+
<a-divider/>
82+
<a-pagination
83+
class="row-element pagination"
84+
size="small"
85+
:current="page"
86+
:pageSize="pageSize"
87+
:total="totalIps"
88+
:showTotal="total => `Total ${total} items`"
89+
:pageSizeOptions="['10', '20', '40', '80', '100']"
90+
@change="changePage"
91+
@showSizeChange="changePageSize"
92+
showSizeChanger/>
93+
</a-spin>
94+
<a-modal
95+
v-if="showAcquireIp"
96+
:visible="showAcquireIp"
97+
:title="$t('label.acquire.new.ip')"
98+
:closable="true"
99+
@cancel="onCloseModal"
100+
@ok="acquireIpAddress"
101+
centered
102+
width="450px">
103+
<a-spin :spinning="acquireLoading">
104+
<a-alert :message="$t('message.action.acquire.ip')" type="warning" />
105+
<a-form-item :label="$t('label.ipaddress')">
106+
<a-select
107+
style="width: 100%;"
108+
showSearch
109+
v-model="acquireIp">
110+
<a-select-option
111+
v-for="ip in listPublicIpAddress"
112+
:key="ip.ipaddress">{{ ip.ipaddress }}</a-select-option>
113+
</a-select>
114+
</a-form-item>
115+
</a-spin>
116+
</a-modal>
117+
</div>
88118
</template>
89119
<script>
90120
import { api } from '@/api'
@@ -142,7 +172,11 @@ export default {
142172
title: '',
143173
scopedSlots: { customRender: 'action' }
144174
}
145-
]
175+
],
176+
showAcquireIp: false,
177+
acquireLoading: false,
178+
acquireIp: null,
179+
listPublicIpAddress: []
146180
}
147181
},
148182
mounted () {
@@ -181,6 +215,21 @@ export default {
181215
this.fetchLoading = false
182216
})
183217
},
218+
fetchListPublicIpAddress () {
219+
return new Promise((resolve, reject) => {
220+
const params = {
221+
zoneid: this.resource.zoneid,
222+
domainid: this.resource.domainid,
223+
account: this.resource.account,
224+
forvirtualnetwork: true,
225+
allocatedonly: false
226+
}
227+
api('listPublicIpAddresses', params).then(json => {
228+
const listPublicIps = json.listpublicipaddressesresponse.publicipaddress || []
229+
resolve(listPublicIps)
230+
}).catch(reject)
231+
})
232+
},
184233
handleTierSelect (tier) {
185234
this.vpcTier = tier
186235
this.fetchData()
@@ -205,7 +254,9 @@ export default {
205254
} else {
206255
params.networkid = this.resource.id
207256
}
208-
this.fetchLoading = true
257+
params.ipaddress = this.acquireIp
258+
this.acquireLoading = true
259+
209260
api('associateIpAddress', params).then(response => {
210261
this.$pollJob({
211262
jobId: response.associateipaddressresponse.jobid,
@@ -221,12 +272,14 @@ export default {
221272
catchMessage: 'Error encountered while fetching async job result'
222273
})
223274
}).catch(error => {
224-
this.fetchLoading = false
225275
this.$notification.error({
226276
message: `Error ${error.response.status}`,
227277
description: error.response.data.errorresponse.errortext,
228278
duration: 0
229279
})
280+
}).finally(() => {
281+
this.acquireLoading = false
282+
this.onCloseModal()
230283
})
231284
},
232285
releaseIpAddress (ip) {
@@ -255,6 +308,35 @@ export default {
255308
duration: 0
256309
})
257310
})
311+
},
312+
async onShowAcquireIp () {
313+
this.showAcquireIp = true
314+
this.acquireLoading = true
315+
this.listPublicIpAddress = []
316+
317+
try {
318+
const listPublicIpAddress = await this.fetchListPublicIpAddress()
319+
listPublicIpAddress.forEach(item => {
320+
if (item.state === 'Free') {
321+
this.listPublicIpAddress.push({
322+
ipaddress: item.ipaddress
323+
})
324+
}
325+
})
326+
this.listPublicIpAddress.sort(function (a, b) {
327+
if (a.ipaddress < b.ipaddress) { return -1 }
328+
if (a.ipaddress > b.ipaddress) { return 1 }
329+
return 0
330+
})
331+
this.acquireIp = this.listPublicIpAddress && this.listPublicIpAddress.length > 0 ? this.listPublicIpAddress[0].ipaddress : null
332+
this.acquireLoading = false
333+
} catch (e) {
334+
this.acquireLoading = false
335+
this.$notifyError(e)
336+
}
337+
},
338+
onCloseModal () {
339+
this.showAcquireIp = false
258340
}
259341
}
260342
}

0 commit comments

Comments
 (0)