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 7c0d6aa compute: new instance hardware component
7c0d6aa is described below
commit 7c0d6aa2ef5e37fe644245c6682736b3e25e9ee5
Author: Rohit Yadav <[email protected]>
AuthorDate: Sun Jun 21 14:49:53 2020 +0530
compute: new instance hardware component
Refactor existing component in line of the VPC tab component
Signed-off-by: Rohit Yadav <[email protected]>
---
src/components/header/ProjectMenu.vue | 2 +-
src/config/section/compute.js | 7 +-
src/config/section/infra/routers.js | 7 +
src/core/lazy_lib/components_use.js | 1 +
.../{InstanceHardware.vue => InstanceTab.vue} | 323 +++++++++------------
src/views/network/NicsTable.vue | 121 ++++++++
6 files changed, 263 insertions(+), 198 deletions(-)
diff --git a/src/components/header/ProjectMenu.vue
b/src/components/header/ProjectMenu.vue
index 0d1f8db..adb4f96 100644
--- a/src/components/header/ProjectMenu.vue
+++ b/src/components/header/ProjectMenu.vue
@@ -21,7 +21,7 @@
class="project-select"
defaultValue="Default View"
:loading="loading"
- :value="('id' in $store.getters.project) ?
($store.getters.project.displaytext || $store.getters.project.name) : 'Default
View'"
+ :value="($store.getters.project && 'id' in $store.getters.project) ?
($store.getters.project.displaytext || $store.getters.project.name) : 'Default
View'"
:disabled="isDisabled()"
:filterOption="filterProject"
@change="changeProject"
diff --git a/src/config/section/compute.js b/src/config/section/compute.js
index 8219dca..2992a5a 100644
--- a/src/config/section/compute.js
+++ b/src/config/section/compute.js
@@ -61,6 +61,7 @@ export default {
}
return fields
},
+ details: ['displayname', 'name', 'id', 'state', 'ipaddress',
'templatename', 'ostypename', 'serviceofferingname', 'isdynamicallyscalable',
'haenable', 'hypervisor', 'boottype', 'bootmode', 'account', 'domain',
'zonename'],
related: [{
name: 'volume',
title: 'label.volumes',
@@ -79,11 +80,7 @@ export default {
param: 'virtualmachineid'
}],
tabs: [{
- name: 'hardware',
- component: () => import('@/views/compute/InstanceHardware.vue')
- }, {
- name: 'settings',
- component: () => import('@/components/view/DetailSettings')
+ component: () => import('@/views/compute/InstanceTab.vue')
}],
actions: [
{
diff --git a/src/config/section/infra/routers.js
b/src/config/section/infra/routers.js
index 8a0eba8..c810a5a 100644
--- a/src/config/section/infra/routers.js
+++ b/src/config/section/infra/routers.js
@@ -23,6 +23,13 @@ export default {
params: { projectid: '-1' },
columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname',
'redundantstate', 'version', 'hostname', 'account', 'zonename',
'requiresupgrade'],
details: ['name', 'id', 'version', 'requiresupgrade', 'guestnetworkname',
'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname',
'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account',
'zonename', 'created'],
+ tabs: [{
+ name: 'details',
+ component: () => import('@/components/view/DetailsTab.vue')
+ }, {
+ name: 'nics',
+ component: () => import('@/views/network/NicsTable.vue')
+ }],
actions: [
{
api: 'startRouter',
diff --git a/src/core/lazy_lib/components_use.js
b/src/core/lazy_lib/components_use.js
index 81ddb25..4713112 100644
--- a/src/core/lazy_lib/components_use.js
+++ b/src/core/lazy_lib/components_use.js
@@ -55,6 +55,7 @@ import {
Progress,
Skeleton,
Popconfirm,
+ Descriptions,
message,
notification
} from 'ant-design-vue'
diff --git a/src/views/compute/InstanceHardware.vue
b/src/views/compute/InstanceTab.vue
similarity index 64%
rename from src/views/compute/InstanceHardware.vue
rename to src/views/compute/InstanceTab.vue
index 4d9dacb..9d3ac02 100644
--- a/src/views/compute/InstanceHardware.vue
+++ b/src/views/compute/InstanceTab.vue
@@ -16,199 +16,109 @@
// under the License.
<template>
- <div>
- <a-collapse v-model="activeKey" :bordered="false">
- <a-collapse-panel :header="'ISO: ' + vm.isoname" v-if="vm.isoid" key="1">
- <a-list
- itemLayout="horizontal">
- <a-list-item>
- <a-list-item-meta>
- <div slot="avatar">
- <a-avatar>
- <a-icon type="usb" />
- </a-avatar>
- </div>
- <div slot="title">
- <router-link :to="{ path: '/iso/' + vm.isoid }">{{ vm.isoname
}}</router-link> <br/>
- <a-icon type="barcode"/> {{ vm.isoid }}
- </div>
- </a-list-item-meta>
- </a-list-item>
- </a-list>
- </a-collapse-panel>
-
- <a-collapse-panel :header="'Disks: ' + volumes.length" key="2">
- <a-list
+ <a-spin :spinning="loading">
+ <a-tabs
+ :activeKey="currentTab"
+ :tabPosition="device === 'mobile' ? 'top' : 'left'"
+ :animated="false"
+ @change="handleChangeTab">
+ <a-tab-pane :tab="$t('label.details')" key="details">
+ <DetailsTab :resource="resource" :loading="loading" />
+ </a-tab-pane>
+ <a-tab-pane :tab="$t('label.iso')" key="cdrom" v-if="vm.isoid">
+ <a-icon type="usb" />
+ <router-link :to="{ path: '/iso/' + vm.isoid }">{{ vm.isoname
}}</router-link> <br/>
+ <a-icon type="barcode"/> {{ vm.isoid }}
+ </a-tab-pane>
+ <a-tab-pane :tab="$t('label.volumes')" key="volumes" v-if="'listVolumes'
in $store.getters.apis">
+ <a-table
+ class="table"
size="small"
- itemLayout="vertical"
+ :columns="volumeColumns"
:dataSource="volumes"
+ :rowKey="item => item.id"
+ :pagination="false"
>
- <a-list-item slot="renderItem" slot-scope="item" class="list-item">
- <a-list-item-meta>
- <div slot="avatar">
- <a-avatar>
- <a-icon type="hdd" />
- </a-avatar>
- </div>
- <div slot="title" class="title">
- <router-link :to="{ path: '/volume/' + item.id }">{{ item.name
}} </router-link>
- <div class="tags">
- <a-tag v-if="item.type">
- {{ item.type }}
- </a-tag>
- <a-tag v-if="item.state">
- {{ item.state }}
- </a-tag>
- <a-tag v-if="item.provisioningtype">
- {{ item.provisioningtype }}
- </a-tag>
- </div>
- </div>
- </a-list-item-meta>
- <div>
- <a-divider class="divider-small" />
- <div class="attribute">
- <div class="label">{{ $t('label.size') }}</div>
- <div>{{ (item.size / (1024 * 1024 * 1024.0)).toFixed(2) }}
GB</div>
- </div>
- <div class="attribute" v-if="item.physicalsize">
- <div class="label">{{ $t('label.physicalsize') }}</div>
- <div>{{ (item.physicalsize / (1024 * 1024 *
1024.0)).toFixed(4) }} GB</div>
- </div>
- <div class="attribute" v-if="item.storage">
- <div class="label">{{ $t('label.storagepool') }}</div>
- <div>{{ item.storage }} ({{ item.storagetype }})</div>
- </div>
- <div class="attribute">
- <div class="label">{{ $t('label.id') }}</div>
- <div><a-icon type="barcode"/> {{ item.id }}</div>
- </div>
- </div>
- </a-list-item>
- </a-list>
- </a-collapse-panel>
-
- <a-collapse-panel :header="'Network Adapter(s): ' + (vm && vm.nic ?
vm.nic.length : 0)" key="3" >
+ <template slot="name" slot-scope="text, item">
+ <a-icon type="hdd" />
+ <router-link :to="{ path: '/volume/' + item.id }">
+ {{ text }}
+ </router-link>
+ <a-tag v-if="item.provisioningtype">
+ {{ item.provisioningtype }}
+ </a-tag>
+ </template>
+ <template slot="state" slot-scope="text">
+ <status :text="text ? text : ''" displayText />
+ </template>
+ <template slot="size" slot-scope="text, item">
+ {{ parseFloat(item.size / (1024.0 * 1024.0 * 1024.0)).toFixed(2)
}} GB
+ </template>
+ </a-table>
+ </a-tab-pane>
+ <a-tab-pane :tab="$t('label.nics')" key="nics" v-if="'listNics' in
$store.getters.apis">
<a-button
- type="primary"
+ type="dashed"
+ style="width: 100%; margin-bottom: 10px"
@click="showAddModal"
:loading="loadingNic"
:disabled="!('addNicToVirtualMachine' in $store.getters.apis)">
<a-icon type="plus"></a-icon> {{ $t('label.network.addvm') }}
</a-button>
- <a-divider class="divider-small" />
- <a-list
- size="small"
- itemLayout="vertical"
- :dataSource="vm.nic"
- class="list"
- :loading="loadingNic"
- >
- <a-list-item slot="renderItem" slot-scope="item" class="list-item">
- <a-list-item-meta>
- <div slot="avatar">
- <a-avatar slot="avatar">
- <a-icon type="wifi" />
- </a-avatar>
- </div>
- <div slot="title" class="title">
- <router-link :to="{ path: '/guestnetwork/' + item.networkid
}">{{ item.networkname }} </router-link>
- <div class="title__details">
- <div class="actions">
- <a-popconfirm
- title="Please confirm that you would like to make this
NIC the default for this VM."
- @confirm="setAsDefault(item)"
- okText="Yes"
- cancelText="No"
- v-if="!item.isdefault"
- >
- <a-button
- :disabled="!('updateDefaultNicForVirtualMachine' in
$store.getters.apis)"
- icon="check-square"
- shape="circle" />
- </a-popconfirm>
- <a-tooltip placement="bottom" v-if="item.type !== 'L2'">
- <template slot="title">
- {{ "Change IP Address" }}
- </template>
- <a-button
- icon="swap"
- shape="circle"
- :disabled="!('updateVmNicIp' in $store.getters.apis)"
- @click="editIpAddressNic = item.id; showUpdateIpModal
= true" />
- </a-tooltip>
- <a-tooltip placement="bottom" v-if="item.type !== 'L2'">
- <template slot="title">
- {{ "Manage Secondary IP Addresses" }}
- </template>
- <a-button
- icon="environment"
- shape="circle"
- :disabled="(!('addIpToNic' in $store.getters.apis) &&
!('addIpToNic' in $store.getters.apis))"
- @click="fetchSecondaryIPs(item.id)" />
- </a-tooltip>
- <a-popconfirm
- :title="$t('message.network.removenic')"
- @confirm="removeNIC(item)"
- okText="Yes"
- cancelText="No"
- v-if="!item.isdefault"
- >
- <a-button
- :disabled="!('removeNicFromVirtualMachine' in
$store.getters.apis)"
- type="danger"
- icon="delete"
- shape="circle" />
- </a-popconfirm>
- </div>
- <div class="tags">
- <a-tag v-if="item.isdefault">
- {{ $t('label.default') }}
- </a-tag>
- <a-tag v-if="item.type">
- {{ item.type }}
- </a-tag>
- <a-tag v-if="item.broadcasturi">
- {{ item.broadcasturi }}
- </a-tag>
- <a-tag v-if="item.isolationuri">
- {{ item.isolationuri }}
- </a-tag>
- </div>
- </div>
- </div>
- </a-list-item-meta>
- <div>
- <a-divider class="divider-small" />
- <div class="attribute">
- <div class="label">{{ $t('label.macaddress') }}</div>
- <div>{{ item.macaddress }}</div>
- </div>
- <div class="attribute" v-if="item.ipaddress">
- <div class="label">{{ $t('label.ipaddress') }}</div>
- <div>{{ item.ipaddress }}</div>
- </div>
- <div class="attribute" v-if="item.secondaryip &&
item.secondaryip.length > 0 && item.type !== 'L2'">
- <div class="label">{{ $t('label.secondaryips') }}</div>
- <div>{{ item.secondaryip.map(x => x.ipaddress).join(', ')
}}</div>
- </div>
- <div class="attribute" v-if="item.netmask">
- <div class="label">{{ $t('label.netmask') }}</div>
- <div>{{ item.netmask }}</div>
- </div>
- <div class="attribute" v-if="item.gateway">
- <div class="label">{{ $t('label.gateway') }}</div>
- <div>{{ item.gateway }}</div>
- </div>
- <div class="attribute">
- <div class="label">{{ $t('label.id') }}</div>
- <div><a-icon type="barcode"/> {{ item.id }}</div>
- </div>
- </div>
- </a-list-item>
- </a-list>
- </a-collapse-panel>
- </a-collapse>
+ <NicsTable :resource="vm" :loading="loading">
+ <span slot="actions" slot-scope="record">
+ <a-popconfirm
+ :title="$t('label.set.default.nic')"
+ @confirm="setAsDefault(record.nic)"
+ okText="Yes"
+ cancelText="No"
+ v-if="!record.nic.isdefault"
+ >
+ <a-button
+ :disabled="!('updateDefaultNicForVirtualMachine' in
$store.getters.apis)"
+ icon="check-square"
+ shape="circle" />
+ </a-popconfirm>
+ <a-tooltip placement="bottom" v-if="record.nic.type !== 'L2'">
+ <template slot="title">
+ {{ "Change IP Address" }}
+ </template>
+ <a-button
+ icon="swap"
+ shape="circle"
+ :disabled="!('updateVmNicIp' in $store.getters.apis)"
+ @click="editIpAddressNic = record.nic.id; showUpdateIpModal =
true" />
+ </a-tooltip>
+ <a-tooltip placement="bottom" v-if="record.nic.type !== 'L2'">
+ <template slot="title">
+ {{ "Manage Secondary IP Addresses" }}
+ </template>
+ <a-button
+ icon="environment"
+ shape="circle"
+ :disabled="(!('addIpToNic' in $store.getters.apis) &&
!('addIpToNic' in $store.getters.apis))"
+ @click="fetchSecondaryIPs(record.nic.id)" />
+ </a-tooltip>
+ <a-popconfirm
+ :title="$t('message.network.removenic')"
+ @confirm="removeNIC(record.nic)"
+ okText="Yes"
+ cancelText="No"
+ v-if="!record.nic.isdefault"
+ >
+ <a-button
+ :disabled="!('removeNicFromVirtualMachine' in
$store.getters.apis)"
+ type="danger"
+ icon="delete"
+ shape="circle" />
+ </a-popconfirm>
+ </span>
+ </NicsTable>
+ </a-tab-pane>
+ <a-tab-pane :tab="$t('label.settings')" key="settings">
+ <DetailSettings :resource="resource" :loading="loading" />
+ </a-tab-pane>
+ </a-tabs>
<a-modal
:visible="showAddNetworkModal"
@@ -216,10 +126,9 @@
@cancel="closeModals"
@ok="submitAddNetwork">
{{ $t('message.network.addvm.desc') }}
-
<div class="modal-form">
<p class="modal-form__label">{{ $t('label.network') }}:</p>
- <a-select :defaultValue="addNetworkData.network" @change="e =>
addNetworkData.network === e">
+ <a-select :defaultValue="addNetworkData.network" @change="e =>
addNetworkData.network = e">
<a-select-option
v-for="network in addNetworkData.allNetworks"
:key="network.id"
@@ -230,7 +139,6 @@
<p class="modal-form__label">{{ $t('label.publicip') }}:</p>
<a-input v-model="addNetworkData.ip"></a-input>
</div>
-
</a-modal>
<a-modal
@@ -245,7 +153,6 @@
<p class="modal-form__label">{{ $t('label.publicip') }}:</p>
<a-input v-model="editIpAddressValue"></a-input>
</div>
-
</a-modal>
<a-modal
@@ -284,21 +191,29 @@
</a-list>
</a-modal>
- </div>
+ </a-spin>
</template>
<script>
import { api } from '@/api'
+import { mixinDevice } from '@/utils/mixin.js'
import ResourceLayout from '@/layouts/ResourceLayout'
import Status from '@/components/widgets/Status'
+import DetailsTab from '@/components/view/DetailsTab'
+import DetailSettings from '@/components/view/DetailSettings'
+import NicsTable from '@/views/network/NicsTable'
export default {
- name: 'InstanceHardware',
+ name: 'InstanceTab',
components: {
ResourceLayout,
+ DetailsTab,
+ DetailSettings,
+ NicsTable,
Status
},
+ mixins: [mixinDevice],
props: {
resource: {
type: Object,
@@ -315,7 +230,7 @@ export default {
vm: {},
volumes: [],
totalStorage: 0,
- activeKey: ['1', '2', '3'],
+ currentTab: 'details',
showAddNetworkModal: false,
showUpdateIpModal: false,
showSecondaryIpModal: false,
@@ -329,7 +244,28 @@ export default {
editIpAddressValue: '',
secondaryIPs: [],
selectedNicId: '',
- newSecondaryIp: ''
+ newSecondaryIp: '',
+ volumeColumns: [
+ {
+ title: this.$t('label.name'),
+ dataIndex: 'name',
+ scopedSlots: { customRender: 'name' }
+ },
+ {
+ title: this.$t('label.state'),
+ dataIndex: 'state',
+ scopedSlots: { customRender: 'state' }
+ },
+ {
+ title: this.$t('label.type'),
+ dataIndex: 'type'
+ },
+ {
+ title: this.$t('label.size'),
+ dataIndex: 'size',
+ scopedSlots: { customRender: 'size' }
+ }
+ ]
}
},
created () {
@@ -346,6 +282,9 @@ export default {
}
},
methods: {
+ handleChangeTab (e) {
+ this.currentTab = e
+ },
fetchData () {
this.volumes = []
if (!this.vm || !this.vm.id) {
diff --git a/src/views/network/NicsTable.vue b/src/views/network/NicsTable.vue
new file mode 100644
index 0000000..06d78bd
--- /dev/null
+++ b/src/views/network/NicsTable.vue
@@ -0,0 +1,121 @@
+// 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-table
+ size="small"
+ :columns="nicColumns"
+ :dataSource="resource.nic"
+ :rowKey="item => item.id"
+ :pagination="false"
+ >
+ <p slot="expandedRowRender" slot-scope="record">
+ <slot name="actions" :nic="record" />
+ <a-descriptions style="margin-top: 10px" layout="vertical" :column="1"
:bordered="false" size="small">
+ <a-descriptions-item :label="$t('label.id')">
+ {{ record.id }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.networkid')"
v-if="record.networkid">
+ {{ record.networkid }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.type')" v-if="record.type">
+ {{ record.type }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.traffictype')"
v-if="record.traffictype">
+ {{ record.traffictype }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.secondaryips')"
v-if="record.secondaryip && record.secondaryip.length > 0 && record.type !==
'L2'">
+ {{ record.secondaryip.map(x => x.ipaddress).join(', ') }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.ip6address')"
v-if="record.ip6address">
+ {{ record.ip6address }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.ip6gateway')"
v-if="record.ip6gateway">
+ {{ record.ip6gateway }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.ip6cidr')"
v-if="record.ip6cidr">
+ {{ record.ip6cidr }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.broadcasturi')"
v-if="record.broadcasturi">
+ {{ record.broadcasturi }}
+ </a-descriptions-item>
+ <a-descriptions-item :label="$t('label.isolationuri')"
v-if="record.isolationuri">
+ {{ record.isolationuri }}
+ </a-descriptions-item>
+ </a-descriptions>
+ </p>
+ <template slot="networkname" slot-scope="text, item">
+ <a-icon type="apartment" />
+ <router-link :to="{ path: '/guestnetwork/' + item.networkid }">
+ {{ text }}
+ </router-link>
+ <a-tag v-if="item.isdefault">
+ Default
+ </a-tag>
+ </template>
+ </a-table>
+</template>
+
+<script>
+
+export default {
+ name: 'NicsTable',
+ props: {
+ resource: {
+ type: Object,
+ required: true
+ },
+ loading: {
+ type: Boolean,
+ default: false
+ }
+ },
+ inject: ['parentFetchData'],
+ data () {
+ return {
+ nicColumns: [
+ {
+ title: this.$t('label.networkname'),
+ dataIndex: 'networkname',
+ scopedSlots: { customRender: 'networkname' }
+ },
+ {
+ title: this.$t('label.macaddress'),
+ dataIndex: 'macaddress'
+ },
+ {
+ title: this.$t('label.ipaddress'),
+ dataIndex: 'ipaddress'
+ },
+ {
+ title: this.$t('label.netmask'),
+ dataIndex: 'netmask'
+ },
+ {
+ title: this.$t('label.gateway'),
+ dataIndex: 'gateway'
+ }
+ ]
+ }
+ },
+ watch: {
+ resource: function (newItem, oldItem) {
+ this.resource = newItem
+ }
+ }
+}
+</script>