mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
compute: NICs and IPs management (#71)
Adds VM nic/ip management, implement some placement fixes. Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
200f89bc08
commit
b140b738fb
58
ui/package-lock.json
generated
58
ui/package-lock.json
generated
@ -2341,9 +2341,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@fortawesome/vue-fontawesome": {
|
"@fortawesome/vue-fontawesome": {
|
||||||
"version": "0.1.8",
|
"version": "0.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-0.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-0.1.9.tgz",
|
||||||
"integrity": "sha512-SdFiUD+vFDA/xKuEbnQTVrK8FDxoV0eyQaiHxmCcjAc0+vQe0Kf6oGm28opNPIt8MTgKWR3+Yg3xXP455Ae4tQ=="
|
"integrity": "sha512-h/emhmZz+DfB2zOGLWawNwXq82UYhn9waTfUjLLmeaIqtnIyNt6kYlpQT/vzJjLZRDRvY2IEJAh1di5qKpKVpA=="
|
||||||
},
|
},
|
||||||
"@hapi/address": {
|
"@hapi/address": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
@ -8526,9 +8526,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "3.4.8",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.5.0.tgz",
|
||||||
"integrity": "sha512-b+BBmCZmVgho8KnBUOXpvlqEMguko+0P+kXCwD4vIprsXC6ht1qgPxtb1OK6XgSlrySF71wkwBQ0Hv695bk9gQ=="
|
"integrity": "sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw=="
|
||||||
},
|
},
|
||||||
"core-js-compat": {
|
"core-js-compat": {
|
||||||
"version": "3.4.7",
|
"version": "3.4.7",
|
||||||
@ -10009,9 +10009,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"version": "6.5.1",
|
"version": "6.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
|
||||||
"integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==",
|
"integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.4.0",
|
"bn.js": "^4.4.0",
|
||||||
@ -20621,9 +20621,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"serialize-javascript": {
|
"serialize-javascript": {
|
||||||
"version": "1.9.1",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
|
||||||
"integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
|
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"serve-index": {
|
"serve-index": {
|
||||||
@ -22016,16 +22016,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"terser-webpack-plugin": {
|
"terser-webpack-plugin": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
|
||||||
"integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==",
|
"integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cacache": "^12.0.2",
|
"cacache": "^12.0.2",
|
||||||
"find-cache-dir": "^2.1.0",
|
"find-cache-dir": "^2.1.0",
|
||||||
"is-wsl": "^1.1.0",
|
"is-wsl": "^1.1.0",
|
||||||
"schema-utils": "^1.0.0",
|
"schema-utils": "^1.0.0",
|
||||||
"serialize-javascript": "^1.7.0",
|
"serialize-javascript": "^2.1.2",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
"terser": "^4.1.2",
|
"terser": "^4.1.2",
|
||||||
"webpack-sources": "^1.4.0",
|
"webpack-sources": "^1.4.0",
|
||||||
@ -23005,9 +23005,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"vue": {
|
"vue": {
|
||||||
"version": "2.6.10",
|
"version": "2.6.11",
|
||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
|
||||||
"integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ=="
|
"integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
|
||||||
},
|
},
|
||||||
"vue-cli-plugin-apollo": {
|
"vue-cli-plugin-apollo": {
|
||||||
"version": "0.21.3",
|
"version": "0.21.3",
|
||||||
@ -23259,9 +23259,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"vue-i18n": {
|
"vue-i18n": {
|
||||||
"version": "8.15.1",
|
"version": "8.15.3",
|
||||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.15.3.tgz",
|
||||||
"integrity": "sha512-GBbz8qYCu0U2LNu4IcuFLZiuyninG4k26knvhL7GZG5Ncp4RR2VKDEH6g8gQ6I+UUBCvH2MBQVPSdxWe4DBkPw=="
|
"integrity": "sha512-PVNgo6yhOmacZVFjSapZ314oewwLyXHjJwAqjnaPN1GJAJd/dvsrShGzSiJuCX4Hc36G4epJvNXUwO8y7wEKew=="
|
||||||
},
|
},
|
||||||
"vue-i18n-extract": {
|
"vue-i18n-extract": {
|
||||||
"version": "0.4.14",
|
"version": "0.4.14",
|
||||||
@ -23506,9 +23506,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-template-compiler": {
|
"vue-template-compiler": {
|
||||||
"version": "2.6.10",
|
"version": "2.6.11",
|
||||||
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz",
|
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz",
|
||||||
"integrity": "sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==",
|
"integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"de-indent": "^1.0.2",
|
"de-indent": "^1.0.2",
|
||||||
@ -23607,9 +23607,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"webpack": {
|
"webpack": {
|
||||||
"version": "4.41.2",
|
"version": "4.41.3",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.3.tgz",
|
||||||
"integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==",
|
"integrity": "sha512-EcNzP9jGoxpQAXq1VOoTet0ik7/VVU1MovIfcUSAjLowc7GhcQku/sOXALvq5nPpSei2HF6VRhibeJSC3i/Law==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@webassemblyjs/ast": "1.8.5",
|
"@webassemblyjs/ast": "1.8.5",
|
||||||
@ -23632,7 +23632,7 @@
|
|||||||
"node-libs-browser": "^2.2.1",
|
"node-libs-browser": "^2.2.1",
|
||||||
"schema-utils": "^1.0.0",
|
"schema-utils": "^1.0.0",
|
||||||
"tapable": "^1.1.3",
|
"tapable": "^1.1.3",
|
||||||
"terser-webpack-plugin": "^1.4.1",
|
"terser-webpack-plugin": "^1.4.3",
|
||||||
"watchpack": "^1.6.0",
|
"watchpack": "^1.6.0",
|
||||||
"webpack-sources": "^1.4.1"
|
"webpack-sources": "^1.4.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,10 +37,10 @@
|
|||||||
"@fortawesome/free-brands-svg-icons": "^5.12.0",
|
"@fortawesome/free-brands-svg-icons": "^5.12.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "^5.12.0",
|
"@fortawesome/free-regular-svg-icons": "^5.12.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.8",
|
"@fortawesome/vue-fontawesome": "^0.1.9",
|
||||||
"ant-design-vue": "~1.4.10",
|
"ant-design-vue": "~1.4.10",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
"core-js": "^3.4.8",
|
"core-js": "^3.5.0",
|
||||||
"enquire.js": "^2.1.6",
|
"enquire.js": "^2.1.6",
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
@ -51,10 +51,10 @@
|
|||||||
"npm-check-updates": "^4.0.1",
|
"npm-check-updates": "^4.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"viser-vue": "^2.4.7",
|
"viser-vue": "^2.4.7",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.11",
|
||||||
"vue-clipboard2": "^0.3.1",
|
"vue-clipboard2": "^0.3.1",
|
||||||
"vue-cropper": "0.4.9",
|
"vue-cropper": "0.4.9",
|
||||||
"vue-i18n": "^8.15.1",
|
"vue-i18n": "^8.15.3",
|
||||||
"vue-ls": "^3.2.1",
|
"vue-ls": "^3.2.1",
|
||||||
"vue-router": "^3.1.3",
|
"vue-router": "^3.1.3",
|
||||||
"vue-svg-component-runtime": "^1.0.1",
|
"vue-svg-component-runtime": "^1.0.1",
|
||||||
@ -87,8 +87,8 @@
|
|||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
"vue-cli-plugin-i18n": "^0.6.0",
|
"vue-cli-plugin-i18n": "^0.6.0",
|
||||||
"vue-svg-icon-loader": "^2.1.1",
|
"vue-svg-icon-loader": "^2.1.1",
|
||||||
"vue-template-compiler": "^2.6.10",
|
"vue-template-compiler": "^2.6.11",
|
||||||
"webpack": "^4.41.2"
|
"webpack": "^4.41.3"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
|
|||||||
@ -35,13 +35,36 @@
|
|||||||
:dataSource="detailOptions[newKey]"
|
:dataSource="detailOptions[newKey]"
|
||||||
placeholder="Value"
|
placeholder="Value"
|
||||||
@change="e => onAddInputChange(e, 'newValue')" />
|
@change="e => onAddInputChange(e, 'newValue')" />
|
||||||
<a-button type="dashed" style="width: 50%" icon="close" @click="showAddDetail = false">Cancel</a-button>
|
<a-button type="primary" style="width: 25%" icon="plus" @click="addDetail">Add Setting</a-button>
|
||||||
<a-button type="primary" style="width: 50%" icon="plus" @click="addDetail">Add Setting</a-button>
|
<a-button type="dashed" style="width: 25%" icon="close" @click="showAddDetail = false">Cancel</a-button>
|
||||||
</div>
|
</div>
|
||||||
<a-list size="large">
|
<a-list size="large">
|
||||||
<a-list-item :key="index" v-for="(item, index) in details">
|
<a-list-item :key="index" v-for="(item, index) in details">
|
||||||
<a-list-item-meta>
|
<a-list-item-meta>
|
||||||
<span slot="title"><strong>{{ item.name }}</strong></span>
|
<span slot="title">
|
||||||
|
{{ item.name }}
|
||||||
|
<a-button shape="circle" size="small" @click="updateDetail(index)" v-if="item.edit">
|
||||||
|
<a-icon type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
|
||||||
|
</a-button>
|
||||||
|
<a-button shape="circle" size="small" @click="hideEditDetail(index)" v-if="item.edit" style="margin-left: 5px">
|
||||||
|
<a-icon type="close-circle" theme="twoTone" twoToneColor="#f5222d" />
|
||||||
|
</a-button>
|
||||||
|
<a-button shape="circle" size="small" @click="showEditDetail(index)" v-if="!item.edit">
|
||||||
|
<a-icon type="edit" />
|
||||||
|
</a-button>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a-popconfirm
|
||||||
|
title="Delete setting?"
|
||||||
|
@confirm="deleteDetail(index)"
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<a-button shape="circle" size="small">
|
||||||
|
<a-icon type="delete" theme="twoTone" twoToneColor="#f5222d" />
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
</span>
|
||||||
<span slot="description" style="word-break: break-all">
|
<span slot="description" style="word-break: break-all">
|
||||||
<span v-if="item.edit" style="display: flex">
|
<span v-if="item.edit" style="display: flex">
|
||||||
<a-auto-complete
|
<a-auto-complete
|
||||||
@ -54,30 +77,6 @@
|
|||||||
<span v-else @click="showEditDetail(index)">{{ item.value }}</span>
|
<span v-else @click="showEditDetail(index)">{{ item.value }}</span>
|
||||||
</span>
|
</span>
|
||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
<div slot="actions">
|
|
||||||
<a-button shape="circle" size="default" @click="updateDetail(index)" v-if="item.edit">
|
|
||||||
<a-icon type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
|
|
||||||
</a-button>
|
|
||||||
<a-button shape="circle" size="default" @click="hideEditDetail(index)" v-if="item.edit">
|
|
||||||
<a-icon type="close-circle" theme="twoTone" twoToneColor="#f5222d" />
|
|
||||||
</a-button>
|
|
||||||
<a-button shape="circle" @click="showEditDetail(index)" v-if="!item.edit">
|
|
||||||
<a-icon type="edit" />
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
<div slot="actions">
|
|
||||||
<a-popconfirm
|
|
||||||
title="Delete setting?"
|
|
||||||
@confirm="deleteDetail(index)"
|
|
||||||
okText="Yes"
|
|
||||||
cancelText="No"
|
|
||||||
placement="left"
|
|
||||||
>
|
|
||||||
<a-button shape="circle">
|
|
||||||
<a-icon type="delete" theme="twoTone" twoToneColor="#f5222d" />
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
</div>
|
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-list>
|
</a-list>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
|
|||||||
@ -17,13 +17,13 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-table
|
<a-table
|
||||||
size="small"
|
size="middle"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:dataSource="items"
|
:dataSource="items"
|
||||||
:rowKey="record => record.id || record.name"
|
:rowKey="record => record.id || record.name"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
|
:rowSelection="['vm', 'event', 'alert'].includes($route.name) ? {selectedRowKeys: selectedRowKeys, onChange: onSelectChange} : null"
|
||||||
:rowClassName="getRowClassName"
|
:rowClassName="getRowClassName"
|
||||||
>
|
>
|
||||||
<template slot="footer">
|
<template slot="footer">
|
||||||
@ -33,7 +33,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a slot="name" slot-scope="text, record" href="javascript:;">
|
<a slot="name" slot-scope="text, record" href="javascript:;">
|
||||||
<div>
|
<div style="min-width: 150px; padding-left: 5px">
|
||||||
<span v-if="$route.path.startsWith('/project')" style="margin-right: 5px">
|
<span v-if="$route.path.startsWith('/project')" style="margin-right: 5px">
|
||||||
<a-button type="dashed" size="small" shape="circle" icon="login" @click="changeProject(record)" />
|
<a-button type="dashed" size="small" shape="circle" icon="login" @click="changeProject(record)" />
|
||||||
</span>
|
</span>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<router-link :to="{ path: $route.path + '/' + record.id }" v-if="record.id">{{ text }}</router-link>
|
<router-link :to="{ path: $route.path + '/' + record.id }" v-if="record.id">{{ text }}</router-link>
|
||||||
<router-link :to="{ path: $route.path + '/' + record.name }" v-else>{{ text }}</router-link>
|
<router-link :to="{ path: $route.path + '/' + record.name }" v-else>{{ text }}</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$route.meta.related" style="padding-top: 5px">
|
<div v-if="$route.meta.related" style="padding-top: 10px; padding-left: 5px; display: inline-flex">
|
||||||
<span v-for="item in $route.meta.related" :key="item.path">
|
<span v-for="item in $route.meta.related" :key="item.path">
|
||||||
<router-link
|
<router-link
|
||||||
v-if="$router.resolve('/' + item.name).route.name !== '404'"
|
v-if="$router.resolve('/' + item.name).route.name !== '404'"
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<a-list size="large" class="list" :loading="loading || tabLoading">
|
<a-list size="large" class="list" :loading="loading || tabLoading">
|
||||||
<a-list-item :key="index" v-for="(item, index) in items" class="item">
|
<a-list-item :key="index" v-for="(item, index) in items" class="item">
|
||||||
<a-list-item-meta>
|
<a-list-item-meta>
|
||||||
<span slot="title" style="word-break: break-all"><strong>{{ item.name }}</strong></span>
|
<span slot="title" style="word-break: break-all">{{ item.name }}</span>
|
||||||
<span slot="description" style="word-break: break-all">{{ item.description }}</span>
|
<span slot="description" style="word-break: break-all">{{ item.description }}</span>
|
||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
|
|
||||||
|
|||||||
@ -173,8 +173,16 @@ export default {
|
|||||||
icon: 'safety-certificate',
|
icon: 'safety-certificate',
|
||||||
label: 'Add certificate',
|
label: 'Add certificate',
|
||||||
dataView: true,
|
dataView: true,
|
||||||
args: ['name', 'certificate', 'privatekey', 'certchain', 'password'],
|
args: ['name', 'certificate', 'privatekey', 'certchain', 'password', 'account', 'domainid'],
|
||||||
show: (record) => { return record.state === 'enabled' }
|
show: (record) => { return record.state === 'enabled' },
|
||||||
|
mapping: {
|
||||||
|
account: {
|
||||||
|
value: (record) => { return record.name }
|
||||||
|
},
|
||||||
|
domainid: {
|
||||||
|
value: (record) => { return record.domainid }
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
api: 'deleteAccount',
|
api: 'deleteAccount',
|
||||||
|
|||||||
@ -134,6 +134,7 @@
|
|||||||
"current": "isCurrent",
|
"current": "isCurrent",
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"dedicated": "Dedicated",
|
"dedicated": "Dedicated",
|
||||||
|
"default": "Default",
|
||||||
"deleteconfirm": "Please confirm that you would like to delete this {name}",
|
"deleteconfirm": "Please confirm that you would like to delete this {name}",
|
||||||
"deleteprofile": "Delete Profile",
|
"deleteprofile": "Delete Profile",
|
||||||
"deploymentPlanner": "Deployment planner",
|
"deploymentPlanner": "Deployment planner",
|
||||||
@ -632,6 +633,10 @@
|
|||||||
"memused": "Memory Usage",
|
"memused": "Memory Usage",
|
||||||
"message.edit.account": "Edit (\"-1\" indicates no limit to the amount of resources create)",
|
"message.edit.account": "Edit (\"-1\" indicates no limit to the amount of resources create)",
|
||||||
"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.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.",
|
||||||
|
"message.network.secondaryIP" : "Please confirm that you would like to acquire a new secondary IP for this NIC. \n NOTE: You need to manually configure the newly-acquired secondary IP inside the virtual machine.",
|
||||||
|
"message.network.updateIp": "Please confirm that you would like to change the IP address for this NIC on VM.",
|
||||||
"minCPUNumber": "Min CPU Cores",
|
"minCPUNumber": "Min CPU Cores",
|
||||||
"minInstance": "Min Instances",
|
"minInstance": "Min Instances",
|
||||||
"minIops": "Min IOPS",
|
"minIops": "Min IOPS",
|
||||||
@ -729,6 +734,7 @@
|
|||||||
"protocolnumber": "#Protocol",
|
"protocolnumber": "#Protocol",
|
||||||
"provider": "HA Provider",
|
"provider": "HA Provider",
|
||||||
"providername": "Provider",
|
"providername": "Provider",
|
||||||
|
"provisioning": "Provisioning",
|
||||||
"provisioningType": "Provisioning Type",
|
"provisioningType": "Provisioning Type",
|
||||||
"provisioningtype": "Provisioning Type",
|
"provisioningtype": "Provisioning Type",
|
||||||
"publicinterface": "Public Interface",
|
"publicinterface": "Public Interface",
|
||||||
@ -754,6 +760,7 @@
|
|||||||
"redundantstate": "Redundant state",
|
"redundantstate": "Redundant state",
|
||||||
"redundantvpcrouter": "Redundant VPC",
|
"redundantvpcrouter": "Redundant VPC",
|
||||||
"reenterpassword": "Re-enter Password",
|
"reenterpassword": "Re-enter Password",
|
||||||
|
"refresh": "Refresh",
|
||||||
"relationaloperator": "Operator",
|
"relationaloperator": "Operator",
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
"requireshvm": "HVM",
|
"requireshvm": "HVM",
|
||||||
@ -946,6 +953,7 @@
|
|||||||
"zoneId": "Zone",
|
"zoneId": "Zone",
|
||||||
"zoneid": "Zone",
|
"zoneid": "Zone",
|
||||||
"zonename": "Zone",
|
"zonename": "Zone",
|
||||||
|
"zonenamelabel": "Zone Name",
|
||||||
"instance": "Instance",
|
"instance": "Instance",
|
||||||
"yourInstance": "Your instance",
|
"yourInstance": "Your instance",
|
||||||
"newInstance": "New instance",
|
"newInstance": "New instance",
|
||||||
|
|||||||
@ -19,23 +19,25 @@
|
|||||||
<div>
|
<div>
|
||||||
<a-card class="breadcrumb-card">
|
<a-card class="breadcrumb-card">
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="12">
|
<a-col :span="24" style="display: flex">
|
||||||
<breadcrumb style="padding-top: 6px" />
|
<breadcrumb />
|
||||||
|
<a-tooltip placement="bottom">
|
||||||
|
<template slot="title">
|
||||||
|
{{ "Refresh" }}
|
||||||
|
</template>
|
||||||
|
<a-button
|
||||||
|
style="margin-left: 8px"
|
||||||
|
:loading="loading"
|
||||||
|
shape="round"
|
||||||
|
size="small"
|
||||||
|
icon="sync"
|
||||||
|
@click="fetchData()">
|
||||||
|
{{ $t('refresh') }}
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="24" style="padding-top: 12px; margin-bottom: -6px">
|
||||||
<span style="float: right">
|
<span style="padding-left: 5px">
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template slot="title">
|
|
||||||
{{ "Refresh" }}
|
|
||||||
</template>
|
|
||||||
<a-button
|
|
||||||
:loading="loading"
|
|
||||||
shape="circle"
|
|
||||||
type="dashed"
|
|
||||||
icon="reload"
|
|
||||||
style="margin-right: 5px"
|
|
||||||
@click="fetchData()" />
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-for="(action, actionIndex) in actions"
|
v-for="(action, actionIndex) in actions"
|
||||||
:key="actionIndex"
|
:key="actionIndex"
|
||||||
@ -56,7 +58,7 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
style="width: unset"
|
style="width: 50%; padding-left: 6px"
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
v-if="!dataView && !treeView"
|
v-if="!dataView && !treeView"
|
||||||
|
|||||||
@ -17,18 +17,22 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-collapse v-model="activeKey">
|
<a-collapse v-model="activeKey" :bordered="false">
|
||||||
|
|
||||||
<a-collapse-panel :header="'ISO: ' + vm.isoname" v-if="vm.isoid" key="1">
|
<a-collapse-panel :header="'ISO: ' + vm.isoname" v-if="vm.isoid" key="1">
|
||||||
<a-list
|
<a-list
|
||||||
itemLayout="horizontal">
|
itemLayout="horizontal">
|
||||||
<a-list-item>
|
<a-list-item>
|
||||||
<a-list-item-meta :description="vm.isoid">
|
<a-list-item-meta>
|
||||||
<a slot="title" href="">
|
<div slot="avatar">
|
||||||
<router-link :to="{ path: '/iso/' + vm.isoid }">{{ vm.isoname }}</router-link>
|
<a-avatar>
|
||||||
</a> ({{ vm.isoname }})
|
<a-icon type="usb" />
|
||||||
<a-avatar slot="avatar">
|
</a-avatar>
|
||||||
<a-icon type="usb" />
|
</div>
|
||||||
</a-avatar>
|
<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-meta>
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-list>
|
</a-list>
|
||||||
@ -42,59 +46,220 @@
|
|||||||
>
|
>
|
||||||
<a-list-item slot="renderItem" slot-scope="item">
|
<a-list-item slot="renderItem" slot-scope="item">
|
||||||
<a-list-item-meta>
|
<a-list-item-meta>
|
||||||
|
<div slot="avatar">
|
||||||
|
<a-avatar>
|
||||||
|
<a-icon type="hdd" />
|
||||||
|
</a-avatar>
|
||||||
|
</div>
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
<router-link :to="{ path: '/volume/' + item.id }">{{ item.name }}</router-link> ({{ item.type }}) <br/>
|
<router-link :to="{ path: '/volume/' + item.id }">{{ item.name }} </router-link>
|
||||||
<status :text="item.state" displayText /><br/>
|
<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>
|
||||||
|
<br/>
|
||||||
|
{{ $t('size') }}: {{ (item.size / (1024 * 1024 * 1024.0)).toFixed(2) }} GB<br/>
|
||||||
|
{{ $t('physicalsize') }}: {{ (item.physicalsize / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
|
||||||
|
{{ $t('storagePool') }}: {{ item.storage }} ({{ item.storagetype }})<br/>
|
||||||
|
<a-icon type="barcode"/> {{ item.id }} <br/>
|
||||||
</div>
|
</div>
|
||||||
<div slot="description">
|
|
||||||
<a-icon type="barcode"/> {{ item.id }}
|
|
||||||
</div>
|
|
||||||
<a-avatar slot="avatar">
|
|
||||||
<a-icon type="hdd" />
|
|
||||||
</a-avatar>
|
|
||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
<p>
|
<div slot="actions" class="actions">
|
||||||
Size: {{ (item.size / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
|
</div>
|
||||||
Physical Size: {{ (item.physicalsize / (1024 * 1024 * 1024.0)).toFixed(4) }} GB<br/>
|
|
||||||
Provisioning: {{ item.provisioningtype }}<br/>
|
|
||||||
Storage Pool: {{ item.storage }} ({{ item.storagetype }})<br/>
|
|
||||||
</p>
|
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-list>
|
</a-list>
|
||||||
|
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
|
||||||
<a-collapse-panel :header="'Network Adapter(s): ' + (vm && vm.nic ? vm.nic.length : 0)" key="3" >
|
<a-collapse-panel :header="'Network Adapter(s): ' + (vm && vm.nic ? vm.nic.length : 0)" key="3" >
|
||||||
|
<a-button type="primary" @click="showAddModal" :loading="loadingNic">
|
||||||
|
<a-icon type="plus"></a-icon> {{ $t('label.network.addVM') }}
|
||||||
|
</a-button>
|
||||||
<a-list
|
<a-list
|
||||||
size="small"
|
size="small"
|
||||||
itemLayout="horizontal"
|
itemLayout="horizontal"
|
||||||
:dataSource="vm.nic"
|
:dataSource="vm.nic"
|
||||||
|
class="list"
|
||||||
|
:loading="loadingNic"
|
||||||
>
|
>
|
||||||
<a-list-item slot="renderItem" slot-scope="item">
|
<a-list-item slot="renderItem" slot-scope="item" class="list__item">
|
||||||
<a-list-item-meta>
|
<a-list-item-meta>
|
||||||
<div slot="title">
|
<div slot="avatar">
|
||||||
<span v-show="item.isdefault">(Default) </span>
|
<a-avatar slot="avatar">
|
||||||
<router-link :to="{ path: '/guestnetwork/' + item.networkid }">{{ item.networkname }} </router-link><br/>
|
<a-icon type="wifi" />
|
||||||
Mac Address: {{ item.macaddress }}<br/>
|
</a-avatar>
|
||||||
<span v-if="item.ipaddress">Address: {{ item.ipaddress }} <br/></span>
|
<br/>
|
||||||
Netmask: {{ item.netmask }}<br/>
|
<a-popconfirm
|
||||||
Gateway: {{ item.gateway }}<br/>
|
title="Please confirm that you would like to make this NIC the default for this VM."
|
||||||
|
@confirm="setAsDefault(item)"
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
style="margin-top: 10px"
|
||||||
|
icon="arrow-right"
|
||||||
|
size="small"
|
||||||
|
shape="round" />
|
||||||
|
</a-popconfirm>
|
||||||
|
<br/>
|
||||||
|
<a-tooltip placement="right" v-if="item.type !== 'L2'">
|
||||||
|
<template slot="title">
|
||||||
|
{{ "Change IP Address" }}
|
||||||
|
</template>
|
||||||
|
<a-button
|
||||||
|
style="margin-top: 10px"
|
||||||
|
icon="swap"
|
||||||
|
size="small"
|
||||||
|
shape="round"
|
||||||
|
@click="editIpAddressNic = item.id; showUpdateIpModal = true" />
|
||||||
|
</a-tooltip>
|
||||||
|
<br/>
|
||||||
|
<a-tooltip placement="right" v-if="item.type !== 'L2'">
|
||||||
|
<template slot="title">
|
||||||
|
{{ "Manage Secondary IP Addresses" }}
|
||||||
|
</template>
|
||||||
|
<a-button
|
||||||
|
style="margin-top: 10px"
|
||||||
|
icon="environment"
|
||||||
|
size="small"
|
||||||
|
shape="round"
|
||||||
|
@click="fetchSecondaryIPs(item.id)" />
|
||||||
|
</a-tooltip>
|
||||||
|
<br/>
|
||||||
|
<a-popconfirm
|
||||||
|
:title="$t('message.network.removeNIC')"
|
||||||
|
@confirm="removeNIC(item)"
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
v-if="!item.isdefault"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
style="margin-top: 10px"
|
||||||
|
type="danger"
|
||||||
|
icon="delete"
|
||||||
|
size="small"
|
||||||
|
shape="round" />
|
||||||
|
</a-popconfirm>
|
||||||
</div>
|
</div>
|
||||||
<div slot="description">
|
<div slot="title">
|
||||||
|
<router-link :to="{ path: '/guestnetwork/' + item.networkid }">{{ item.networkname }} </router-link>
|
||||||
|
<a-tag v-if="item.isdefault">
|
||||||
|
{{ $t('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>
|
||||||
|
<br />
|
||||||
|
{{ $t('macaddress') }}: {{ item.macaddress }}<br/>
|
||||||
|
<span v-if="item.ipaddress">
|
||||||
|
{{ $t('IP Address') }}: {{ item.ipaddress }}
|
||||||
|
<br/>
|
||||||
|
</span>
|
||||||
|
<span v-if="item.secondaryip && item.type !== 'L2'">
|
||||||
|
{{ $t('Secondary IPs') }}: {{ item.secondaryip.map(x => x.ipaddress).join(', ') }}
|
||||||
|
<br/>
|
||||||
|
</span>
|
||||||
|
<span v-if="item.netmask">
|
||||||
|
{{ $t('netmask') }}: {{ item.netmask }}
|
||||||
|
<br/>
|
||||||
|
</span>
|
||||||
|
<span v-if="item.gateway">
|
||||||
|
{{ $t('gateway') }}: {{ item.gateway }}
|
||||||
|
<br/>
|
||||||
|
</span>
|
||||||
<a-icon type="barcode"/> {{ item.id }}
|
<a-icon type="barcode"/> {{ item.id }}
|
||||||
</div>
|
</div>
|
||||||
<a-avatar slot="avatar">
|
|
||||||
<a-icon type="wifi" />
|
|
||||||
</a-avatar>
|
|
||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
<p>
|
|
||||||
Type: {{ item.type }}<br/>
|
|
||||||
Broadcast URI: {{ item.broadcasturi }}<br/>
|
|
||||||
Isolation URI: {{ item.isolationuri }}<br/>
|
|
||||||
</p>
|
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-list>
|
</a-list>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
</a-collapse>
|
</a-collapse>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
:visible="showAddNetworkModal"
|
||||||
|
:title="$t('label.network.addVM')"
|
||||||
|
@cancel="closeModals"
|
||||||
|
@ok="submitAddNetwork">
|
||||||
|
{{ $t('message.network.addVM.desc') }}
|
||||||
|
|
||||||
|
<div class="modal-form">
|
||||||
|
<p class="modal-form__label">{{ $t('Network') }}:</p>
|
||||||
|
<a-select :defaultValue="addNetworkData.network" @change="e => addNetworkData.network === e">
|
||||||
|
<a-select-option
|
||||||
|
v-for="network in addNetworkData.allNetworks"
|
||||||
|
:key="network.id"
|
||||||
|
:value="network.id">
|
||||||
|
{{ network.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<p class="modal-form__label">{{ $t('publicip') }}:</p>
|
||||||
|
<a-input v-model="addNetworkData.ip"></a-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
:visible="showUpdateIpModal"
|
||||||
|
:title="$t('label.change.ipaddress')"
|
||||||
|
@cancel="closeModals"
|
||||||
|
@ok="submitUpdateIP"
|
||||||
|
>
|
||||||
|
{{ $t('message.network.updateIp') }}
|
||||||
|
|
||||||
|
<div class="modal-form">
|
||||||
|
<p class="modal-form__label">{{ $t('publicip') }}:</p>
|
||||||
|
<a-input v-model="editIpAddressValue"></a-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
:visible="showSecondaryIpModal"
|
||||||
|
:title="$t('label.acquire.new.secondary.ip')"
|
||||||
|
:footer="null"
|
||||||
|
:closable="false"
|
||||||
|
class="wide-modal"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
{{ $t('message.network.secondaryIP') }}
|
||||||
|
</p>
|
||||||
|
<a-divider />
|
||||||
|
<a-input placeholder="Enter new secondary IP address" v-model="newSecondaryIp"></a-input>
|
||||||
|
<div style="margin-top: 10px; display: flex; justify-content:flex-end;">
|
||||||
|
<a-button @click="submitSecondaryIP" type="primary" style="margin-right: 10px;">Add Secondary IP</a-button>
|
||||||
|
<a-button @click="closeModals">Close</a-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
<a-list itemLayout="vertical">
|
||||||
|
<a-list-item v-for="(ip, index) in secondaryIPs" :key="index">
|
||||||
|
<a-popconfirm
|
||||||
|
title="Release IP?"
|
||||||
|
@confirm="removeSecondaryIP(ip.id)"
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="danger"
|
||||||
|
shape="circle"
|
||||||
|
size="small"
|
||||||
|
icon="delete" />
|
||||||
|
{{ ip.ipaddress }}
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -120,12 +285,27 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
inject: ['parentFetchData'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
vm: {},
|
vm: {},
|
||||||
volumes: [],
|
volumes: [],
|
||||||
totalStorage: 0,
|
totalStorage: 0,
|
||||||
activeKey: ['1', '2', '3']
|
activeKey: ['1', '2', '3'],
|
||||||
|
showAddNetworkModal: false,
|
||||||
|
showUpdateIpModal: false,
|
||||||
|
showSecondaryIpModal: false,
|
||||||
|
addNetworkData: {
|
||||||
|
allNetworks: [],
|
||||||
|
network: '',
|
||||||
|
ip: ''
|
||||||
|
},
|
||||||
|
loadingNic: false,
|
||||||
|
editIpAddressNic: '',
|
||||||
|
editIpAddressValue: '',
|
||||||
|
secondaryIPs: [],
|
||||||
|
selectedNicId: '',
|
||||||
|
newSecondaryIp: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
@ -154,26 +334,339 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$set(this.resource, 'volumes', this.volumes)
|
this.$set(this.resource, 'volumes', this.volumes)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
listNetworks () {
|
||||||
|
api('listNetworks', {
|
||||||
|
listAll: 'true',
|
||||||
|
zoneid: this.vm.zoneid
|
||||||
|
}).then(response => {
|
||||||
|
this.addNetworkData.allNetworks = response.listnetworksresponse.network.filter(network => !this.vm.nic.map(nic => nic.networkid).includes(network.id))
|
||||||
|
this.addNetworkData.network = this.addNetworkData.allNetworks[0].id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetchSecondaryIPs (nicId) {
|
||||||
|
this.showSecondaryIpModal = true
|
||||||
|
this.selectedNicId = nicId
|
||||||
|
api('listNics', {
|
||||||
|
nicId: nicId,
|
||||||
|
keyword: '',
|
||||||
|
virtualmachineid: this.vm.id
|
||||||
|
}).then(response => {
|
||||||
|
this.secondaryIPs = response.listnicsresponse.nic[0].secondaryip
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showAddModal () {
|
||||||
|
this.showAddNetworkModal = true
|
||||||
|
this.listNetworks()
|
||||||
|
},
|
||||||
|
closeModals () {
|
||||||
|
this.showAddNetworkModal = false
|
||||||
|
this.showUpdateIpModal = false
|
||||||
|
this.showSecondaryIpModal = false
|
||||||
|
this.addNetworkData.network = ''
|
||||||
|
this.addNetworkData.ip = ''
|
||||||
|
this.editIpAddressValue = ''
|
||||||
|
this.newSecondaryIp = ''
|
||||||
|
},
|
||||||
|
submitAddNetwork () {
|
||||||
|
const params = {}
|
||||||
|
params.virtualmachineid = this.vm.id
|
||||||
|
params.networkid = this.addNetworkData.network
|
||||||
|
if (this.addNetworkData.ip) {
|
||||||
|
params.ipaddress = this.addNetworkData.ip
|
||||||
|
}
|
||||||
|
this.showAddNetworkModal = false
|
||||||
|
this.loadingNic = true
|
||||||
|
api('addNicToVirtualMachine', params).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.addnictovirtualmachineresponse.jobid,
|
||||||
|
successMessage: `Successfully added network`,
|
||||||
|
successMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.closeModals()
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
errorMessage: 'Adding network failed',
|
||||||
|
errorMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.closeModals()
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
loadingMessage: `Adding network...`,
|
||||||
|
catchMessage: 'Error encountered while fetching async job result',
|
||||||
|
catchMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.closeModals()
|
||||||
|
this.parentFetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: `Error ${error.response.status}`,
|
||||||
|
description: error.response.data.errorresponse.errortext
|
||||||
|
})
|
||||||
|
this.loadingNic = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setAsDefault (item) {
|
||||||
|
this.loadingNic = true
|
||||||
|
api('updateDefaultNicForVirtualMachine', {
|
||||||
|
virtualmachineid: this.vm.id,
|
||||||
|
nicid: item.id
|
||||||
|
}).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.updatedefaultnicforvirtualmachineresponse.jobid,
|
||||||
|
successMessage: `Successfully set ${item.networkname} to default. Please manually update the default NIC on the VM now.`,
|
||||||
|
successMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
errorMessage: `Error setting ${item.networkname} to default`,
|
||||||
|
errorMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
loadingMessage: `Setting ${item.networkname} to default...`,
|
||||||
|
catchMessage: 'Error encountered while fetching async job result',
|
||||||
|
catchMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.parentFetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: `Error ${error.response.status}`,
|
||||||
|
description: error.response.data.errorresponse.errortext
|
||||||
|
})
|
||||||
|
this.loadingNic = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitUpdateIP () {
|
||||||
|
this.loadingNic = true
|
||||||
|
this.showUpdateIpModal = false
|
||||||
|
api('updateVmNicIp', {
|
||||||
|
nicId: this.editIpAddressNic,
|
||||||
|
ipaddress: this.editIpAddressValue
|
||||||
|
}).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.updatevmnicipresponse.jobid,
|
||||||
|
successMessage: `Successfully updated IP Address`,
|
||||||
|
successMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.closeModals()
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
errorMessage: `Error`,
|
||||||
|
errorMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.closeModals()
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
loadingMessage: `Updating IP Address...`,
|
||||||
|
catchMessage: 'Error encountered while fetching async job result',
|
||||||
|
catchMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.closeModals()
|
||||||
|
this.parentFetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: `Error ${error.response.status}`,
|
||||||
|
description: error.response.data.errorresponse.errortext
|
||||||
|
})
|
||||||
|
this.loadingNic = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeNIC (item) {
|
||||||
|
this.loadingNic = true
|
||||||
|
|
||||||
|
api('removeNicFromVirtualMachine', {
|
||||||
|
nicid: item.id,
|
||||||
|
virtualmachineid: this.vm.id
|
||||||
|
}).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.removenicfromvirtualmachineresponse.jobid,
|
||||||
|
successMessage: `Successfully removed`,
|
||||||
|
successMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
errorMessage: `There was an error`,
|
||||||
|
errorMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
loadingMessage: `Removing NIC...`,
|
||||||
|
catchMessage: 'Error encountered while fetching async job result',
|
||||||
|
catchMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.parentFetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: `Error ${error.response.status}`,
|
||||||
|
description: error.response.data.errorresponse.errortext
|
||||||
|
})
|
||||||
|
this.loadingNic = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitSecondaryIP () {
|
||||||
|
this.loadingNic = true
|
||||||
|
|
||||||
|
const params = {}
|
||||||
|
params.nicid = this.selectedNicId
|
||||||
|
if (this.newSecondaryIp) {
|
||||||
|
params.ipaddress = this.newSecondaryIp
|
||||||
|
}
|
||||||
|
|
||||||
|
api('addIpToNic', params).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.addiptovmnicresponse.jobid,
|
||||||
|
successMessage: `Successfully added secondary IP Address`,
|
||||||
|
successMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
errorMessage: `There was an error adding the secondary IP Address`,
|
||||||
|
errorMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
loadingMessage: `Add Secondary IP address...`,
|
||||||
|
catchMessage: 'Error encountered while fetching async job result',
|
||||||
|
catchMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
this.parentFetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: `Error ${error.response.status}`,
|
||||||
|
description: error.response.data.addiptovmnicresponse.errortext
|
||||||
|
})
|
||||||
|
this.loadingNic = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeSecondaryIP (id) {
|
||||||
|
this.loadingNic = true
|
||||||
|
|
||||||
|
api('removeIpFromNic', { id }).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.removeipfromnicresponse.jobid,
|
||||||
|
successMessage: `Successfully removed secondary IP Address`,
|
||||||
|
successMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
errorMessage: `There was an error removing the secondary IP Address`,
|
||||||
|
errorMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
this.parentFetchData()
|
||||||
|
},
|
||||||
|
loadingMessage: `Removing Secondary IP address...`,
|
||||||
|
catchMessage: 'Error encountered while fetching async job result',
|
||||||
|
catchMethod: () => {
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
this.parentFetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: `Error ${error.response.status}`,
|
||||||
|
description: error.response.data.errorresponse.errortext
|
||||||
|
})
|
||||||
|
this.loadingNic = false
|
||||||
|
this.fetchSecondaryIPs(this.selectedNicId)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="scss" scoped>
|
||||||
.page-header-wrapper-grid-content-main {
|
.page-header-wrapper-grid-content-main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
.vm-detail {
|
.vm-detail {
|
||||||
.svg-inline--fa {
|
.svg-inline--fa {
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
@media (min-width: 760px) {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&--no-margin {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
margin-left: -24px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 760px) {
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 24px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
span {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
}
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wide-modal {
|
||||||
|
min-width: 50vw;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -19,23 +19,24 @@
|
|||||||
<a-row :gutter="24">
|
<a-row :gutter="24">
|
||||||
<a-col :md="24">
|
<a-col :md="24">
|
||||||
<a-card class="breadcrumb-card">
|
<a-card class="breadcrumb-card">
|
||||||
<a-col :md="14">
|
<a-col :md="24" style="display: flex">
|
||||||
<breadcrumb style="padding-top: 6px" />
|
<breadcrumb style="padding-top: 6px" />
|
||||||
</a-col>
|
|
||||||
<a-col :md="10">
|
|
||||||
<a-button
|
<a-button
|
||||||
style="margin-left: 10px; float: right"
|
style="margin-left: 12px; margin-top: 4px"
|
||||||
@click="fetchData()"
|
|
||||||
icon="reload"
|
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
type="primary">
|
icon="reload"
|
||||||
{{ $t('Refresh') }}
|
size="small"
|
||||||
|
shape="round"
|
||||||
|
@click="fetchData()" >
|
||||||
|
{{ $t('refresh') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
style="margin-left: 10px; float: right"
|
style="margin-left: 12px; margin-top: 4px"
|
||||||
@click="sslFormVisible = true"
|
icon="safety-certificate"
|
||||||
icon="safety-certificate">
|
size="small"
|
||||||
{{ $t('SSL Certificate') }}
|
shape="round"
|
||||||
|
@click="sslFormVisible = true">
|
||||||
|
{{ $t('Setup SSL Certificate') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-modal
|
<a-modal
|
||||||
:title="$t('SSL Certificate')"
|
:title="$t('SSL Certificate')"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user