| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697 |
- <template>
- <div>
- <page-header :title="$t('k8s.text_146')" />
- <a-alert :showIcon="true" type="info" banner class="mt-2">
- <template slot="message">
- <div>
- <p>{{$t('k8s.text_147')}}</p>
- <p>{{$t('k8s.text_148')}}</p>
- <p>{{$t('k8s.text_149')}}</p>
- </div>
- </template>
- </a-alert>
- <a-alert :showIcon="true" type="error" v-if="!preCheckResp.pass">
- <template slot="message" v-if="showDocsLink()">
- <div>
- {{$t('k8s.provider_image_not_prepared')}}
- <help-link :href="docs[provider.hypervisor]">{{$t('k8s.ref_prepare_doc')}}</help-link>
- </div>
- </template>
- </a-alert>
- <page-body needMarginBottom>
- <a-form
- class="mt-3"
- :form="form.fc">
- <a-form-item
- :label="$t('k8s.text_412')"
- v-bind="formItemLayout">
- <base-select
- v-if="$store.getters.isAdminMode"
- v-decorator="decorators.project_domain_id"
- resource="domains"
- version="v1"
- :params="params.domain"
- @change="domainChange"
- is-default-select
- filterable />
- <div v-else>{{ $store.getters.userInfo.projectDomain }}</div>
- </a-form-item>
- <a-form-item
- :label="$t('k8s.platform')"
- v-bind="formItemLayout">
- <a-radio-group
- v-decorator="decorators.provider(provider)"
- v-if="providers.length"
- @change="providerChange">
- <a-radio-button v-for="item in providers" :key="item.value" :value="item">
- {{ item.label }}
- </a-radio-button>
- </a-radio-group>
- <div v-else>{{ $t('common_467') }}</div>
- </a-form-item>
- <a-form-item :label="$t('k8s.region')" class="mb-0" v-bind="formItemLayout" v-if="provider.brand">
- <cloudregion-vpc
- :cloudregion-params="cloudregionParams"
- :vpc-params="params.vpcParams"
- :decorator="decorators.regionVpc" />
- </a-form-item>
- <a-form-item
- :label="$t('k8s.text_41')"
- v-bind="formItemLayout">
- <a-input v-decorator="decorators.name" :placeholder="$t('validator.serverName')" />
- </a-form-item>
- <a-form-item :label="$t('k8s.text_152')" v-if="cloudregionId" v-bind="formItemLayout">
- <server-config
- :form="form"
- :cloudregionId="cloudregionId"
- :decorator="decorators.serverConfig"
- :hypervisor="hypervisor"
- :platform="platform"
- :networkParams="params.network" />
- </a-form-item>
- <a-form-item :label="$t('k8s.text_153')" v-bind="formItemLayout">
- <base-select
- v-decorator="decorators.version"
- :options="k8sVersionOps"
- :filterable="true"
- :select-props="{ placeholder: $t('k8s.text_154') }" />
- </a-form-item>
- <!-- <a-form-item :label="$t('k8s.text_155')" v-bind="formItemLayout" v-if="isAdminMode">
- <a-switch :checkedChildren="$t('k8s.text_156')" :unCheckedChildren="$t('k8s.text_157')" v-decorator="decorators.is_public" />
- </a-form-item> -->
- <a-form-item :label="$t('k8s.text_158')" v-bind="formItemLayout">
- <a-switch :checkedChildren="$t('k8s.text_156')" :unCheckedChildren="$t('k8s.text_157')" v-decorator="decorators.isConfigImage" @change="isConfigImageChange" />
- </a-form-item>
- <a-form-item
- v-if="isConfigImage"
- :label="$t('k8s.text_52')"
- v-bind="formItemLayout"
- :extra="$t('k8s.text_159')">
- <a-input v-decorator="decorators.image_repository_url" :placeholder="$t('k8s.text_160')" />
- </a-form-item>
- <a-form-item v-if="isConfigImage" :wrapper-col="{ span: 20, offset: 3 }">
- <a-checkbox v-decorator="decorators.image_repository_insecure">{{$t('k8s.text_161')}}</a-checkbox>
- </a-form-item>
- </a-form>
- </page-body>
- <page-footer>
- <div slot="right">
- <a-button class="mr-2" type="primary" @click="handleConfirm" :loading="loading">{{$t('common.create')}}</a-button>
- <a-button @click="cancel">{{ $t('dialog.cancel') }}</a-button>
- </div>
- </page-footer>
- </div>
- </template>
- <script>
- /* import * as R from 'ramda' */
- import { mapGetters } from 'vuex'
- import { HYPERVISORS_MAP } from '@/constants'
- import { IMAGES_TYPE_MAP } from '@/constants/compute'
- import { DOCS_MAP, showDocsLink } from '@/constants/docs'
- import ServerConfig from '@K8S/sections/serverConfig'
- import CloudregionVpc from '@/sections/CloudregionVpc'
- import { isWithinRange, isRequired } from '@/utils/validate'
- import { findPlatform } from '@/utils/common/hypervisor'
- import i18n from '@/locales'
- import { KUBE_PROVIDER, K8S_HYPERVISORS_MAP } from '../constants'
- function checkIpInSegment (i, networkData) {
- return (rule, value, _callback) => {
- const isIn = isWithinRange(value, networkData.guest_ip_start, networkData.guest_ip_end)
- if (isIn) {
- _callback()
- } else {
- _callback(this.$t('k8s.text_163'))
- }
- }
- }
- export default {
- name: 'ClusterCreate',
- components: {
- CloudregionVpc,
- ServerConfig,
- },
- data () {
- return {
- showDocsLink,
- loading: false,
- providers: [],
- provider: {},
- cloudregionId: '',
- capability: {},
- preCheckResp: {
- pass: true,
- },
- docs: DOCS_MAP.cluster(),
- form: {
- fc: this.$form.createForm(this, {
- onValuesChange: (props, values) => {
- if (values.vpc && values.vpc.key) {
- this.params.network = {
- vpc: values.vpc.key,
- filter: 'server_type.notin(ipmi, pxe)',
- scope: this.scope,
- }
- }
- if (values.cloudregion && values.cloudregion.key) {
- this.cloudregionId = values.cloudregion.key
- }
- Object.keys(values).forEach((key) => {
- this.form.fd[key] = values[key]
- })
- },
- }),
- fi: {
- /* hypervisors: ['kvm'], */
- /* capability: {}, */
- },
- fd: {
- /* hypervisor: hyperOpts[0].value, */
- project_domain_id: this.$store.getters.projectDomainId,
- },
- },
- decorators: {
- project_domain_id: [
- 'project_domain_id',
- {
- rules: [
- { required: true, message: this.$t('k8s.text_413') },
- ],
- },
- ],
- provider: defaultProvider => [
- 'provider',
- {
- initialValue: defaultProvider,
- rules: [
- { required: true, message: this.$t('k8s.text_164') },
- ],
- },
- ],
- regionVpc: {
- cloudregion: [
- 'cloudregion',
- {
- initialValue: { key: '', label: '' },
- rules: [
- { required: true, message: this.$t('k8s.text_165') },
- ],
- },
- ],
- vpc: [
- 'vpc',
- {
- initialValue: { key: '', label: '' },
- rules: [
- { required: true, message: this.$t('k8s.text_165') },
- ],
- },
- ],
- },
- name: [
- 'name',
- {
- validateTrigger: 'blur',
- rules: [
- { required: true, message: this.$t('k8s.text_60') },
- { validator: this.$validate('serverName') },
- ],
- },
- ],
- serverConfig: {
- network: i => [
- `network[${i}]`,
- {
- rules: [
- { required: true, message: this.$t('k8s.text_122') },
- ],
- },
- ],
- ip: (i, networkData) => [
- `ip[${i}]`,
- {
- validateFirst: true,
- validateTrigger: ['blur', 'change'],
- rules: [{
- required: true,
- message: this.$t('k8s.text_169'),
- }, {
- validator: checkIpInSegment(i, networkData),
- }],
- },
- ],
- sku: i => [
- `sku[${i}]`,
- {
- rules: [
- { validator: isRequired(true, 'id'), message: this.$t('compute.text_216') },
- ],
- },
- ],
- imageOS: i => [
- `imageOS[${i}]`,
- {
- os: [
- `os[${i}]`,
- {
- initialValue: '',
- rules: [
- { required: true, message: i18n.t('compute.text_153') },
- ],
- },
- ],
- image: [
- `image[${i}]`,
- {
- initialValue: { key: '', label: '' },
- rules: [
- { validator: isRequired(), message: i18n.t('compute.text_214') },
- ],
- },
- ],
- imageType: [
- `imageType[${i}]`,
- {
- initialValue: IMAGES_TYPE_MAP.standard.key,
- },
- ],
- },
- ],
- /*
- * vcpu_count: i => [
- * `vcpu_count[${i}]`,
- * {
- * initialValue: 4,
- * rules: [
- * { required: true, message: this.$t('k8s.text_99') },
- * { validator: this.validator('vcpu_count') },
- * ],
- * },
- * ],
- * vmem_size: i => [
- * `vmem_size[${i}]`,
- * {
- * initialValue: 4,
- * rules: [
- * { required: true, message: this.$t('k8s.text_167') },
- * { validator: this.validator('vmem_size') },
- * ],
- * },
- * ],
- */
- disk: i => ({
- type: [
- `systemDiskType[${i}]`,
- {
- rules: [
- { validator: isRequired(), message: this.$t('compute.text_121') },
- ],
- },
- ],
- size: [
- `systemDiskSize[${i}]`,
- {
- rules: [
- { required: true, message: this.$t('compute.text_122') },
- ],
- },
- ],
- schedtag: [
- `systemDiskSchedtag[${i}]`,
- {
- validateTrigger: ['change', 'blur'],
- rules: [{
- required: true,
- message: this.$t('compute.text_123'),
- }],
- },
- ],
- policy: [
- `systemDiskPolicy[${i}]`,
- {
- validateTrigger: ['blur', 'change'],
- rules: [{
- required: true,
- message: this.$t('compute.text_123'),
- }],
- },
- ],
- }),
- num: i => [
- `num[${i}]`,
- {
- initialValue: 1,
- rules: [
- { required: true, message: this.$t('k8s.text_170') },
- ],
- },
- ],
- role: i => [
- `role[${i}]`,
- {
- initialValue: 'controlplane',
- rules: [
- { required: true },
- ],
- },
- ],
- },
- version: [
- 'version',
- ],
- is_public: [
- 'is_public',
- {
- valuePropName: 'checked',
- initialValue: false,
- },
- ],
- isConfigImage: [
- 'isConfigImage',
- {
- valuePropName: 'checked',
- initialValue: false,
- },
- ],
- image_repository_url: [
- 'image_repository_url',
- {
- rules: [
- { required: true, message: this.$t('k8s.text_53') },
- ],
- },
- ],
- image_repository_insecure: [
- 'image_repository_insecure',
- {
- valuePropName: 'checked',
- initialValue: true,
- },
- ],
- },
- isConfigImage: false,
- formItemLayout: {
- wrapperCol: {
- md: { span: 18 },
- xl: { span: 20 },
- xxl: { span: 22 },
- },
- labelCol: {
- md: { span: 6 },
- xl: { span: 4 },
- xxl: { span: 2 },
- },
- },
- params: {
- vpcParams: {
- usable: true,
- show_emulated: true,
- order_by: 'created_at',
- order: 'asc',
- scope: this.scope,
- 'filter.0': 'external_access_mode.in(eip,eip-distgw)',
- },
- network: {},
- k8sVersions: () => {
- return {
- provider: this.hypervisor || KUBE_PROVIDER,
- resource_type: 'guest',
- }
- },
- domain: {
- scope: this.$store.getters.scope,
- limit: 0,
- },
- },
- k8sVersionOps: [],
- }
- },
- provide () {
- return {
- form: this.form,
- }
- },
- computed: {
- ...mapGetters(['userInfo', 'scope', 'isAdminMode', 'isDomainMode']),
- cloudregionParams () {
- const provider = this.provider
- /* const type = findPlatform(provider, 'hypervisor') */
- const param = {
- usable: true,
- usable_vpc: true,
- project_domain: this.form.fd.project_domain_id,
- brand: provider.brand,
- }
- /*
- * switch (type) {
- * case 'idc':
- * param = { cloud_env: 'onpremise' }
- * break
- * case 'public':
- * param = { cloud_env: 'public' }
- * break
- * case 'private':
- * param = { cloud_env: 'private', show_emulated: true }
- * break
- * default :
- * param = { is_on_premise: true }
- * }
- */
- return param
- },
- hypervisor () {
- return this.provider.hypervisor
- },
- platform () {
- return findPlatform(this.hypervisor, 'hypervisor')
- },
- },
- created () {
- this.clustersM = new this.$Manager('kubeclusters', 'v1')
- this.form.fc.getFieldDecorator('cloudregion', { preserve: true })
- /* this.form.fc.getFieldDecorator('zone', { preserve: true }) */
- this.isDomainMode && this.fetchCapability(this.userInfo.projectDomainId)
- },
- methods: {
- /*
- * async fetchCapability (id, resource) {
- * const params = {
- * show_emulated: true,
- * resource_type: 'shared',
- * scope: this.scope,
- * }
- * const capabilityParams = { id, spec: 'capability', params }
- * if (!id) return
- * this.capabilityParams = capabilityParams
- * try {
- * const { data } = await new this.$Manager(`${resource}s`).getSpecific(this.capabilityParams)
- * let hypervisors = R.is(Object, data) ? (data.hypervisors || []) : []
- * if (hypervisors.includes(HYPERVISORS_MAP.kvm.key)) { // kvm 排序为第一个
- * hypervisors = [HYPERVISORS_MAP.kvm.key].concat(hypervisors).filter(val => val !== 'baremetal')
- * }
- * hypervisors = Array.from(new Set(hypervisors))
- * this.form.fi.hypervisors = hypervisors
- * this.form.fi.capability = data
- * } catch (error) {
- * throw error
- * }
- * },
- */
- domainChange (val) {
- this.form.fd.project_domain_id = val
- this.fetchCapability(val)
- },
- fetchCapability (domainId) {
- new this.$Manager('capabilities', 'v2').list({
- params: {
- domain: domainId,
- scope: this.scope,
- },
- }).then(({ data }) => {
- this.capability = data.data[0]
- this.updateProviders(this.capability)
- })
- },
- updateProviders (capability) {
- const brands = capability.brands || []
- const providers = Object.entries(K8S_HYPERVISORS_MAP).filter(item => {
- const itemProvider = item[1].provider
- return brands.includes(itemProvider)
- }).map(item => item[1])
- this.providers = providers
- if (this.providers.length > 0) {
- // set default provider
- this.provider = this.providers[0]
- this.preCheckK8sProvider(this.provider)
- }
- },
- providerChange (e) {
- this.provider = e.target.value
- this.cloudregionId = ''
- this.preCheckK8sProvider(this.provider)
- /*
- * const type = findPlatform(provider, 'hypervisor')
- * let param = {
- * usable: true,
- * project_domain: this.form.fd.project_domain_id,
- * brand: provider.brand,
- * }
- * switch (type) {
- * case 'idc':
- * param = { cloud_env: 'onpremise' }
- * break
- * case 'public':
- * param = { cloud_env: 'public' }
- * break
- * case 'private':
- * param = { cloud_env: 'private', show_emulated: true }
- * break
- * default :
- * param = { is_on_premise: true }
- * }
- * this.params.cloudregion = {
- * ...this.params.cloudregion,
- * ...param,
- * }
- */
- },
- preCheckK8sProvider (provider) {
- this.clustersM.performAction({
- id: 'pre-check',
- action: '',
- data: {
- provider: this.provider.hypervisor,
- resource_type: 'guest',
- },
- }).then(({ data }) => {
- this.preCheckResp = data
- this.fetchK8sVersions()
- })
- },
- fetchK8sVersions () {
- new this.$Manager('kubeclusters/k8s-versions', 'v1').list({
- params: this.params.k8sVersions(),
- }).then(({ data }) => {
- data.map((item, index) => {
- this.k8sVersionOps.push({ key: item, label: item })
- })
- this.form.fc.setFieldsValue({ version: data[0] })
- })
- },
- isConfigImageChange (val) {
- this.isConfigImage = val
- },
- validator (type) {
- return (rule, value, _callback) => {
- if (type === 'vcpu_count') {
- if (value < 4 || value > 32) {
- return _callback(this.$t('k8s.text_172'))
- }
- } else if (type === 'vmem_size') {
- if (value < 4 || value > 128) {
- return _callback(this.$t('k8s.text_173'))
- }
- } else if (type === 'disk') {
- if (value < 1 || value > 500) {
- return _callback(this.$t('k8s.text_174'))
- }
- }
- return _callback()
- }
- },
- k8sVersionsLabelFormat (val) {
- return val.model
- },
- doCreate (data) {
- return new this.$Manager('kubeclusters', 'v1').create({
- data,
- })
- },
- genData (data) {
- const { provider, version: k8sVersion, name, vpc, cloudregion, sku } = data
- const hypervisor = provider.hypervisor
- const values = {
- project_domain_id: data.project_domain_id,
- version: k8sVersion,
- machines: [],
- name,
- resource_type: 'guest',
- cloudregion_id: cloudregion.key,
- vpc_id: vpc.key,
- }
- if (data.image_repository_url) {
- values.image_repository = {}
- values.image_repository.url = data.image_repository_url
- }
- if (data.image_repository_insecure) values.image_repository.insecure = data.image_repository_insecure
- Object.keys(data.sku).map(key => {
- const disks = [{
- index: 0,
- size: data.systemDiskSize[key] * 1024,
- backend: data.systemDiskType[key].key,
- }]
- if (data.systemDiskSchedtag) {
- if (data.systemDiskSchedtag[key] && data.systemDiskPolicy[key]) {
- disks[0].schedtags = [{ id: data.systemDiskSchedtag[key], strategy: data.systemDiskPolicy[key] }]
- }
- }
- if (hypervisor === HYPERVISORS_MAP.kvm.key || hypervisor === HYPERVISORS_MAP.cloudpods.key) {
- const backend = disks[0].backend
- disks[0].backend = backend.split('/')[0]
- disks[0].medium = backend.split('/')[1]
- }
- if (data.image && data.image[key]) {
- disks[0].image_id = data.image[key].key
- }
- const machinesItem = {
- vm: {
- /* vcpu_count: data.vcpu_count[key], */
- /* vmem_size: data.vmem_size[key] * 1024, */
- instance_type: sku[key].name,
- hypervisor,
- disks,
- nets: [{ network: data.network[key] }],
- },
- }
- if (data.ip && data.ip[key]) machinesItem.vm.nets[0].address = data.ip[key]
- if (data.num[key] > 1) {
- for (let i = 0; i < data.num[key]; i++) {
- values.machines.push({ config: machinesItem, role: data.role[key], resource_type: 'vm' })
- }
- } else {
- values.machines.push({ config: machinesItem, role: data.role[key], resource_type: 'vm' })
- }
- })
- return values
- },
- async handleConfirm () {
- if (!this.providers || !this.providers.length) {
- this.$message.error(this.$t('common_468'))
- return
- }
- try {
- const values = await this.form.fc.validateFields()
- const genValues = this.genData(values)
- const hasControl = genValues.machines.some(val => val.role === 'controlplane')
- if (!hasControl) {
- this.$message.warning(this.$t('k8s.text_175'))
- this.loading = false
- return
- }
- this.loading = true
- await this.doCreate(genValues)
- this.loading = false
- this.$router.push('/k8s-cluster')
- } catch (error) {
- this.loading = false
- throw error
- }
- },
- cancel () {
- this.$router.push('/k8s-cluster')
- },
- },
- }
- </script>
|