Merge "feat: support quota info && check when resize instance"
This commit is contained in:
commit
03d34ba9a4
@ -22,8 +22,96 @@ import {
|
|||||||
checkStatus,
|
checkStatus,
|
||||||
isIronicInstance,
|
isIronicInstance,
|
||||||
} from 'resources/nova/instance';
|
} from 'resources/nova/instance';
|
||||||
|
import globalProjectStore from 'stores/keystone/project';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
import { getGiBValue, formatSize } from 'utils/index';
|
||||||
import FlavorSelectTable from '../components/FlavorSelectTable';
|
import FlavorSelectTable from '../components/FlavorSelectTable';
|
||||||
|
|
||||||
|
export async function fetchQuota(self) {
|
||||||
|
self.setState({
|
||||||
|
quota: {},
|
||||||
|
quotaLoading: true,
|
||||||
|
});
|
||||||
|
const result = await globalProjectStore.fetchProjectNovaQuota();
|
||||||
|
self.setState({
|
||||||
|
quota: result,
|
||||||
|
quotaLoading: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getQuota = (novaQuota) => {
|
||||||
|
if (isEmpty(novaQuota)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const { cores = {}, ram = {} } = novaQuota || {};
|
||||||
|
return {
|
||||||
|
cores,
|
||||||
|
ram,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAdd = (self, flavor) => {
|
||||||
|
if (isEmpty(flavor)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const { vcpus: itemVcpus, ram: itemRam } = self.item.flavor_info || {};
|
||||||
|
const { vcpus, ram: flavorRam } = flavor || {};
|
||||||
|
const newVcpu = vcpus - itemVcpus;
|
||||||
|
const newRamGiB = getGiBValue(flavorRam - itemRam);
|
||||||
|
return {
|
||||||
|
vcpuAdd: newVcpu,
|
||||||
|
ramAdd: newRamGiB,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkFlavorDisable = (flavor, self) => {
|
||||||
|
const { quotaLoading = true, quota } = self.state;
|
||||||
|
if (quotaLoading || isEmpty(quota)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
cores: { left },
|
||||||
|
ram: { left: ramLeft },
|
||||||
|
} = getQuota(quota);
|
||||||
|
const { vcpuAdd, ramAdd } = getAdd(self, flavor);
|
||||||
|
const vcpuOK = left === -1 || left >= vcpuAdd;
|
||||||
|
const ramOK = ramLeft === -1 || ramLeft >= ramAdd;
|
||||||
|
return !vcpuOK || !ramOK;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getQuotaInfo = (self) => {
|
||||||
|
const { quota = {}, quotaLoading, flavor = {} } = self.state;
|
||||||
|
if (quotaLoading || isEmpty(quota)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const { cores = {}, ram = {} } = getQuota(quota);
|
||||||
|
const { vcpuAdd = 0, ramAdd = 0 } = getAdd(self, flavor || {});
|
||||||
|
|
||||||
|
const cpuQuotaInfo = {
|
||||||
|
...cores,
|
||||||
|
add: vcpuAdd,
|
||||||
|
name: 'cpu',
|
||||||
|
title: t('CPU'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const ramQuotaInfo = {
|
||||||
|
...ram,
|
||||||
|
add: ramAdd,
|
||||||
|
name: 'ram',
|
||||||
|
title: t('Memory (GiB)'),
|
||||||
|
type: 'line',
|
||||||
|
};
|
||||||
|
return [cpuQuotaInfo, ramQuotaInfo];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFlavorLabel = (self) => {
|
||||||
|
const { flavor, flavor_info: { vcpus, ram } = {} } = self.item;
|
||||||
|
return `${flavor} (${t('VCPUs')}: ${vcpus}, ${t('Memory')}: ${formatSize(
|
||||||
|
ram,
|
||||||
|
2
|
||||||
|
)})`;
|
||||||
|
};
|
||||||
|
|
||||||
export class Resize extends ModalAction {
|
export class Resize extends ModalAction {
|
||||||
static id = 'resize';
|
static id = 'resize';
|
||||||
|
|
||||||
@ -33,6 +121,7 @@ export class Resize extends ModalAction {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.store = globalFlavorStore;
|
this.store = globalFlavorStore;
|
||||||
|
fetchQuota(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
@ -71,8 +160,17 @@ export class Resize extends ModalAction {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get showQuota() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get quotaInfo() {
|
||||||
|
return getQuotaInfo(this);
|
||||||
|
}
|
||||||
|
|
||||||
get defaultValue() {
|
get defaultValue() {
|
||||||
const { name, flavor } = this.item;
|
const { name } = this.item;
|
||||||
|
const flavor = getFlavorLabel(this);
|
||||||
const value = {
|
const value = {
|
||||||
instance: name,
|
instance: name,
|
||||||
flavor,
|
flavor,
|
||||||
@ -82,7 +180,8 @@ export class Resize extends ModalAction {
|
|||||||
|
|
||||||
static policy = 'os_compute_api:servers:resize';
|
static policy = 'os_compute_api:servers:resize';
|
||||||
|
|
||||||
static isActiveOrShutOff = (item) => checkStatus(['active', 'shutoff'], item);
|
static isActiveOrShutOff = (item) =>
|
||||||
|
checkStatus(['active', 'shutoff'], item, false);
|
||||||
|
|
||||||
static allowed = (item, containerProps) => {
|
static allowed = (item, containerProps) => {
|
||||||
const { isAdminPage } = containerProps;
|
const { isAdminPage } = containerProps;
|
||||||
@ -94,6 +193,17 @@ export class Resize extends ModalAction {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onFlavorChange = (flavor) => {
|
||||||
|
const { selectedRows = [] } = flavor || {};
|
||||||
|
this.setState({
|
||||||
|
flavor: selectedRows[0],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
disabledFlavor = (flavor) => {
|
||||||
|
return checkFlavorDisable(flavor, this);
|
||||||
|
};
|
||||||
|
|
||||||
get formItems() {
|
get formItems() {
|
||||||
const { flavor } = this.item;
|
const { flavor } = this.item;
|
||||||
return [
|
return [
|
||||||
@ -114,7 +224,11 @@ export class Resize extends ModalAction {
|
|||||||
label: t('Flavor'),
|
label: t('Flavor'),
|
||||||
type: 'select-table',
|
type: 'select-table',
|
||||||
component: (
|
component: (
|
||||||
<FlavorSelectTable flavor={flavor} onChange={this.onFlavorChange} />
|
<FlavorSelectTable
|
||||||
|
flavor={flavor}
|
||||||
|
onChange={this.onFlavorChange}
|
||||||
|
disabledFunc={this.disabledFlavor}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
required: true,
|
required: true,
|
||||||
wrapperCol: {
|
wrapperCol: {
|
||||||
|
@ -329,7 +329,7 @@ export class FlavorSelectTable extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { value } = this.props;
|
const { value, disabledFunc } = this.props;
|
||||||
const isLoading =
|
const isLoading =
|
||||||
this.settingStore.list.isLoading && this.flavorStore.list.isLoading;
|
this.settingStore.list.isLoading && this.flavorStore.list.isLoading;
|
||||||
const props = {
|
const props = {
|
||||||
@ -345,6 +345,7 @@ export class FlavorSelectTable extends Component {
|
|||||||
],
|
],
|
||||||
value,
|
value,
|
||||||
onChange: this.onChange,
|
onChange: this.onChange,
|
||||||
|
disabledFunc,
|
||||||
};
|
};
|
||||||
return <SelectTable {...props} />;
|
return <SelectTable {...props} />;
|
||||||
}
|
}
|
||||||
|
@ -152,11 +152,11 @@ export const isLocked = (instance) => !!instance.locked;
|
|||||||
|
|
||||||
export const lockRender = (value) => (value ? lockIcon : unlockIcon);
|
export const lockRender = (value) => (value ? lockIcon : unlockIcon);
|
||||||
|
|
||||||
export const checkStatus = (statusList = [], instance) => {
|
export const checkStatus = (statusList = [], instance, checkState = true) => {
|
||||||
const { status, vm_state } = instance;
|
const { status, vm_state } = instance;
|
||||||
return (
|
return (
|
||||||
statusList.includes(status.toLowerCase()) ||
|
statusList.includes(status.toLowerCase()) ||
|
||||||
(vm_state && statusList.includes(vm_state.toLowerCase()))
|
(checkState && vm_state && statusList.includes(vm_state.toLowerCase()))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user