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 0b4122b network: Add support for tiers in PF, LB rules for a VPC
(#379)
0b4122b is described below
commit 0b4122bd3122b8197c7a910d8c8d9c2a896f7d45
Author: Hoang Nguyen <[email protected]>
AuthorDate: Wed Jun 24 14:54:25 2020 +0700
network: Add support for tiers in PF, LB rules for a VPC (#379)
Fixes #333
Fixes #438
Signed-off-by: Rohit Yadav <[email protected]>
Co-authored-by: Rohit Yadav <[email protected]>
---
src/components/view/ResourceView.vue | 19 ++-
src/views/network/EnableStaticNat.vue | 6 +-
src/views/network/LoadBalancing.vue | 242 +++++++++++++++++++++++++---------
src/views/network/PortForwarding.vue | 235 +++++++++++++++++++++++++--------
4 files changed, 375 insertions(+), 127 deletions(-)
diff --git a/src/components/view/ResourceView.vue
b/src/components/view/ResourceView.vue
index f3f79e2..c7035a9 100644
--- a/src/components/view/ResourceView.vue
+++ b/src/components/view/ResourceView.vue
@@ -43,7 +43,7 @@
v-for="tab in tabs"
:tab="$t('label.' + tab.name)"
:key="tab.name"
- v-if="showHideTab(tab)">
+ v-if="showTab(tab)">
<component :is="tab.component" :resource="resource"
:loading="loading" :tab="activeTab" />
</a-tab-pane>
</a-tabs>
@@ -97,8 +97,12 @@ export default {
if (newItem.id === oldItem.id) return
if (this.resource.associatednetworkid) {
- api('listNetworks', { id: this.resource.associatednetworkid
}).then(response => {
- this.networkService = response.listnetworksresponse.network[0]
+ api('listNetworks', { id: this.resource.associatednetworkid, listall:
true }).then(response => {
+ if (response && response.listnetworksresponse &&
response.listnetworksresponse.network) {
+ this.networkService = response.listnetworksresponse.network[0]
+ } else {
+ this.networkService = {}
+ }
})
}
}
@@ -107,12 +111,15 @@ export default {
onTabChange (key) {
this.activeTab = key
},
- showHideTab (tab) {
+ showTab (tab) {
if ('networkServiceFilter' in tab) {
- if (this.resource.virtualmachineid && tab.name !== 'Firewall') {
+ if (this.resource && this.resource.virtualmachineid &&
!this.resource.vpcid && tab.name !== 'firewall') {
return false
}
- if (this.resource && this.resource.vpcid && tab.name !== 'Firewall') {
+ if (this.resource && this.resource.virtualmachineid &&
this.resource.vpcid) {
+ return false
+ }
+ if (this.resource && this.resource.vpcid && tab.name !== 'firewall') {
return true
}
return this.networkService && this.networkService.service &&
diff --git a/src/views/network/EnableStaticNat.vue
b/src/views/network/EnableStaticNat.vue
index 3a7c35f..c9e22b0 100644
--- a/src/views/network/EnableStaticNat.vue
+++ b/src/views/network/EnableStaticNat.vue
@@ -172,7 +172,7 @@ export default {
domainid: this.resource.domainid,
keyword: this.searchQuery
}).then(response => {
- this.vmsList = response.listvirtualmachinesresponse.virtualmachine
+ this.vmsList = response.listvirtualmachinesresponse.virtualmachine ||
[]
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
@@ -204,9 +204,9 @@ export default {
this.loading = true
api('listNics', {
virtualmachineid: this.selectedVm,
- networkid: this.resource.associatednetworkid
+ networkid: this.resource.associatednetworkid || this.selectedVpcTier
}).then(response => {
- this.nicsList = response.listnicsresponse.nic
+ this.nicsList = response.listnicsresponse.nic || []
let secondaryIps = this.nicsList.map(item => item.secondaryip)
diff --git a/src/views/network/LoadBalancing.vue
b/src/views/network/LoadBalancing.vue
index b258676..638da12 100644
--- a/src/views/network/LoadBalancing.vue
+++ b/src/views/network/LoadBalancing.vue
@@ -18,6 +18,21 @@
<template>
<div>
<div>
+ <div class="filter" v-if="'vpcid' in resource && !('associatednetworkid'
in resource)">
+ <div class="form">
+ <div class="form__item" ref="newRuleTier">
+ <div class="form__label">{{ $t('label.tiername') }}</div>
+ <a-select v-model="newRule.tier">
+ <a-select-option
+ v-for="tier in tiers.data"
+ :loading="tiers.loading"
+ :key="tier.id">
+ {{ tier.displaytext }}
+ </a-select-option>
+ </a-select>
+ </div>
+ </div>
+ </div>
<div class="form">
<div class="form__item" ref="newRuleName">
<div class="form__label"><span class="form__required">*</span>{{
$t('label.name') }}</div>
@@ -63,7 +78,7 @@
<a-table
size="small"
- style="overflow-y: auto"
+ class="list-view"
:loading="loading"
:columns="columns"
:dataSource="lbRules"
@@ -278,47 +293,58 @@
{disabled: newRule.virtualmachineid === [] } }"
@cancel="closeModal"
>
+ <div>
+ <a-input-search
+ class="input-search"
+ placeholder="Search"
+ v-model="searchQuery"
+ allowClear
+ @search="onSearch" />
+ <a-table
+ size="small"
+ class="list-view"
+ :loading="addVmModalLoading"
+ :columns="vmColumns"
+ :dataSource="vms"
+ :pagination="false"
+ :rowKey="record => record.id"
+ :scroll="{ y: 300 }">
+ <div slot="name" slot-scope="text, record, index">
+ <span>
+ {{ text }}
+ </span>
+ <a-icon v-if="addVmModalNicLoading" type="loading"></a-icon>
+ <a-select
+ style="display: block"
+ v-else-if="!addVmModalNicLoading &&
newRule.virtualmachineid[index] === record.id"
+ mode="multiple"
+ v-model="newRule.vmguestip[index]"
+ >
+ <a-select-option v-for="(nic, nicIndex) in nics[index]"
:key="nic" :value="nic">
+ {{ nic }}{{ nicIndex === 0 ? ' (Primary)' : null }}
+ </a-select-option>
+ </a-select>
+ </div>
- <a-icon v-if="addVmModalLoading" type="loading"></a-icon>
-
- <div v-else>
- <div class="vm-modal__header">
- <span style="min-width: 200px;">{{ $t('label.name') }}</span>
- <span>{{ $t('label.instancename') }}</span>
- <span>{{ $t('label.displayname') }}</span>
- <span>{{ $t('label.ip') }}</span>
- <span>{{ $t('label.account') }}</span>
- <span>{{ $t('label.zonenamelabel') }}</span>
- <span>{{ $t('label.state') }}</span>
- <span>{{ $t('label.select') }}</span>
- </div>
+ <div slot="state" slot-scope="text">
+ <status :text="text ? text : ''" displayText></status>
+ </div>
- <a-checkbox-group style="width: 100%;">
- <div v-for="(vm, index) in vms" :key="index" class="vm-modal__item">
- <span style="min-width: 200px;">
- <span>
- {{ vm.name }}
- </span>
- <a-icon v-if="addVmModalNicLoading" type="loading"></a-icon>
- <a-select
- v-else-if="!addVmModalNicLoading &&
newRule.virtualmachineid[index] === vm.id"
- mode="multiple"
- v-model="newRule.vmguestip[index]"
- >
- <a-select-option v-for="(nic, nicIndex) in nics[index]"
:key="nic" :value="nic">
- {{ nic }}{{ nicIndex === 0 ? ' (Primary)' : null }}
- </a-select-option>
- </a-select>
- </span>
- <span>{{ vm.instancename }}</span>
- <span>{{ vm.displayname }}</span>
- <span></span>
- <span>{{ vm.account }}</span>
- <span>{{ vm.zonename }}</span>
- <span>{{ vm.state }}</span>
- <a-checkbox :value="vm.id" @change="e => fetchNics(e, index)" />
+ <div slot="action" slot-scope="text, record, index"
style="text-align: center">
+ <a-checkbox :value="record.id" @change="e => fetchNics(e, index)"
/>
</div>
- </a-checkbox-group>
+ </a-table>
+ <a-pagination
+ class="pagination"
+ size="small"
+ :current="vmPage"
+ :pageSize="vmPageSize"
+ :total="vmCount"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="handleChangePage"
+ @showSizeChange="handleChangePageSize"
+ showSizeChanger/>
</div>
</a-modal>
@@ -423,7 +449,46 @@ export default {
title: this.$t('label.action'),
scopedSlots: { customRender: 'actions' }
}
- ]
+ ],
+ tiers: {
+ loading: false,
+ data: []
+ },
+ vmColumns: [
+ {
+ title: this.$t('label.name'),
+ dataIndex: 'name',
+ scopedSlots: { customRender: 'name' },
+ width: 220
+ },
+ {
+ title: this.$t('label.state'),
+ dataIndex: 'state',
+ scopedSlots: { customRender: 'state' }
+ },
+ {
+ title: this.$t('label.displayname'),
+ dataIndex: 'displayname'
+ },
+ {
+ title: this.$t('label.account'),
+ dataIndex: 'account'
+ },
+ {
+ title: this.$t('label.zonename'),
+ dataIndex: 'zonename'
+ },
+ {
+ title: this.$t('label.select'),
+ dataIndex: 'action',
+ scopedSlots: { customRender: 'action' },
+ width: 80
+ }
+ ],
+ vmPage: 1,
+ vmPageSize: 10,
+ vmCount: 0,
+ searchQuery: null
}
},
mounted () {
@@ -446,9 +511,30 @@ export default {
},
methods: {
fetchData () {
+ this.fetchListTiers()
+ this.fetchLBRules()
+ },
+ fetchListTiers () {
+ this.tiers.loading = true
+
+ api('listNetworks', {
+ account: this.resource.account,
+ domainid: this.resource.domainid,
+ supportedservices: 'Lb',
+ vpcid: this.resource.vpcid
+ }).then(json => {
+ this.tiers.data = json.listnetworksresponse.network || []
+ this.newRule.tier = this.tiers.data && this.tiers.data[0].id ?
this.tiers.data[0].id : null
+ this.$forceUpdate()
+ }).catch(error => {
+ this.$notifyError(error)
+ }).finally(() => { this.tiers.loading = false })
+ },
+ fetchLBRules () {
this.loading = true
this.lbRules = []
this.stickinessPolicies = []
+
api('listLoadBalancerRules', {
listAll: true,
publicipid: this.resource.id,
@@ -882,26 +968,7 @@ export default {
if (!this.newRule.name || !this.newRule.publicport ||
!this.newRule.privateport) return
}
this.addVmModalVisible = true
- this.addVmModalLoading = true
- api('listVirtualMachines', {
- listAll: true,
- page: 1,
- pagesize: 500,
- networkid: this.resource.associatednetworkid,
- account: this.resource.account,
- domainid: this.resource.domainid
- }).then(response => {
- this.vms = response.listvirtualmachinesresponse.virtualmachine
- this.vms.forEach((vm, index) => {
- this.newRule.virtualmachineid[index] = null
- this.nics[index] = null
- this.newRule.vmguestip[index] = null
- })
- this.addVmModalLoading = false
- }).catch(error => {
- this.$notifyError(error)
- this.closeModal()
- })
+ this.fetchVirtualMachines()
},
fetchNics (e, index) {
if (!e.target.checked) {
@@ -917,7 +984,7 @@ export default {
virtualmachineid: e.target.value,
networkid: this.resource.associatednetworkid
}).then(response => {
- if (!response.listnicsresponse.nic[0]) return
+ if (!response || !response.listnicsresponse ||
!response.listnicsresponse.nic[0]) return
const newItem = []
newItem.push(response.listnicsresponse.nic[0].ipaddress)
if (response.listnicsresponse.nic[0].secondaryip) {
@@ -931,6 +998,33 @@ export default {
this.closeModal()
})
},
+ fetchVirtualMachines () {
+ this.vmCount = 0
+ this.vms = []
+ this.addVmModalLoading = true
+ const networkId = ('vpcid' in this.resource && !('associatednetworkid'
in this.resource)) ? this.newRule.tier : this.resource.associatednetworkid
+ api('listVirtualMachines', {
+ listAll: true,
+ keyword: this.searchQuery,
+ page: this.vmPage,
+ pagesize: this.vmPageSize,
+ networkid: networkId,
+ account: this.resource.account,
+ domainid: this.resource.domainid
+ }).then(response => {
+ this.vmCount = response.listvirtualmachinesresponse.count || 0
+ this.vms = response.listvirtualmachinesresponse.virtualmachine || []
+ this.vms.forEach((vm, index) => {
+ this.newRule.virtualmachineid[index] = null
+ this.nics[index] = null
+ this.newRule.vmguestip[index] = null
+ })
+ }).catch(error => {
+ this.$notifyError(error)
+ }).finally(() => {
+ this.addVmModalLoading = false
+ })
+ },
handleAssignToLBRule (data) {
const vmIDIpMap = {}
@@ -991,9 +1085,10 @@ export default {
return
}
+ const networkId = ('vpcid' in this.resource && !('associatednetworkid'
in this.resource)) ? this.newRule.tier : this.resource.associatednetworkid
api('createLoadBalancerRule', {
openfirewall: false,
- networkid: this.resource.associatednetworkid,
+ networkid: networkId,
publicipid: this.resource.id,
algorithm: this.newRule.algorithm,
name: this.newRule.name,
@@ -1040,6 +1135,10 @@ export default {
this.page = currentPage
this.pageSize = pageSize
this.fetchData()
+ },
+ onSearch (value) {
+ this.searchQuery = value
+ this.fetchVirtualMachines()
}
}
}
@@ -1372,6 +1471,7 @@ export default {
.pagination {
margin-top: 20px;
+ text-align: right;
}
.actions {
@@ -1381,4 +1481,22 @@ export default {
}
}
}
+
+ .list-view {
+ overflow-y: auto;
+ display: block;
+ width: 100%;
+ }
+
+ .filter {
+ display: block;
+ width: 240px;
+ margin-bottom: 10px;
+ }
+
+ .input-search {
+ margin-bottom: 10px;
+ width: 220px;
+ float: right;
+ }
</style>
diff --git a/src/views/network/PortForwarding.vue
b/src/views/network/PortForwarding.vue
index f5bc4ac..dabf6e3 100644
--- a/src/views/network/PortForwarding.vue
+++ b/src/views/network/PortForwarding.vue
@@ -18,6 +18,21 @@
<template>
<div>
<div>
+ <div class="filter" v-if="'vpcid' in resource && !('associatednetworkid'
in resource)">
+ <div class="form">
+ <div class="form__item" ref="newRuleTier">
+ <div class="form__label">{{ $t('label.tiername') }}</div>
+ <a-select v-model="newRule.tier">
+ <a-select-option
+ v-for="tier in tiers.data"
+ :loading="tiers.loading"
+ :key="tier.id">
+ {{ tier.displaytext }}
+ </a-select-option>
+ </a-select>
+ </div>
+ </div>
+ </div>
<div class="form">
<div class="form__item">
<div class="form__label">{{ $t('label.privateport') }}</div>
@@ -159,57 +174,70 @@
{disabled: newRule.virtualmachineid === null } }"
@cancel="closeModal"
>
+ <div>
+ <a-input-search
+ class="input-search"
+ placeholder="Search"
+ v-model="searchQuery"
+ allowClear
+ @search="onSearch" />
+ <a-table
+ size="small"
+ class="list-view"
+ :loading="addVmModalLoading"
+ :columns="vmColumns"
+ :dataSource="vms"
+ :pagination="false"
+ :rowKey="record => record.id"
+ :scroll="{ y: 300 }">
+ <div slot="name" slot-scope="text, record">
+ <span>
+ {{ text }}
+ </span>
+ <a-icon v-if="addVmModalNicLoading" type="loading"></a-icon>
+ <a-select
+ style="display: block"
+ v-else-if="!addVmModalNicLoading && newRule.virtualmachineid ===
record.id"
+ v-model="newRule.vmguestip"
+ >
+ <a-select-option v-for="(nic, nicIndex) in nics" :key="nic"
:value="nic">
+ {{ nic }}{{ nicIndex === 0 ? ' (Primary)' : null }}
+ </a-select-option>
+ </a-select>
+ </div>
- <a-icon v-if="addVmModalLoading" type="loading"></a-icon>
-
- <div v-else>
- <div class="vm-modal__header">
- <span style="min-width: 200px;">{{ $t('label.name') }}</span>
- <span>{{ $t('label.instancename') }}</span>
- <span>{{ $t('label.displayname') }}</span>
- <span>{{ $t('label.ip') }}</span>
- <span>{{ $t('label.account') }}</span>
- <span>{{ $t('label.zone') }}</span>
- <span>{{ $t('label.state') }}</span>
- <span>{{ $t('label.select') }}</span>
- </div>
+ <div slot="state" slot-scope="text">
+ <status :text="text ? text : ''" displayText></status>
+ </div>
- <a-radio-group v-model="newRule.virtualmachineid" style="width: 100%;"
@change="fetchNics">
- <div v-for="(vm, index) in vms" :key="index" class="vm-modal__item">
-
- <span style="min-width: 200px;">
- <span>
- {{ vm.name }}
- </span>
- <a-icon v-if="addVmModalNicLoading" type="loading"></a-icon>
- <a-select
- v-else-if="!addVmModalNicLoading && newRule.virtualmachineid
=== vm.id"
- v-model="newRule.vmguestip">
- <a-select-option v-for="(nic, nicIndex) in nics" :key="nic"
:value="nic">
- {{ nic }}{{ nicIndex === 0 ? ' (Primary)' : null }}
- </a-select-option>
- </a-select>
- </span>
- <span>{{ vm.instancename }}</span>
- <span>{{ vm.displayname }}</span>
- <span></span>
- <span>{{ vm.account }}</span>
- <span>{{ vm.zonename }}</span>
- <span>{{ vm.state }}</span>
- <a-radio :value="vm.id" />
+ <div slot="action" slot-scope="text, record" style="text-align:
center">
+ <a-radio :value="record.id" @change="e => fetchNics(e)" />
</div>
- </a-radio-group>
+ </a-table>
+ <a-pagination
+ class="pagination"
+ size="small"
+ :current="vmPage"
+ :pageSize="vmPageSize"
+ :total="vmCount"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="handleChangePage"
+ @showSizeChange="handleChangePageSize"
+ showSizeChanger/>
</div>
-
</a-modal>
-
</div>
</template>
<script>
import { api } from '@/api'
+import Status from '@/components/widgets/Status'
export default {
+ components: {
+ Status
+ },
props: {
resource: {
type: Object,
@@ -272,7 +300,51 @@ export default {
title: this.$t('label.action'),
scopedSlots: { customRender: 'actions' }
}
- ]
+ ],
+ tiers: {
+ loading: false,
+ data: []
+ },
+ vmColumns: [
+ {
+ title: this.$t('label.name'),
+ dataIndex: 'name',
+ scopedSlots: { customRender: 'name' },
+ width: 210
+ },
+ {
+ title: this.$t('label.state'),
+ dataIndex: 'state',
+ scopedSlots: { customRender: 'state' }
+ },
+ {
+ title: this.$t('label.displayname'),
+ dataIndex: 'displayname'
+ },
+ {
+ title: this.$t('label.ip'),
+ dataIndex: 'ip',
+ width: 100
+ },
+ {
+ title: this.$t('label.account'),
+ dataIndex: 'account'
+ },
+ {
+ title: this.$t('label.zone'),
+ dataIndex: 'zonename'
+ },
+ {
+ title: this.$t('label.select'),
+ dataIndex: 'action',
+ scopedSlots: { customRender: 'action' },
+ width: 80
+ }
+ ],
+ vmPage: 1,
+ vmPageSize: 10,
+ vmCount: 0,
+ searchQuery: null
}
},
mounted () {
@@ -295,6 +367,28 @@ export default {
},
methods: {
fetchData () {
+ this.fetchListTiers()
+ this.fetchPFRules()
+ },
+ fetchListTiers () {
+ if ('vpcid' in this.resource && 'associatednetworkid' in this.resource) {
+ return
+ }
+ this.tiers.loading = true
+ api('listNetworks', {
+ account: this.resource.account,
+ domainid: this.resource.domainid,
+ supportedservices: 'PortForwarding',
+ vpcid: this.resource.vpcid
+ }).then(json => {
+ this.tiers.data = json.listnetworksresponse.network || []
+ this.newRule.tier = this.tiers.data && this.tiers.data[0].id ?
this.tiers.data[0].id : null
+ this.$forceUpdate()
+ }).catch(error => {
+ this.$notifyError(error)
+ }).finally(() => { this.tiers.loading = false })
+ },
+ fetchPFRules () {
this.loading = true
api('listPortForwardingRules', {
listAll: true,
@@ -331,10 +425,11 @@ export default {
addRule () {
this.loading = true
this.addVmModalVisible = false
+ const networkId = ('vpcid' in this.resource && !('associatednetworkid'
in this.resource)) ? this.newRule.tier : this.resource.associatednetworkid
api('createPortForwardingRule', {
...this.newRule,
ipaddressid: this.resource.id,
- networkid: this.resource.associatednetworkid
+ networkid: networkId
}).then(response => {
this.$pollJob({
jobId: response.createportforwardingruleresponse.jobid,
@@ -476,24 +571,11 @@ export default {
},
openAddVMModal () {
this.addVmModalVisible = true
- this.addVmModalLoading = true
- api('listVirtualMachines', {
- listAll: true,
- page: 1,
- pagesize: 500,
- networkid: this.resource.associatednetworkid,
- account: this.resource.account,
- domainid: this.resource.domainid
- }).then(response => {
- this.vms = response.listvirtualmachinesresponse.virtualmachine
- this.addVmModalLoading = false
- }).catch(error => {
- this.$notifyError(error)
- this.closeModal()
- })
+ this.fetchVirtualMachines()
},
fetchNics (e) {
this.addVmModalNicLoading = true
+ this.newRule.virtualmachineid = e.target.value
api('listNics', {
virtualmachineid: e.target.value,
networkid: this.resource.associatednetworkid
@@ -512,6 +594,27 @@ export default {
this.closeModal()
})
},
+ fetchVirtualMachines () {
+ this.vmCount = 0
+ this.vms = []
+ this.addVmModalLoading = true
+ const networkId = ('vpcid' in this.resource && !('associatednetworkid'
in this.resource)) ? this.newRule.tier : this.resource.associatednetworkid
+ api('listVirtualMachines', {
+ listAll: true,
+ keyword: this.searchQuery,
+ page: this.vmPage,
+ pagesize: this.vmPageSize,
+ networkid: networkId,
+ account: this.resource.account,
+ domainid: this.resource.domainid
+ }).then(response => {
+ this.vmCount = response.listvirtualmachinesresponse.count || 0
+ this.vms = response.listvirtualmachinesresponse.virtualmachine
+ this.addVmModalLoading = false
+ }).catch(error => {
+ this.$notifyError(error)
+ })
+ },
handleChangePage (page, pageSize) {
this.page = page
this.pageSize = pageSize
@@ -521,6 +624,10 @@ export default {
this.page = currentPage
this.pageSize = pageSize
this.fetchData()
+ },
+ onSearch (value) {
+ this.searchQuery = value
+ this.fetchVirtualMachines()
}
}
}
@@ -707,6 +814,22 @@ export default {
.pagination {
margin-top: 20px;
+ text-align: right;
}
+ .list-view {
+ overflow-y: auto;
+ display: block;
+ width: 100%;
+ }
+
+ .filter {
+ display: block;
+ width: 240px;
+ margin-bottom: 10px;
+
+ .form__item {
+ width: 100%;
+ }
+ }
</style>