1. Support quota info when bfv instance create snapshot 2. Disable click submit button when snapshot quota or each type quota is insufficient Change-Id: I8647aa9e9e8a7669eda6549ef9ab4dcdba2e3dec
485 lines
11 KiB
JavaScript
485 lines
11 KiB
JavaScript
// Copyright 2021 99cloud
|
|
//
|
|
// Licensed 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.
|
|
|
|
import { action, observable } from 'mobx';
|
|
import { get } from 'lodash';
|
|
import client from 'client';
|
|
import Base from 'stores/base';
|
|
import { mapperRule } from 'resources/neutron/security-group-rule';
|
|
import { RecycleBinStore } from '../skyline/recycle-server';
|
|
|
|
export class ServerStore extends Base {
|
|
@observable
|
|
interface = {};
|
|
|
|
@observable
|
|
securityGroups = {};
|
|
|
|
@observable
|
|
interfaces = [];
|
|
|
|
@observable
|
|
serverSnapshots = [];
|
|
|
|
@observable
|
|
volumesForSnapshot = [];
|
|
|
|
get client() {
|
|
return client.nova.servers;
|
|
}
|
|
|
|
get imageClient() {
|
|
return client.glance.images;
|
|
}
|
|
|
|
get portClient() {
|
|
return client.neutron.ports;
|
|
}
|
|
|
|
get networkClient() {
|
|
return client.neutron.networks;
|
|
}
|
|
|
|
get sgClient() {
|
|
return client.neutron.securityGroups;
|
|
}
|
|
|
|
get mapper() {
|
|
return (item) => {
|
|
item.status = item.status.toLowerCase();
|
|
if (!item.flavor_info) {
|
|
item.flavor_info = item.flavor;
|
|
}
|
|
return item;
|
|
};
|
|
}
|
|
|
|
get mapperSecurityGroupRule() {
|
|
return (data) => {
|
|
const { security_group_rules = [] } = data;
|
|
return {
|
|
...data,
|
|
security_group_rules: security_group_rules.map(mapperRule),
|
|
};
|
|
};
|
|
}
|
|
|
|
listFetchByClient(params) {
|
|
return this.skylineClient.extension.servers(params);
|
|
}
|
|
|
|
get paramsFuncPage() {
|
|
return (params) => {
|
|
const { current, noReminder, ...rest } = params;
|
|
return rest;
|
|
};
|
|
}
|
|
|
|
updateParamsSortPage = (params, sortKey, sortOrder) => {
|
|
if (sortKey && sortOrder) {
|
|
params.sort_keys = sortKey;
|
|
params.sort_dirs = sortOrder === 'descend' ? 'desc' : 'asc';
|
|
}
|
|
};
|
|
|
|
@action
|
|
async fetchDetailWithoutExpiration({ id, all_projects }) {
|
|
this.isLoading = true;
|
|
const result = await this.client.show(
|
|
id,
|
|
this.getDetailParams({ all_projects })
|
|
);
|
|
const originData = get(result, this.responseKey) || result;
|
|
this.detail = this.mapperBeforeFetchProject(originData);
|
|
this.isLoading = false;
|
|
return this.detail;
|
|
}
|
|
|
|
async detailDidFetch(item, all_projects, filters) {
|
|
const { id } = item;
|
|
const { isRecycleBinDetail } = filters;
|
|
try {
|
|
if (!isRecycleBinDetail) {
|
|
const result = await this.fetchList({
|
|
uuid: id,
|
|
noReminder: true,
|
|
all_projects,
|
|
});
|
|
item.itemInList = result[0];
|
|
} else {
|
|
const store = new RecycleBinStore();
|
|
const result = await store.fetchList({ uuid: id, all_projects });
|
|
item.itemInList = result[0];
|
|
}
|
|
} catch (e) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(e);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
async requestList(params, originParams = {}) {
|
|
const { members, isServerGroup } = originParams;
|
|
if (members && isServerGroup && members.length === 0) {
|
|
return [];
|
|
}
|
|
const data = !this.fetchListByLimit
|
|
? await this.requestListAll(params)
|
|
: await this.requestListAllByLimit(params, 100);
|
|
return data;
|
|
}
|
|
|
|
async listDidFetch(newData, allProjects, filters) {
|
|
if (newData.length === 0) {
|
|
return newData;
|
|
}
|
|
const { members, isServerGroup, host } = filters;
|
|
const isoImages = await this.imageClient.list({ disk_format: 'iso' });
|
|
const { images } = isoImages;
|
|
if (images[0]) {
|
|
const imageId = images.map((it) => it.id);
|
|
newData.map((server) => {
|
|
if (imageId.indexOf(server.image) !== -1) {
|
|
server.iso_server = true;
|
|
}
|
|
server.tags = (server.origin_data || {}).tags || [];
|
|
return server;
|
|
});
|
|
}
|
|
if (isServerGroup) {
|
|
return newData
|
|
.filter((it) => members.indexOf(it.id) >= 0)
|
|
.map((it) => ({
|
|
...it,
|
|
tags: (it.origin_data || {}).tags || [],
|
|
}));
|
|
}
|
|
if (host) {
|
|
return newData
|
|
.filter((it) => it.host === host)
|
|
.map((it) => ({
|
|
...it,
|
|
tags: (it.origin_data || {}).tags || [],
|
|
}));
|
|
}
|
|
return newData.map((it) => ({
|
|
...it,
|
|
tags: (it.origin_data || {}).tags || [],
|
|
}));
|
|
}
|
|
|
|
@action
|
|
async fetchInterface({ id }) {
|
|
this.interface.isLoading = true;
|
|
const params = { device_id: id };
|
|
const [resData, networks] = await Promise.all([
|
|
this.portClient.list(params),
|
|
this.networkClient.list(),
|
|
]);
|
|
const interfaces = resData.ports;
|
|
const interfaceAll = [];
|
|
networks.networks.forEach((network) => {
|
|
const interfaceItem = [];
|
|
interfaces.forEach((it) => {
|
|
if (it.network_id === network.id) {
|
|
it.network_name = network.name;
|
|
interfaceItem.push(it);
|
|
}
|
|
});
|
|
if (interfaceItem.length !== 0) {
|
|
interfaceAll.push(interfaceItem);
|
|
}
|
|
});
|
|
this.interface = {
|
|
data: interfaceAll || [],
|
|
total: resData.total_count || resData.length || 0,
|
|
isLoading: false,
|
|
};
|
|
}
|
|
|
|
@action
|
|
async fetchSecurityGroup({ id }) {
|
|
this.securityGroups.isLoading = true;
|
|
const portResult = await this.portClient.list({
|
|
device_id: id,
|
|
});
|
|
const { ports = [] } = portResult;
|
|
const sgs = [];
|
|
ports.forEach((it) => sgs.push(...it.security_groups));
|
|
const sgIds = Array.from(new Set(sgs));
|
|
let sgItems = [];
|
|
try {
|
|
const result = await Promise.all(
|
|
sgIds.map((it) => this.sgClient.show(it))
|
|
);
|
|
sgItems = result.map((it) =>
|
|
this.mapperSecurityGroupRule(it.security_group)
|
|
);
|
|
} catch (e) {}
|
|
this.securityGroups = {
|
|
data: sgItems || [],
|
|
interfaces: ports,
|
|
isLoading: false,
|
|
};
|
|
}
|
|
|
|
@action
|
|
delete = async ({ id }) => {
|
|
return this.client.delete(id);
|
|
};
|
|
|
|
@action
|
|
async create(body) {
|
|
return this.submitting(this.client.create(body));
|
|
}
|
|
|
|
@action
|
|
async getConsole({ id }) {
|
|
const body = {
|
|
remote_console: {
|
|
protocol: 'vnc',
|
|
type: 'novnc',
|
|
},
|
|
};
|
|
const result = await this.client.createConsole(id, body);
|
|
this.isSubmitting = false;
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
async getConsoleIronic({ id }) {
|
|
const body = {
|
|
remote_console: {
|
|
protocol: 'serial',
|
|
type: 'serial',
|
|
},
|
|
};
|
|
const result = await this.client.createConsole(id, body);
|
|
this.isSubmitting = false;
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
update(id, body) {
|
|
return this.submitting(this.client.action(id, body));
|
|
}
|
|
|
|
@action
|
|
async operation({ body, id, key }) {
|
|
// set timeout to delay to fresh
|
|
let reqBody = body;
|
|
if (!reqBody) {
|
|
reqBody = {};
|
|
reqBody[key] = null;
|
|
}
|
|
return this.update(id, reqBody);
|
|
}
|
|
|
|
@action
|
|
async lock({ id }) {
|
|
return this.operation({ key: 'lock', id });
|
|
}
|
|
|
|
@action
|
|
async unlock({ id }) {
|
|
return this.operation({ key: 'unlock', id });
|
|
}
|
|
|
|
@action
|
|
async pause({ id }) {
|
|
return this.operation({ key: 'pause', id });
|
|
}
|
|
|
|
@action
|
|
async unpause({ id }) {
|
|
return this.operation({ key: 'unpause', id });
|
|
}
|
|
|
|
@action
|
|
async suspend({ id }) {
|
|
return this.operation({ key: 'suspend', id });
|
|
}
|
|
|
|
@action
|
|
async resume({ id }) {
|
|
return this.operation({ key: 'resume', id });
|
|
}
|
|
|
|
@action
|
|
async start({ id }) {
|
|
return this.operation({ key: 'os-start', id });
|
|
}
|
|
|
|
@action
|
|
async stop({ id }) {
|
|
return this.operation({ key: 'os-stop', id });
|
|
}
|
|
|
|
@action
|
|
async restore({ id }) {
|
|
return this.operation({ key: 'restore', id });
|
|
}
|
|
|
|
@action
|
|
async forceDelete({ id }) {
|
|
const body = {
|
|
forceDelete: null,
|
|
};
|
|
return this.client.action(id, body);
|
|
}
|
|
|
|
@action
|
|
async softReboot({ id }) {
|
|
const body = {
|
|
reboot: {
|
|
type: 'SOFT',
|
|
},
|
|
};
|
|
return this.operation({ body, id });
|
|
}
|
|
|
|
@action
|
|
async reboot({ id }) {
|
|
const body = {
|
|
reboot: {
|
|
type: 'HARD',
|
|
},
|
|
};
|
|
return this.operation({ body, id });
|
|
}
|
|
|
|
@action
|
|
async changePassword({ id, password }) {
|
|
const body = {
|
|
changePassword: {
|
|
adminPass: password,
|
|
},
|
|
};
|
|
return this.operation({ body, id });
|
|
}
|
|
|
|
@action
|
|
async createImage({ id, image }) {
|
|
const body = {
|
|
createImage: {
|
|
name: image,
|
|
metadata: {
|
|
usage_type: 'common',
|
|
image_type: 'snapshot',
|
|
instance_id: id,
|
|
},
|
|
},
|
|
};
|
|
return this.operation({ body, id });
|
|
}
|
|
|
|
@action
|
|
async rebuild({ id, image }) {
|
|
const body = {
|
|
rebuild: {
|
|
imageRef: image,
|
|
},
|
|
};
|
|
return this.operation({ body, id });
|
|
}
|
|
|
|
@action
|
|
async resize({ id, flavor }) {
|
|
const body = {
|
|
resize: {
|
|
flavorRef: flavor,
|
|
},
|
|
};
|
|
return this.operation({ body, id });
|
|
}
|
|
|
|
@action
|
|
async migrate({ id, body }) {
|
|
if (body) {
|
|
const newBody = {
|
|
migrate: body,
|
|
};
|
|
return this.operation({ body: newBody, id });
|
|
}
|
|
return this.operation({ key: 'migrate', id });
|
|
}
|
|
|
|
@action
|
|
async shelve({ id }) {
|
|
return this.operation({ key: 'shelve', id });
|
|
}
|
|
|
|
@action
|
|
async unshelve({ id }) {
|
|
return this.operation({ key: 'unshelve', id });
|
|
}
|
|
|
|
@action
|
|
async migrateLive({ id, body }) {
|
|
const newBody = {
|
|
'os-migrateLive': body,
|
|
};
|
|
return this.operation({ body: newBody, id });
|
|
}
|
|
|
|
@action
|
|
async removeFloatingIp({ id, body }) {
|
|
const newBody = {
|
|
removeFloatingIp: body,
|
|
};
|
|
return this.operation({ body: newBody, id });
|
|
}
|
|
|
|
@action
|
|
async addInterface({ id, body }) {
|
|
return this.submitting(this.client.interfaces.create(id, body));
|
|
}
|
|
|
|
@action
|
|
async fetchInterfaceList({ id }) {
|
|
const result = await this.client.interfaces.list(id);
|
|
this.interfaces = result.interfaceAttachments;
|
|
return result.interfaceAttachments;
|
|
}
|
|
|
|
@action
|
|
async detachInterface({ id, ports }) {
|
|
return this.submitting(
|
|
Promise.all(ports.map((port) => this.client.interfaces.delete(id, port)))
|
|
);
|
|
}
|
|
|
|
@action
|
|
async attachVolume({ id, body }) {
|
|
return this.submitting(this.client.volumeAttachments.create(id, body));
|
|
}
|
|
|
|
@action
|
|
async detachVolume({ id, volumes }) {
|
|
return this.submitting(
|
|
Promise.all(
|
|
volumes.map((item) => this.client.volumeAttachments.delete(id, item))
|
|
)
|
|
);
|
|
}
|
|
|
|
@action
|
|
setVolumesForSnapshot(volumes) {
|
|
this.volumesForSnapshot = volumes;
|
|
}
|
|
}
|
|
|
|
const globalServerStore = new ServerStore();
|
|
export default globalServerStore;
|