| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- <template>
- <div class="disk-wrapper d-flex w-auto">
- <a-form-item :wrapperCol="{ span: 24 }" :validate-status="storageStatusMap.type">
- <a-tag color="blue" v-if="diskTypeLabel && !disabled">{{ diskTypeLabel }}</a-tag>
- <a-select v-else v-decorator="decorator.type" labelInValue :style="{minWidth: '300px'}" @change="typeChange" :disabled="disabled || imageType === 'snapshot'">
- <a-select-option v-for="(item, key) of typesMap" :key="key" :value="key">{{ item.label }}</a-select-option>
- </a-select>
- </a-form-item>
- <a-form-item class="mx-1" :wrapperCol="{ span: 24 }">
- <a-tooltip :title="tooltip" placement="top">
- <disk-size-input
- v-decorator="decorator.size"
- :step="10"
- :min="minSize"
- :max="max"
- :normalizeGb="normalizeDiskSizeGb"
- :disabled="sizeDisabled || (imageType === 'backup' || imageType === 'snapshot')" />
- </a-tooltip>
- </a-form-item>
- <!-- 高级 -->
- <template v-if="showAdvanced">
- <!-- 快照和挂载点不能共存 -->
- <template v-if="!showMountpoint && has('snapshot') && !disabled && imageType !== 'backup' && imageType !== 'snapshot'">
- <a-form-item v-if="showSnapshot" class="mx-1" :wrapperCol="{ span: 24 }">
- <base-select
- v-decorator="decorator.snapshot"
- resource="snapshots"
- :params="snapshotsParams"
- :item.sync="snapshotObj"
- :select-props="{ placeholder: $t('compute.text_124') }" />
- </a-form-item>
- <a-button class="mt-1" type="link" v-show="!simplify" @click="() => showSnapshot = !showSnapshot">{{ showSnapshot ? $t('compute.text_135') : $t('compute.text_133') }}</a-button>
- </template>
- <template v-if="!showSnapshot && has('mount-point') && !disabled && imageType !== 'backup' && imageType !== 'snapshot'">
- <disk-mountpoint
- class="mx-1"
- v-if="showMountpoint"
- :decorators="{ filetype: decorator.filetype, mountPath: decorator.mountPath }" />
- <a-button class="mt-1" type="link" @click="() => showMountpoint = !showMountpoint">{{ showMountpoint ? $t('compute.text_135') : $t('compute.text_134') }}</a-button>
- </template>
- <template v-if="has('schedtag') && !showStorage && !isStorageShow && imageType !== 'backup' && imageType !== 'snapshot'">
- <schedtag-policy v-if="showSchedtag" :form="form" :decorators="{ schedtag: decorator.schedtag, policy: decorator.policy }" :schedtag-params="schedtagParams" :policyReactInSchedtag="false" />
- <a-button v-if="!disabled" v-show="!simplify" class="mt-1" type="link" @click="() => showSchedtag = !showSchedtag">{{ showSchedtag ? $t('compute.text_135') : $t('compute.text_1315') }}</a-button>
- </template>
- <template v-if="has('storage') && !showSchedtag && imageType !== 'snapshot'">
- <storage style="min-width: 480px; max-width: 500px;" :diskKey="diskKey" :decorators="decorator" :storageParams="storageParams" v-if="showStorage" :form="form" :storageHostParams="storageHostParams" @storageHostChange="(val) => $emit('storageHostChange', val)" />
- <a-button v-if="!disabled" class="mt-1" type="link" @click="storageShowClick">{{ showStorage ? $t('compute.text_135') : $t('compute.text_1350') }}</a-button>
- </template>
- <!-- 关机重置 -->
- <a-form-item v-if="isAutoResetShow">
- <a-checkbox v-decorator="decorator.auto_reset">{{ $t('compute.shutdown_auto_reset') }}</a-checkbox>
- </a-form-item>
- <template v-if="isVMware && imageType !== 'backup' && imageType !== 'snapshot'">
- <a-form-item class="mx-1" :wrapperCol="{ span: 24 }">
- <base-select
- v-if="showPreallocation"
- v-decorator="decorator.preallocation"
- :options="preallocationOptions"
- :select-props="{ allowClear: true, placeholder: $t('common.select') }" />
- </a-form-item>
- <a-button v-if="!disabled" class="mt-1" type="link" @click="preallocationShowClick">{{ showPreallocation ? $t('compute.text_135') : $t('compute.assign_preallocation') }}</a-button>
- </template>
- <!-- iops 创建时可设置,修改时禁用 -->
- <template v-if="has('iops') && !disabled && isIopsShow">
- <a-form-item>
- <a-tooltip :title="iopsTooltip" placement="top">
- <a-input-number
- v-if="showIops"
- v-decorator="decorator.iops"
- placeholder="IOPS"
- :min="iopsLimit.min"
- :max="iopsLimit.max"
- :precision="0" />
- </a-tooltip>
- </a-form-item>
- <a-button class="mt-1" type="link" @click="() => changeIopsShow(!showIops)">{{ showIops ? $t('compute.text_135') : $t('compute.set_iops') }}</a-button>
- </template>
- <!-- throughput 创建时可设置,修改时禁用 -->
- <template v-if="has('throughput') && !disabled && isThroughputShow">
- <a-form-item>
- <a-tooltip title="125 ~ 1000MiB/s" placement="top">
- <a-input-number
- v-if="showThroughput"
- v-decorator="decorator.throughput"
- :placeholder="$t('compute.throughput')"
- :min="125"
- :max="1000"
- :precision="0" />
- </a-tooltip>
- </a-form-item>
- <a-button class="mt-1" type="link" @click="() => changeThroughputShow(!showThroughput)">{{ showThroughput ? $t('compute.text_135') : $t('compute.set_throughput') }}</a-button>
- </template>
- </template>
- <template v-if="has('iops') && disabled && isIopsShow && defaultIops && iamgeType !== 'backup' && imageType !== 'snapshot'">
- <span class="ml-2">{{ $t('compute.iops') }}: {{ defaultIops }}</span>
- </template>
- <template v-if="has('throughput') && disabled && isThroughputShow && defaultThroughput && imageType !== 'backup' && imageType !== 'snapshot'">
- <span class="ml-2">{{ $t('compute.throughput') }}: {{ defaultThroughput }}</span>
- </template>
- <!-- 磁盘容量预警信息提示 -->
- <a-tooltip v-if="storageStatusMap.tooltip">
- <template slot="title">
- <div slot="help">{{ storageStatusMap.tooltip }}</div>
- </template>
- <a-icon type="exclamation-circle" class="storage-icon" :class="storageClass" />
- </a-tooltip>
- <a-button v-if="!disabled && hasAdvanced" class="mt-1" type="link" @click="() => showAdvanced = !showAdvanced">{{ showAdvanced ? $t('compute.hide_advanced') : $t('compute.advanced') }}</a-button>
- </div>
- </template>
- <script>
- import * as R from 'ramda'
- import { PREALLOCATION_OPTIONS } from '@Compute/constants'
- import { HYPERVISORS_MAP } from '@/constants'
- import SchedtagPolicy from '@/sections/SchedtagPolicy'
- import DiskMountpoint from '@/sections/DiskMountpoint'
- import DiskSizeInput from '@/sections/DiskSizeInput'
- import { diskSupportTypeMedium } from '@/utils/common/hypervisor'
- import Storage from './components/Storage'
- export default {
- name: 'Disk',
- components: {
- SchedtagPolicy,
- DiskMountpoint,
- Storage,
- DiskSizeInput,
- },
- props: {
- diskKey: String,
- decorator: {
- type: Object,
- required: true,
- validator: val => val.type && val.size,
- },
- typesMap: {
- type: Object,
- default: () => ({}),
- },
- hypervisor: {
- type: String,
- },
- min: {
- type: Number,
- required: true,
- },
- max: {
- type: Number,
- required: true,
- },
- elements: {
- type: Array,
- required: true,
- },
- diskTypeLabel: {
- type: String,
- default: '',
- },
- disabled: {
- type: Boolean,
- default: false,
- },
- simplify: {
- type: Boolean,
- default: false,
- },
- sizeDisabled: { // 磁盘大小的限制
- type: Boolean,
- default: false,
- },
- snapshotsParams: {
- type: Object,
- default: () => ({
- with_meta: true,
- cloud_env: 'onpremise',
- limit: 0,
- }),
- },
- schedtagParams: {
- type: Object,
- default: () => ({
- with_meta: true,
- cloud_env: 'onpremise',
- resource_type: 'storages',
- limit: 0,
- }),
- },
- storageStatusMap: {
- type: Object,
- default: () => ({}),
- },
- form: {
- type: Object,
- validator: val => !val || val.fc, // 不传 或者 传就有fc
- },
- storageParams: {
- type: Object,
- },
- storageHostParams: Object,
- isStorageShow: {
- type: Boolean,
- default: false,
- },
- isIopsShow: {
- type: Boolean,
- default: false,
- },
- isThroughputShow: {
- type: Boolean,
- default: false,
- },
- iopsLimit: {
- type: Object,
- default: () => ({ min: 0 }),
- },
- isAutoResetShow: {
- type: Boolean,
- default: false,
- },
- defaultIops: {
- type: Number,
- default: 0,
- },
- defaultThroughput: {
- type: Number,
- default: 0,
- },
- imageType: {
- type: String,
- },
- },
- data () {
- return {
- showSchedtag: false,
- showMountpoint: false,
- showSnapshot: false,
- showStorage: false,
- showIops: false,
- showThroughput: false,
- showPreallocation: false,
- snapshotObj: {},
- preallocationOptions: PREALLOCATION_OPTIONS.filter(item => item.value !== 'off').map(item => {
- return {
- id: item.value,
- name: item.label,
- }
- }),
- showAdvanced: false,
- }
- },
- computed: {
- tooltip () {
- return this.$t('compute.text_137', [this.minSize, this.max])
- },
- iopsTooltip () {
- if (this.iopsLimit.min && this.iopsLimit.max) {
- return `${this.iopsLimit.min} ~ ${this.iopsLimit.max}`
- }
- return ''
- },
- minSize () {
- let snapshotSize = this.snapshotObj.size || 0
- if (R.is(Number, snapshotSize)) {
- snapshotSize = snapshotSize / 1024
- }
- return Math.max(this.min, snapshotSize)
- },
- storageClass () {
- return `${this.storageStatusMap.type}-color`
- },
- isVMware () {
- return this.hypervisor === HYPERVISORS_MAP.esxi.key
- },
- hasAdvanced () {
- return this.has('snapshot') || this.has('mount-point') || this.has('schedtag') || this.has('storage') || this.has('iops') || this.has('throughput') || this.isAutoResetShow || this.isVMware
- },
- },
- watch: {
- 'snapshotObj.size' (val) {
- if (val) {
- const size = val / 1024
- this.$emit('snapshotChange', size)
- }
- },
- showStorage (v) {
- this.$emit('showStorageChange', v)
- },
- elements (val, oldV) {
- if (!R.equals(val, oldV)) this.init()
- },
- },
- methods: {
- normalizeDiskSizeGb (gb) {
- let num = gb
- if (this.hypervisor === HYPERVISORS_MAP.qcloud.key) {
- num = Math.floor(num / 10) * 10
- }
- return num
- },
- initData (data, hyper) {
- setTimeout(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.type[0]]: { key: diskSupportTypeMedium(hyper) ? `${data.backend}/${data.medium}` : data.backend, label: '' },
- [this.decorator.size[0]]: data.size / 1024,
- })
- if (data.schedtags || data.storage_id || data.auto_reset || data.iops || data.throughput || data.preallocation) {
- this.showAdvanced = true
- if (data.schedtags && data.schedtags.length) {
- this.showSchedtag = true
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.schedtag[0]]: data.schedtags[0].id,
- [this.decorator.policy[0]]: data.schedtags[0].strategy,
- })
- })
- }
- if (data.storage_id) {
- this.showStorage = true
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.storage[0]]: data.storage_id,
- })
- })
- }
- if (data.auto_reset) {
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.auto_reset[0]]: data.auto_reset,
- })
- })
- }
- if (data.iops) {
- this.showIops = true
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.iops[0]]: data.iops,
- })
- })
- }
- if (data.throughput) {
- this.showThroughput = true
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.throughput[0]]: data.throughput,
- })
- })
- }
- if (data.preallocation) {
- this.showPreallocation = true
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- [this.decorator.preallocation[0]]: data.preallocation,
- })
- })
- }
- }
- }, 1000)
- },
- setValues (values) {
- for (const key in values) {
- this[key] = values[key]
- }
- },
- has (element) {
- return this.elements.includes(element)
- },
- parser (value) {
- value = String(value)
- return value.replace(/[GB]*/g, '')
- },
- formatter (num) {
- const n = this.parser(num)
- if (this.hypervisor === HYPERVISORS_MAP.qcloud.key) {
- num = Math.floor(num / 10) * 10
- }
- return `${n}GB`
- },
- typeChange (val) {
- this.$emit('diskTypeChange', val)
- if (this.showStorage) {
- this.$emit('storageHostChange', { disk: this.diskKey, storageHosts: [] })
- }
- this.snapshotObj = {}
- },
- init () {
- this.showSchedtag = false
- this.showMountpoint = false
- this.showSnapshot = false
- this.showStorage = false
- this.snapshotObj = {}
- },
- formatterLabel (row) {
- return row.description ? `${row.name} / ${row.description}` : row.name
- },
- storageShowClick () {
- if (this.showStorage) {
- this.$emit('storageHostChange', { disk: this.diskKey, storageHosts: [] })
- }
- this.showStorage = !this.showStorage
- },
- preallocationShowClick () {
- this.showPreallocation = !this.showPreallocation
- if (this.isVMware) {
- const systemDiskPreallocation = this.form.fd.systemDiskPreallocation
- this.$nextTick(() => {
- if (this.diskKey !== 'system') {
- this.form.fc.setFieldsValue({
- [`dataDiskPreallocation[${this.diskKey}]`]: systemDiskPreallocation,
- })
- }
- })
- }
- },
- changeIopsShow (show) {
- this.showIops = show
- },
- changeThroughputShow (show) {
- this.showThroughput = show
- },
- },
- }
- </script>
- <style lang="less" scoped>
- .disk-wrapper{
- .storage-icon{
- position: relative;
- top: 12px;
- margin-left: 10px;
- }
- }
- </style>
|