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 ebd0cef vpc: consolidated tabs for configuration and management (#143)
ebd0cef is described below
commit ebd0cef416de16e510c7a244804280dfaaa9e66d
Author: Ritchie Vincent <[email protected]>
AuthorDate: Wed Feb 5 11:04:07 2020 +0000
vpc: consolidated tabs for configuration and management (#143)
Adds VPC consolidated component that has tabs for may related items.
Co-authored-by: Rohit Yadav <[email protected]>
Signed-off-by: Rohit Yadav <[email protected]>
---
src/components/view/ResourceView.vue | 7 +
src/config/section/network.js | 34 +-
src/locales/en.json | 4 +
src/views/network/VpcRouterTab.vue | 98 ----
src/views/network/VpcTab.vue | 939 +++++++++++++++++++++++++++++++++++
src/views/network/VpcTiersTab.vue | 42 +-
6 files changed, 980 insertions(+), 144 deletions(-)
diff --git a/src/components/view/ResourceView.vue
b/src/components/view/ResourceView.vue
index 2dc572e..cf2ba07 100644
--- a/src/components/view/ResourceView.vue
+++ b/src/components/view/ResourceView.vue
@@ -27,7 +27,14 @@
class="spin-content"
:bordered="true"
style="width:100%">
+ <component
+ v-if="tabs.length === 1"
+ :is="tabs[0].component"
+ :resource="resource"
+ :loading="loading"
+ :tab="tabs[0].name" />
<a-tabs
+ v-else
style="width: 100%"
:animated="false"
:defaultActiveKey="tabs[0].name"
diff --git a/src/config/section/network.js b/src/config/section/network.js
index 3e13fd6..c3f7ab8 100644
--- a/src/config/section/network.js
+++ b/src/config/section/network.js
@@ -119,43 +119,13 @@ export default {
columns: ['name', 'state', 'displaytext', 'cidr', 'account', 'zonename'],
details: ['name', 'id', 'displaytext', 'cidr', 'networkdomain',
'ispersistent', 'redundantvpcrouter', 'restartrequired', 'zonename', 'account',
'domain'],
related: [{
- name: 'privategw',
- title: 'Private Gateways',
- param: 'vpcid'
- }, {
- name: 'publicip',
- title: 'Public IP Addresses',
- param: 'vpcid'
- }, {
- name: 's2svpn',
- title: 'Site-to-Site VPN Gateways',
- param: 'vpcid'
- }, {
- name: 's2svpnconn',
- title: 'Site-to-Site VPN Connections',
- param: 'vpcid'
- }, {
- name: 'acllist',
- title: 'Network ACL Lists',
- param: 'vpcid'
- }, {
- name: 'guestnetwork',
- title: 'Networks',
- param: 'vpcid'
- }, {
name: 'vm',
title: 'Instances',
param: 'vpcid'
}],
tabs: [{
- name: 'details',
- component: () => import('@/components/view/DetailsTab.vue')
- }, {
- name: 'Router',
- component: () => import('@/views/network/VpcRouterTab.vue')
- }, {
- name: 'Network',
- component: () => import('@/views/network/VpcTiersTab.vue')
+ name: 'VPC',
+ component: () => import('@/views/network/VpcTab.vue')
}],
actions: [
{
diff --git a/src/locales/en.json b/src/locales/en.json
index 6125c41..73c7bc0 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -458,8 +458,10 @@
"label.add.l2.guest.network": "Add L2 Guest Network",
"label.add.ldap.account": "Add LDAP account",
"label.add.ldap.list.users": "List LDAP users",
+"label.add.list.name":"ACL List Name",
"label.add.netScaler.device": "Add Netscaler device",
"label.add.network.offering": "Add network offering",
+"label.add.new.gateway": "Add new gateway",
"label.add.new.tier": "Add new tier",
"label.add.nfs.secondary.staging.store": "Add NFS Secondary Staging Store",
"label.add.pod": "Add Pod",
@@ -635,6 +637,7 @@
"label.revoke.project.invite": "Revoke invitation",
"label.secondary.storage":"Secondary Storage",
"label.secondary.storage.vm":"Secondary storage VM",
+"label.service.offering":"Service Offering",
"label.set.default.NIC": "Set default NIC",
"label.shutdown.provider": "Shutdown provider",
"label.snapshot.schedule": "Set up Recurring Snapshot",
@@ -708,6 +711,7 @@
"memoryusedgb": "Used",
"memused": "Memory Usage",
"message.edit.account": "Edit (\"-1\" indicates no limit to the amount of
resources create)",
+"message.add.new.gateway.to.vpc":"Please specify the information to add a new
gateway to this VPC.",
"message.assign.instance.another": "Please specify the account type, domain,
account name and network (optional) of the new account. <br> If the default nic
of the vm is on a shared network, CloudStack will check if the network can be
used by the new account if you do not specify one network. <br> If the default
nic of the vm is on a isolated network, and the new account has more one
isolated networks, you should specify one.",
"message.network.addVM.desc":"Please specify the network that you would like
to add this VM to. A new NIC will be added for this network.",
"message.network.removeNIC": "Please confirm that want to remove this NIC,
which will also remove the associated network from the VM.",
diff --git a/src/views/network/VpcRouterTab.vue
b/src/views/network/VpcRouterTab.vue
deleted file mode 100644
index dde958f..0000000
--- a/src/views/network/VpcRouterTab.vue
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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>
- <a-spin :spinning="fetchLoading">
- <a-tabs :animated="false" tabPosition="left">
- <a-tab-pane tab="Private Gateways" key="pgw" v-if="'listPrivateGateways'
in $store.getters.apis">
- <a-button type="dashed" icon="plus" style="width: 100%">Add Private
Gateway</a-button>
- </a-tab-pane>
- <a-tab-pane tab="Public IP Addresses" key="ip"
v-if="'listPublicIpAddresses' in $store.getters.apis">
- <a-button type="dashed" icon="plus" style="width: 100%">Acquire New
IP</a-button>
- </a-tab-pane>
- <a-tab-pane tab="S2S VPN Gateway" key="vpngw" v-if="'listVpnGateways' in
$store.getters.apis">
- <a-button type="dashed" icon="plus" style="width: 100%">Create
Site-to-Site VPN Gateway</a-button>
- </a-tab-pane>
- <a-tab-pane tab="S2S VPN Connection" key="vpnc"
v-if="'listVpnConnections' in $store.getters.apis">
- <a-button type="dashed" icon="plus" style="width: 100%">Create
Site-to-Site VPN Connection</a-button>
- </a-tab-pane>
- <a-tab-pane tab="Network ACL Lists" key="acl"
v-if="'listNetworkACLLists' in $store.getters.apis">
- <a-button type="dashed" icon="plus" style="width: 100%">Add Network
ACL List</a-button>
- </a-tab-pane>
- <a-tab-pane tab="Virtual Routers" key="vr" v-if="'listRouters' in
$store.getters.apis">
- {{ routers }}
- </a-tab-pane>
- </a-tabs>
- </a-spin>
-</template>
-
-<script>
-import { api } from '@/api'
-import Status from '@/components/widgets/Status'
-
-export default {
- name: 'VpcRouterTab',
- components: {
- Status
- },
- props: {
- resource: {
- type: Object,
- required: true
- },
- loading: {
- type: Boolean,
- default: false
- }
- },
- data () {
- return {
- routers: [],
- fetchLoading: false
- }
- },
- mounted () {
- this.fetchData()
- },
- watch: {
- loading (newData, oldData) {
- if (!newData && this.resource.id) {
- this.fetchData()
- }
- }
- },
- methods: {
- fetchData () {
- this.fetchLoading = true
- api('listRouters', { vpcid: this.resource.id, listAll: true }).then(json
=> {
- this.routers = json.listroutersresponse.router
- }).catch(error => {
- this.$notification.error({
- message: 'Request Failed',
- description: error.response.headers['x-description']
- })
- }).finally(() => {
- this.fetchLoading = false
- })
- }
- }
-}
-</script>
-
-<style lang="less" scoped>
-
-</style>
diff --git a/src/views/network/VpcTab.vue b/src/views/network/VpcTab.vue
new file mode 100644
index 0000000..02da039
--- /dev/null
+++ b/src/views/network/VpcTab.vue
@@ -0,0 +1,939 @@
+// 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>
+ <a-spin :spinning="fetchLoading">
+ <a-tabs
+ :activeKey="currentTab"
+ :tabPosition="device === 'tablet' || device === 'mobile' ? 'top' :
'left'"
+ :animated="false"
+ @change="handleChangeTab">
+ <a-tab-pane :tab="$t('details')" key="details">
+ <DetailsTab :resource="resource" :loading="loading" />
+ </a-tab-pane>
+ <a-tab-pane :tab="$t('networks')" key="tier">
+ <VpcTiersTab :resource="resource" :loading="loading" />
+ </a-tab-pane>
+ <a-tab-pane tab="Private Gateways" key="pgw" v-if="'listPrivateGateways'
in $store.getters.apis">
+ <a-button
+ type="dashed"
+ icon="plus"
+ style="width: 100%"
+ @click="() => handleOpenModals('privateGateways')">Add Private
Gateway</a-button>
+ <a-table
+ class="table"
+ size="small"
+ :columns="privateGatewaysColumns"
+ :dataSource="privateGateways"
+ :rowKey="item => item.id"
+ :pagination="false"
+ >
+ <template slot="ipaddress" slot-scope="text, item">
+ <router-link :to="{ path: '/privategw/' + item.id }">{{ text
}}</router-link>
+ </template>
+ <template slot="state" slot-scope="text, item">
+ <status :text="item.state" displayText></status>
+ </template>
+ </a-table>
+ <a-pagination
+ class="row-element pagination"
+ size="small"
+ :current="page"
+ :pageSize="pageSize"
+ :total="itemCounts.privateGateways"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="changePage"
+ @showSizeChange="changePageSize"
+ showSizeChanger/>
+
+ <a-modal v-model="modals.gateway" :title="$t('label.add.new.gateway')"
@ok="handleGatewayFormSubmit">
+ <a-spin :spinning="modals.gatewayLoading">
+ <p>{{ $t('message.add.new.gateway.to.vpc') }}</p>
+ <a-form @submit.prevent="handleGatewayFormSubmit"
:form="gatewayForm">
+ <a-form-item :label="$t('physicalnetworkid')">
+ <a-select v-decorator="['physicalnetwork']">
+ <a-select-option v-for="item in physicalnetworks"
:key="item.id" :value="item.id">
+ {{ item.name }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
+ <a-form-item :label="$t('label.vlan')" :required="true">
+ <a-input
+ :placeholder="placeholders.vlan"
+ v-decorator="['vlan', {rules: [{ required: true, message:
'Required' }]}]"
+ ></a-input>
+ </a-form-item>
+ <a-form-item :label="$t('publicip')" :required="true">
+ <a-input
+ :placeholder="placeholders.ipaddress"
+ v-decorator="['ipaddress', {rules: [{ required: true,
message: 'Required' }]}]"
+ ></a-input>
+ </a-form-item>
+ <a-form-item :label="$t('gateway')" :required="true">
+ <a-input
+ :placeholder="placeholders.gateway"
+ v-decorator="['gateway', {rules: [{ required: true, message:
'Required' }]}]"
+ ></a-input>
+ </a-form-item>
+ <a-form-item :label="$t('netmask')" :required="true">
+ <a-input
+ :placeholder="placeholders.netmask"
+ v-decorator="['netmask', {rules: [{ required: true, message:
'Required' }]}]"
+ ></a-input>
+ </a-form-item>
+ <a-form-item :label="$t('sourceNat')">
+ <a-checkbox v-decorator="['nat']"></a-checkbox>
+ </a-form-item>
+ <a-form-item :label="$t('aclid')">
+ <a-select v-decorator="['acl']">
+ <a-select-option v-for="item in networkAcls" :key="item.id"
:value="item.id">
+ {{ item.name }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
+ </a-form>
+ </a-spin>
+ </a-modal>
+ </a-tab-pane>
+ <a-tab-pane tab="Public IP Addresses" key="ip"
v-if="'listPublicIpAddresses' in $store.getters.apis">
+ <a-button type="dashed" icon="plus" style="width: 100%"
@click="handleAcquireNewIp">Acquire New IP</a-button>
+ <a-table
+ class="table"
+ size="small"
+ :columns="publicIpAddressesColumns"
+ :dataSource="publicIpAddresses"
+ :rowKey="item => item.id"
+ :pagination="false"
+ >
+ <template slot="ipaddress" slot-scope="text, item">
+ <router-link :to="{ path: '/publicip/' + item.id }">
+ {{ text }}
+ <a-tag v-if="item.issourcenat">source-nat</a-tag>
+ <a-tag v-if="item.isstaticnat">static-nat</a-tag>
+ </router-link>
+ </template>
+ <template slot="state" slot-scope="text, item">
+ <status :text="item.state" displayText></status>
+ </template>
+ <template slot="vm" slot-scope="text, item">
+ <router-link :to="{ path: '/vm/' + item.virtualmachineid }">
+ {{ item.virtualmachinedisplayname || item.virtualmachinename }}
+ </router-link>
+ </template>
+ <template slot="network" slot-scope="text, item">
+ <router-link :to="{ path: '/guestnetwork/' +
item.associatednetworkid }">
+ {{ item.associatednetworkname }}
+ </router-link>
+ </template>
+ </a-table>
+ <a-pagination
+ class="row-element pagination"
+ size="small"
+ :current="page"
+ :pageSize="pageSize"
+ :total="itemCounts.publicIpAddresses"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="changePage"
+ @showSizeChange="changePageSize"
+ showSizeChanger/>
+ </a-tab-pane>
+ <a-tab-pane tab="VPN Gateway" key="vpngw" v-if="'listVpnGateways' in
$store.getters.apis">
+ <a-button
+ v-if="vpnGateways.length === 0"
+ type="dashed"
+ icon="plus"
+ style="width: 100%"
+ @click="handleCreateVpnGateway">
+ Create Site-to-Site VPN Gateway
+ </a-button>
+ <a-list class="list">
+ <a-list-item v-for="item in vpnGateways" :key="item.id">
+ <div class="list__item">
+ <div class="list__col">
+ <div class="list__label">{{ $t('ip') }}</div>
+ <div>
+ <router-link :to="{ path: '/s2svpn/' + item.id }">
+ {{ item.publicip }}
+ </router-link>
+ </div>
+ </div>
+ </div>
+ </a-list-item>
+ </a-list>
+ </a-tab-pane>
+ <a-tab-pane tab="VPN Connections" key="vpnc" v-if="'listVpnConnections'
in $store.getters.apis">
+ <a-button
+ type="dashed"
+ icon="plus"
+ style="width: 100%"
+ @click="handleOpenModals('vpnConnection')">
+ Create Site-to-Site VPN Connection
+ </a-button>
+ <a-table
+ class="table"
+ size="small"
+ :columns="vpnConnectionsColumns"
+ :dataSource="vpnConnections"
+ :pagination="false"
+ :rowKey="record => record.id">
+ <a slot="publicip" slot-scope="text, record" href="javascript:;">
+ <router-link :to="{ path: '/s2svpnconn/' + record.id }">
+ {{ text }}
+ </router-link>
+ </a>
+ <template slot="state" slot-scope="text">
+ <status :text="text ? text : ''" displayText />
+ </template>
+ </a-table>
+ <a-pagination
+ class="row-element pagination"
+ size="small"
+ :current="page"
+ :pageSize="pageSize"
+ :total="itemCounts.vpnConnections"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="changePage"
+ @showSizeChange="changePageSize"
+ showSizeChanger/>
+ <a-modal v-model="modals.vpnConnection"
:title="$t('label.create.VPN.connection')" @ok="handleVpnConnectionFormSubmit">
+ <a-spin :spinning="modals.vpnConnectionLoading">
+ <a-form @submit.prevent="handleVpnConnectionFormSubmit"
:form="vpnConnectionForm">
+ <a-form-item :label="$t('vpncustomergatewayid')">
+ <a-select v-decorator="['vpncustomergateway']">
+ <a-select-option v-for="item in vpncustomergateways"
:key="item.id" :value="item.id">
+ {{ item.name }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
+ <a-form-item :label="$t('passive')">
+ <a-checkbox v-decorator="['passive']"></a-checkbox>
+ </a-form-item>
+ </a-form>
+ </a-spin>
+ </a-modal>
+ </a-tab-pane>
+ <a-tab-pane tab="Network ACL Lists" key="acl"
v-if="'listNetworkACLLists' in $store.getters.apis">
+ <a-button
+ type="dashed"
+ icon="plus"
+ style="width: 100%"
+ @click="() => handleOpenModals('networkAcl')">
+ Add Network ACL List
+ </a-button>
+ <a-table
+ class="table"
+ size="small"
+ :columns="networkAclsColumns"
+ :dataSource="networkAcls"
+ :rowKey="item => item.id"
+ :pagination="false"
+ >
+ <template slot="name" slot-scope="text, item">
+ <router-link :to="{ path: '/acllist/' + item.id }">
+ {{ text }}
+ </router-link>
+ </template>
+ </a-table>
+ <a-pagination
+ class="row-element pagination"
+ size="small"
+ :current="page"
+ :pageSize="pageSize"
+ :total="itemCounts.networkAcls"
+ :showTotal="total => `Total ${total} items`"
+ :pageSizeOptions="['10', '20', '40', '80', '100']"
+ @change="changePage"
+ @showSizeChange="changePageSize"
+ showSizeChanger/>
+ <a-modal
+ v-model="modals.networkAcl"
+ :title="$t('label.add.acl.list')"
+ @ok="handleNetworkAclFormSubmit">
+ <a-form @submit.prevent="handleNetworkAclFormSubmit"
:form="networkAclForm">
+ <a-form-item :label="$t('label.add.list.name')">
+ <a-input v-decorator="['name', {rules: [{ required: true,
message: 'Required' }]}]"></a-input>
+ </a-form-item>
+ <a-form-item :label="$t('description')">
+ <a-input v-decorator="['description', {rules: [{ required: true,
message: 'Required' }]}]"></a-input>
+ </a-form-item>
+ </a-form>
+ </a-modal>
+ </a-tab-pane>
+ <a-tab-pane tab="Virtual Routers" key="vr" v-if="'listRouters' in
$store.getters.apis">
+ <a-list>
+ <a-list-item v-for="item in routers" :key="item.id">
+ <div class="list__item">
+ <div class="list__row">
+ <div class="list__col">
+ <div class="list__label">{{ $t('name') }}</div>
+ <div>
+ <router-link :to="{ path: '/router/' + item.id }">
+ {{ item.name }}
+ </router-link>
+ </div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">{{ $t('state') }}</div>
+ <div><status :text="item.state" displayText></status></div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">{{ $t('publicip') }}</div>
+ <div>{{ item.publicip }}</div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">{{ $t('redundantrouter') }}</div>
+ <div>{{ item.isredundantrouter }}</div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">{{ $t('redundantstate') }}</div>
+ <div>{{ item.redundantstate }}</div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">{{ $t('hostname') }}</div>
+ <div>
+ <router-link :to="{ path: '/host/' + item.hostid }">
+ {{ item.hostname }}
+ </router-link>
+ </div>
+ </div>
+ </div>
+ </div>
+ </a-list-item>
+ </a-list>
+ </a-tab-pane>
+ </a-tabs>
+ </a-spin>
+</template>
+
+<script>
+import { api } from '@/api'
+import DetailsTab from '@/components/view/DetailsTab'
+import Status from '@/components/widgets/Status'
+import VpcTiersTab from './VpcTiersTab'
+import { mixinDevice } from '@/utils/mixin.js'
+
+export default {
+ name: 'VpcTab',
+ components: {
+ DetailsTab,
+ Status,
+ VpcTiersTab
+ },
+ mixins: [mixinDevice],
+ props: {
+ resource: {
+ type: Object,
+ required: true
+ },
+ loading: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data () {
+ return {
+ routers: [],
+ fetchLoading: false,
+ privateGateways: [],
+ publicIpAddresses: [],
+ vpnGateways: [],
+ vpnConnections: [],
+ networkAcls: [],
+ modals: {
+ gateway: false,
+ gatewayLoading: false,
+ vpnConnection: false,
+ vpnConnectionLoading: false,
+ networkAcl: false
+ },
+ placeholders: {
+ vlan: null,
+ ipaddress: null,
+ gateway: null,
+ netmask: null
+ },
+ physicalnetworks: [],
+ vpncustomergateways: [],
+ privateGatewaysColumns: [
+ {
+ title: this.$t('ip'),
+ dataIndex: 'ipaddress',
+ scopedSlots: { customRender: 'ipaddress' }
+ },
+ {
+ title: this.$t('state'),
+ dataIndex: 'state',
+ scopedSlots: { customRender: 'state' }
+ },
+ {
+ title: this.$t('gateway'),
+ dataIndex: 'gateway'
+ },
+ {
+ title: this.$t('netmask'),
+ dataIndex: 'netmask'
+ },
+ {
+ title: this.$t('vlan'),
+ dataIndex: 'vlan'
+ }
+ ],
+ vpnConnectionsColumns: [
+ {
+ title: this.$t('ip'),
+ dataIndex: 'publicip',
+ scopedSlots: { customRender: 'publicip' }
+ },
+ {
+ title: this.$t('state'),
+ dataIndex: 'state',
+ scopedSlots: { customRender: 'state' }
+ },
+ {
+ title: this.$t('gateway'),
+ dataIndex: 'gateway'
+ },
+ {
+ title: this.$t('ipsecpsk'),
+ dataIndex: 'ipsecpsk'
+ }
+ ],
+ publicIpAddressesColumns: [
+ {
+ title: this.$t('ip'),
+ dataIndex: 'ipaddress',
+ scopedSlots: { customRender: 'ipaddress' }
+ },
+ {
+ title: this.$t('state'),
+ dataIndex: 'state',
+ scopedSlots: { customRender: 'state' }
+ },
+ {
+ title: this.$t('vm'),
+ dataIndex: 'vm',
+ scopedSlots: { customRender: 'vm' }
+ },
+ {
+ title: this.$t('network'),
+ dataIndex: 'network',
+ scopedSlots: { customRender: 'network' }
+ }
+ ],
+ networkAclsColumns: [
+ {
+ title: this.$t('name'),
+ dataIndex: 'name',
+ scopedSlots: { customRender: 'name' }
+ },
+ {
+ title: this.$t('description'),
+ dataIndex: 'description'
+ }
+ ],
+ itemCounts: {
+ privateGateways: 0,
+ publicIpAddresses: 0,
+ vpnConnections: 0,
+ networkAcls: 0
+ },
+ page: 1,
+ pageSize: 10,
+ currentTab: 'details'
+ }
+ },
+ beforeCreate () {
+ this.gatewayForm = this.$form.createForm(this)
+ this.vpnConnectionForm = this.$form.createForm(this)
+ this.networkAclForm = this.$form.createForm(this)
+ },
+ mounted () {
+ this.handleFetchData()
+ },
+ watch: {
+ loading (newData, oldData) {
+ if (!newData && this.resource.id) {
+ this.handleFetchData()
+ }
+ }
+ },
+ methods: {
+ handleChangeTab (e) {
+ this.currentTab = e
+ this.page = 1
+ this.pageSize = 10
+ this.handleFetchData()
+ },
+ handleFetchData () {
+ switch (this.currentTab) {
+ case 'pgw':
+ this.fetchPrivateGateways()
+ break
+ case 'ip':
+ this.fetchPublicIpAddresses()
+ break
+ case 'vpngw':
+ this.fetchVpnGateways()
+ break
+ case 'vpnc':
+ this.fetchVpnConnections()
+ break
+ case 'acl':
+ this.fetchAclList()
+ break
+ case 'vr':
+ this.fetchRouters()
+ break
+ }
+ },
+ fetchRouters () {
+ this.fetchLoading = true
+ api('listRouters', { vpcid: this.resource.id, listAll: true }).then(json
=> {
+ this.routers = json.listroutersresponse.router
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ })
+ },
+ fetchPrivateGateways () {
+ this.fetchLoading = true
+ api('listPrivateGateways', {
+ vpcid: this.resource.id,
+ listAll: true,
+ page: this.page,
+ pagesize: this.pageSize
+ }).then(json => {
+ this.privateGateways = json.listprivategatewaysresponse.privategateway
+ this.itemCounts.privateGateways =
json.listprivategatewaysresponse.count
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ })
+ },
+ fetchPublicIpAddresses () {
+ this.fetchLoading = true
+ api('listPublicIpAddresses', {
+ vpcid: this.resource.id,
+ listAll: true,
+ page: this.page,
+ pagesize: this.pageSize,
+ forvirtualnetwork: true
+ }).then(json => {
+ this.publicIpAddresses =
json.listpublicipaddressesresponse.publicipaddress
+ this.itemCounts.publicIpAddresses =
json.listpublicipaddressesresponse.count
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ })
+ },
+ fetchVpnGateways () {
+ this.fetchLoading = true
+ api('listVpnGateways', {
+ vpcid: this.resource.id,
+ listAll: true
+ }).then(json => {
+ this.vpnGateways = json.listvpngatewaysresponse.vpngateway ?
json.listvpngatewaysresponse.vpngateway : []
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ })
+ },
+ fetchVpnConnections () {
+ this.fetchLoading = true
+ api('listVpnConnections', {
+ vpcid: this.resource.id,
+ listAll: true,
+ page: this.page,
+ pagesize: this.pageSize
+ }).then(json => {
+ this.vpnConnections = json.listvpnconnectionsresponse.vpnconnection
+ this.itemCounts.vpnConnections = json.listvpnconnectionsresponse.count
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ })
+ },
+ fetchAclList () {
+ this.fetchLoading = true
+ api('listNetworkACLLists', {
+ vpcid: this.resource.id,
+ listAll: true,
+ page: this.page,
+ pagesize: this.pageSize
+ }).then(json => {
+ this.networkAcls = json.listnetworkacllistsresponse.networkacllist
+ this.itemCounts.networkAcls = json.listnetworkacllistsresponse.count
+ if (this.modals.gateway === true) {
+ this.$nextTick(() => {
+ this.gatewayForm.setFieldsValue({ acl: this.networkAcls[0].id })
+ })
+ }
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ })
+ },
+ fetchPhysicalNetworks () {
+ this.modals.gatewayLoading = true
+ api('listPhysicalNetworks', { zoneid: this.resource.zoneid }).then(json
=> {
+ this.physicalnetworks =
json.listphysicalnetworksresponse.physicalnetwork
+ if (this.modals.gateway === true) {
+ this.$nextTick(() => {
+ this.gatewayForm.setFieldsValue({ physicalnetwork:
this.physicalnetworks[0].id })
+ })
+ }
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.modals.gatewayLoading = false
+ })
+ },
+ fetchVpnCustomerGateways () {
+ this.modals.vpnConnectionLoading = true
+ api('listVpnCustomerGateways', { listAll: true }).then(json => {
+ this.vpncustomergateways =
json.listvpncustomergatewaysresponse.vpncustomergateway
+ if (this.modals.vpnConnection === true) {
+ this.$nextTick(() => {
+ this.vpnConnectionForm.setFieldsValue({ vpncustomergateway:
this.vpncustomergateways[0].id })
+ })
+ }
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.modals.vpnConnectionLoading = false
+ })
+ },
+ handleOpenModals (e) {
+ switch (e) {
+ case 'privateGateways':
+ this.modals.gateway = true
+ this.gatewayForm.resetFields()
+ this.fetchAclList()
+ this.fetchPhysicalNetworks()
+ break
+ case 'vpnConnection':
+ this.modals.vpnConnection = true
+ this.vpnConnectionForm.resetFields()
+ this.fetchVpnCustomerGateways()
+ this.fetchVpnGateways()
+ break
+ case 'networkAcl':
+ this.modals.networkAcl = true
+ this.networkAclForm.resetFields()
+ break
+ }
+ },
+ handleGatewayFormSubmit () {
+ this.modals.gatewayLoading = true
+
+ this.gatewayForm.validateFields(errors => {
+ if (errors) {
+ this.modals.gatewayLoading = false
+ return
+ }
+
+ const data = this.gatewayForm.getFieldsValue()
+
+ api('createPrivateGateway', {
+ sourcenatsupported: data.nat,
+ physicalnetworkid: data.physicalnetwork,
+ vpcid: this.resource.id,
+ ipaddress: data.ipaddress,
+ gateway: data.gateway,
+ netmask: data.netmask,
+ vlan: data.vlan,
+ aclid: data.acl
+ }).then(response => {
+ this.$store.dispatch('AddAsyncJob', {
+ title: `Successfully added Private Gateway`,
+ jobid: response.createprivategatewayresponse.jobid,
+ status: 'progress'
+ })
+ this.$pollJob({
+ jobId: response.createprivategatewayresponse.jobid,
+ successMethod: () => {
+ this.modals.gateway = false
+ this.handleFetchData()
+ },
+ errorMessage: 'Adding Private Gateway failed',
+ errorMethod: () => {
+ this.modals.gateway = false
+ this.handleFetchData()
+ },
+ loadingMessage: `Adding Private Gateway...`,
+ catchMessage: 'Error encountered while fetching async job result',
+ catchMethod: () => {
+ this.modals.gateway = false
+ this.handleFetchData()
+ }
+ })
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.modals.gatewayLoading = false
+ this.modals.gateway = false
+ this.handleFetchData()
+ })
+ })
+ },
+ handleAcquireNewIp () {
+ this.fetchLoading = true
+ api('associateIpAddress', { vpcid: this.resource.id }).then(response => {
+ this.$store.dispatch('AddAsyncJob', {
+ title: `Successfully acquired new IP`,
+ jobid: response.associateipaddressresponse.jobid,
+ status: 'progress'
+ })
+ this.$pollJob({
+ jobId: response.associateipaddressresponse.jobid,
+ successMethod: () => {
+ this.fetchPublicIpAddresses()
+ },
+ errorMessage: 'Failed to acquire new IP',
+ errorMethod: () => {
+ this.fetchPublicIpAddresses()
+ },
+ loadingMessage: `Acquiring new IP...`,
+ catchMessage: 'Error encountered while fetching async job result',
+ catchMethod: () => {
+ this.fetchPublicIpAddresses()
+ }
+ })
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ this.fetchPublicIpAddresses()
+ })
+ },
+ handleVpnConnectionFormSubmit () {
+ this.fetchLoading = true
+ this.modals.vpnConnection = false
+
+ this.vpnConnectionForm.validateFields((errors, values) => {
+ if (errors) {
+ this.fetchLoading = false
+ return
+ }
+
+ api('createVpnConnection', {
+ s2svpngatewayid: this.vpnGateways[0].id,
+ s2scustomergatewayid: values.vpncustomergateway,
+ passive: values.passive ? values.passive : false
+ }).then(response => {
+ this.$store.dispatch('AddAsyncJob', {
+ title: `VPN Connection`,
+ jobid: response.createvpnconnectionresponse.jobid,
+ status: 'progress'
+ })
+ this.$pollJob({
+ jobId: response.createvpnconnectionresponse.jobid,
+ successMethod: () => {
+ this.fetchVpnConnections()
+ this.fetchLoading = false
+ },
+ errorMessage: 'Adding VPN Connection failed',
+ errorMethod: () => {
+ this.fetchVpnConnections()
+ this.fetchLoading = false
+ },
+ loadingMessage: `Adding VPN Connection...`,
+ catchMessage: 'Error encountered while fetching async job result',
+ catchMethod: () => {
+ this.fetchVpnConnections()
+ this.fetchLoading = false
+ }
+ })
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchVpnConnections()
+ this.fetchLoading = false
+ })
+ })
+ },
+ handleNetworkAclFormSubmit () {
+ this.fetchLoading = true
+ this.modals.networkAcl = false
+
+ this.networkAclForm.validateFields((errors, values) => {
+ if (errors) {
+ this.fetchLoading = false
+ }
+
+ api('createNetworkACLList', {
+ name: values.name,
+ description: values.description,
+ vpcid: this.resource.id
+ }).then(response => {
+ this.$store.dispatch('AddAsyncJob', {
+ title: `Successfully added Network ACL List`,
+ jobid: response.createnetworkacllistresponse.jobid,
+ status: 'progress'
+ })
+ this.$pollJob({
+ jobId: response.createnetworkacllistresponse.jobid,
+ successMethod: () => {
+ this.fetchLoading = false
+ },
+ errorMessage: 'Adding Network ACL List failed',
+ errorMethod: () => {
+ this.fetchLoading = false
+ },
+ loadingMessage: `Adding Network ACL List...`,
+ catchMessage: 'Error encountered while fetching async job result',
+ catchMethod: () => {
+ this.fetchLoading = false
+ }
+ })
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ this.fetchAclList()
+ })
+ })
+ },
+ handleCreateVpnGateway () {
+ this.fetchLoading = true
+ api('createVpnGateway', {
+ vpcid: this.resource.id
+ }).then(response => {
+ this.$store.dispatch('AddAsyncJob', {
+ title: `Successfully added VPN Gateway`,
+ jobid: response.createvpngatewayresponse.jobid,
+ status: 'progress'
+ })
+ this.$pollJob({
+ jobId: response.createvpngatewayresponse.jobid,
+ successMethod: () => {
+ this.fetchLoading = false
+ },
+ errorMessage: 'Adding VPN Gateway failed',
+ errorMethod: () => {
+ this.fetchLoading = false
+ },
+ loadingMessage: `Adding VPN Gateway...`,
+ catchMessage: 'Error encountered while fetching async job result',
+ catchMethod: () => {
+ this.fetchLoading = false
+ }
+ })
+ }).catch(error => {
+ this.$notification.error({
+ message: 'Request Failed',
+ description: error.response.headers['x-description']
+ })
+ }).finally(() => {
+ this.fetchLoading = false
+ this.handleFetchData()
+ })
+ },
+ changePage (page, pageSize) {
+ this.page = page
+ this.pageSize = pageSize
+ this.handleFetchData()
+ },
+ changePageSize (currentPage, pageSize) {
+ this.page = currentPage
+ this.pageSize = pageSize
+ this.handleFetchData()
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.list {
+
+ &__item,
+ &__row {
+ display: flex;
+ flex-wrap: wrap;
+ width: 100%;
+ }
+
+ &__item {
+ margin-bottom: -20px;
+ }
+
+ &__col {
+ flex: 1;
+ margin-right: 20px;
+ margin-bottom: 20px;
+ }
+
+ &__label {
+ font-weight: bold;
+ }
+
+}
+
+.pagination {
+ margin-top: 20px;
+}
+
+.table {
+ margin-top: 20px;
+ overflow-y: auto;
+}
+</style>
diff --git a/src/views/network/VpcTiersTab.vue
b/src/views/network/VpcTiersTab.vue
index fd30f00..a9fd5bb 100644
--- a/src/views/network/VpcTiersTab.vue
+++ b/src/views/network/VpcTiersTab.vue
@@ -24,11 +24,37 @@
<div class="list__item-container">
<div class="list__col">
<div class="list__label">
- <router-link :to="{ path: '/guestnetwork/' + network.id }">{{
network.name }}</router-link>
+ {{ $t('name') }}
</div>
- <div>CIDR: {{ network.cidr }}</div>
+ <div>
+ <router-link :to="{ path: '/guestnetwork/' + network.id }">{{
network.name }} </router-link>
+ <a-tag v-if="network.broadcasturi">{{ network.broadcasturi
}}</a-tag>
+ </div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">{{ $t('state') }}</div>
+ <div><status :text="network.state" displayText></status></div>
</div>
<div class="list__col">
+ <div class="list__label">
+ {{ $t('CIDR') }}
+ </div>
+ <div>{{ network.cidr }}</div>
+ </div>
+ <div class="list__col">
+ <div class="list__label">
+ {{ $t('aclid') }}
+ </div>
+ <div>
+ <router-link :to="{ path: '/acllist/' + network.aclid }">
+ {{ network.aclid }}
+ </router-link>
+ </div>
+ </div>
+
+ </div>
+ <div class="list__item-container">
+ <div class="list__col">
<a-button icon="share-alt">
<router-link :to="{ path: '/ilb?networkid=' + network.id }">
Internal LB</router-link>
</a-button>
@@ -50,20 +76,8 @@
</div>
</div>
</div>
- <div slot="actions">
- <a-popconfirm
- :title="`${$t('label.delete')}?`"
- @confirm="handleDelete(item)"
- okText="Yes"
- cancelText="No"
- placement="top"
- >
- <a-button icon="delete" type="danger" shape="round"></a-button>
- </a-popconfirm>
- </div>
</a-list-item>
</a-list>
-
</a-spin>
</template>