1. Update Form/ModalAction/ActionButton to support right extra info display in modal 2. Add quota info when create server group 3. Support disable click submit button in modalAction / formAction Change-Id: I511c383f0ffa256b76c1a8fd123c6326e7a43ed3
472 lines
12 KiB
JavaScript
472 lines
12 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 { getGiBValue } from 'utils/index';
|
|
import { isNil, isEmpty, isObject } from 'lodash';
|
|
import client from 'client';
|
|
import Base from 'stores/base';
|
|
import globalRootStore from 'stores/root';
|
|
|
|
export class ProjectStore extends Base {
|
|
@observable
|
|
quota = {};
|
|
|
|
@observable
|
|
novaQuota = {};
|
|
|
|
@observable
|
|
groupRoleList = [];
|
|
|
|
get client() {
|
|
return client.keystone.projects;
|
|
}
|
|
|
|
get domainClient() {
|
|
return client.keystone.domains;
|
|
}
|
|
|
|
get roleAssignmentClient() {
|
|
return client.keystone.roleAssignments;
|
|
}
|
|
|
|
get roleClient() {
|
|
return client.keystone.roles;
|
|
}
|
|
|
|
get userClient() {
|
|
return client.keystone.users;
|
|
}
|
|
|
|
get novaQuotaClient() {
|
|
return client.nova.quotaSets;
|
|
}
|
|
|
|
get cinderQuotaClient() {
|
|
return client.cinder.quotaSets;
|
|
}
|
|
|
|
get neutronQuotaClient() {
|
|
return client.neutron.quotas;
|
|
}
|
|
|
|
get shareQuotaClient() {
|
|
return client.manila.quotaSets;
|
|
}
|
|
|
|
listFetchByClient(params, originParams) {
|
|
const { userId } = originParams;
|
|
if (userId) {
|
|
return this.userClient.projects.list(userId, params);
|
|
}
|
|
return this.client.list(params);
|
|
}
|
|
|
|
get paramsFunc() {
|
|
return (params) => {
|
|
const { id, userId, groupId, withRole, ...rest } = params;
|
|
return rest;
|
|
};
|
|
}
|
|
|
|
updateProject = (project, roleAssignments, roles, domains) => {
|
|
const userMapRoles = {};
|
|
const groupMapRoles = {};
|
|
const { id } = project || {};
|
|
roleAssignments.forEach((roleAssignment) => {
|
|
const {
|
|
scope: { project: { id: projectId } = {} } = {},
|
|
user: { id: userId } = {},
|
|
group: { id: groupId } = {},
|
|
role: { id: roleId } = {},
|
|
} = roleAssignment;
|
|
const roleItem = roles.find((it) => it.id === roleId);
|
|
if (projectId === id && roleId) {
|
|
if (userId) {
|
|
userMapRoles[userId] = userMapRoles[userId]
|
|
? [...userMapRoles[userId], roleItem]
|
|
: [roleItem];
|
|
}
|
|
if (groupId) {
|
|
groupMapRoles[groupId] = groupMapRoles[groupId]
|
|
? [...groupMapRoles[groupId], roleItem]
|
|
: [roleItem];
|
|
}
|
|
}
|
|
});
|
|
const domain = domains.find((it) => it.id === project.domain_id);
|
|
return {
|
|
...project,
|
|
users: userMapRoles,
|
|
groups: groupMapRoles,
|
|
userCount: Object.keys(userMapRoles).length,
|
|
groupCount: Object.keys(groupMapRoles).length,
|
|
domain,
|
|
domainName: (domain || {}).name || project.domain_id,
|
|
};
|
|
};
|
|
|
|
async listDidFetch(items, allProjects, filters) {
|
|
if (!items.length) {
|
|
return items;
|
|
}
|
|
const { userId, groupId, withRole = true } = filters;
|
|
const params = {};
|
|
if (groupId) {
|
|
params['group.id'] = groupId;
|
|
}
|
|
const [roleAssignmentResult, roleResult, domainResult] = await Promise.all([
|
|
withRole ? this.roleAssignmentClient.list(params) : null,
|
|
withRole ? this.roleClient.list() : null,
|
|
this.domainClient.list(),
|
|
]);
|
|
const { roles = [] } = roleResult || {};
|
|
const { domains = [] } = domainResult;
|
|
const { role_assignments: assigns = [] } = roleAssignmentResult || {};
|
|
const newItems = items.map((project) => {
|
|
return this.updateProject(project, assigns, roles, domains);
|
|
});
|
|
if (userId) {
|
|
const { groups = [] } = await this.userClient.groups.list(userId);
|
|
return newItems.map((it) => {
|
|
const { users = {}, groups: groupMaps = {} } = it;
|
|
const currentUsers = users[userId] ? { [userId]: users[userId] } : {};
|
|
const groupIds = groups.map((g) => g.id);
|
|
const currentGroups = Object.keys(groupMaps).reduce((pre, cur) => {
|
|
if (groupIds.includes(cur)) {
|
|
pre[cur] = {
|
|
roles: groupMaps[cur],
|
|
group: groups.find((g) => g.id === cur),
|
|
};
|
|
}
|
|
return pre;
|
|
}, {});
|
|
return {
|
|
...it,
|
|
users: currentUsers,
|
|
userCount: Object.keys(currentUsers).length,
|
|
groups: currentGroups,
|
|
groupCount: Object.keys(currentGroups).length,
|
|
};
|
|
});
|
|
}
|
|
if (groupId) {
|
|
return newItems.filter((it) => !!it.groupCount);
|
|
}
|
|
return newItems;
|
|
}
|
|
|
|
async detailDidFetch(item) {
|
|
const { id } = item;
|
|
const [roleAssignmentResult, roleResult, domainResult] = await Promise.all([
|
|
this.roleAssignmentClient.list({
|
|
'scope.project.id': id,
|
|
}),
|
|
this.roleClient.list(),
|
|
this.domainClient.list(),
|
|
]);
|
|
return this.updateProject(
|
|
item,
|
|
roleAssignmentResult.role_assignments,
|
|
roleResult.roles,
|
|
domainResult.domains
|
|
);
|
|
}
|
|
|
|
get enableCinder() {
|
|
return globalRootStore.checkEndpoint('cinder');
|
|
}
|
|
|
|
get enableShare() {
|
|
return globalRootStore.checkEndpoint('manilav2');
|
|
}
|
|
|
|
@action
|
|
async enable({ id }) {
|
|
const reqBody = {
|
|
project: { enabled: true },
|
|
};
|
|
return this.submitting(this.client.patch(id, reqBody));
|
|
}
|
|
|
|
@action
|
|
async forbidden({ id }) {
|
|
const reqBody = {
|
|
project: { enabled: false },
|
|
};
|
|
return this.submitting(this.client.patch(id, reqBody));
|
|
}
|
|
|
|
@action
|
|
async createProject(data) {
|
|
const reqBody = {
|
|
project: data,
|
|
};
|
|
return this.submitting(this.client.create(reqBody));
|
|
}
|
|
|
|
@action
|
|
async edit({ id, description, name }) {
|
|
const reqBody = {
|
|
project: { description, name },
|
|
};
|
|
return this.submitting(this.client.patch(id, reqBody));
|
|
}
|
|
|
|
@action
|
|
async fetchProjectQuota({ project_id }) {
|
|
const promiseArr = [
|
|
this.novaQuotaClient.detail(project_id),
|
|
this.neutronQuotaClient.details(project_id),
|
|
];
|
|
promiseArr.push(
|
|
this.enableCinder
|
|
? this.cinderQuotaClient.show(project_id, { usage: 'True' })
|
|
: null
|
|
);
|
|
promiseArr.push(
|
|
this.enableShare ? this.shareQuotaClient.showDetail(project_id) : null
|
|
);
|
|
const [novaResult, neutronResult, cinderResult, shareResult] =
|
|
await Promise.all(promiseArr);
|
|
this.isSubmitting = false;
|
|
const { quota_set: novaQuota } = novaResult;
|
|
const { ram } = novaQuota;
|
|
const { quota_set: cinderQuota = {} } = cinderResult || {};
|
|
const { quota: neutronQuota } = neutronResult;
|
|
const { quota_set: shareQuota = {} } = shareResult || {};
|
|
novaQuota.ram = {
|
|
in_use: getGiBValue(ram.in_use),
|
|
limit: ram.limit === -1 ? ram.limit : getGiBValue(ram.limit),
|
|
};
|
|
const renameShareQuota = Object.keys(shareQuota).reduce((pre, cur) => {
|
|
if (cur === 'gigabytes') {
|
|
pre.share_gigabytes = shareQuota[cur];
|
|
} else {
|
|
pre[cur] = shareQuota[cur];
|
|
}
|
|
return pre;
|
|
}, {});
|
|
const quota = {
|
|
...novaQuota,
|
|
...cinderQuota,
|
|
...neutronQuota,
|
|
...renameShareQuota,
|
|
};
|
|
const newQuota = this.updateQuotaData(quota);
|
|
this.quota = newQuota;
|
|
return newQuota;
|
|
}
|
|
|
|
omitNil = (obj) => {
|
|
return Object.keys(obj).reduce((acc, v) => {
|
|
if (!isNil(obj[v])) {
|
|
acc[v] = obj[v];
|
|
}
|
|
return acc;
|
|
}, {});
|
|
};
|
|
|
|
getNovaQuotaBody(data) {
|
|
const {
|
|
instances,
|
|
cores,
|
|
ram,
|
|
server_groups,
|
|
server_group_members,
|
|
key_pairs,
|
|
} = data;
|
|
let ramGb = ram;
|
|
if (ram && ram !== -1) {
|
|
ramGb = ram * 1024;
|
|
}
|
|
const novaReqBody = {
|
|
quota_set: this.omitNil({
|
|
instances,
|
|
cores,
|
|
ram: ramGb,
|
|
server_groups,
|
|
server_group_members,
|
|
key_pairs,
|
|
}),
|
|
};
|
|
return novaReqBody;
|
|
}
|
|
|
|
getCinderQuotaBody(data) {
|
|
if (!this.enableCinder) return {};
|
|
const { backups, ...others } = data;
|
|
const rest = {};
|
|
Object.keys(others).forEach((key) => {
|
|
if (
|
|
(key.includes('volumes') ||
|
|
key.includes('gigabytes') ||
|
|
key.includes('snapshots')) &&
|
|
!key.includes('share')
|
|
) {
|
|
rest[key] = others[key];
|
|
}
|
|
});
|
|
const cinderReqBody = {
|
|
quota_set: this.omitNil({
|
|
backups,
|
|
...rest,
|
|
}),
|
|
};
|
|
return cinderReqBody;
|
|
}
|
|
|
|
getNeutronQuotaBody(data) {
|
|
const {
|
|
security_group_rule,
|
|
network,
|
|
router,
|
|
subnet,
|
|
floatingip,
|
|
security_group,
|
|
port,
|
|
} = data;
|
|
const neutronReqBody = {
|
|
quota: this.omitNil({
|
|
network,
|
|
router,
|
|
subnet,
|
|
floatingip,
|
|
security_group,
|
|
security_group_rule,
|
|
port,
|
|
}),
|
|
};
|
|
return neutronReqBody;
|
|
}
|
|
|
|
getShareQuotaBody(data) {
|
|
if (!this.enableShare) {
|
|
return {};
|
|
}
|
|
const { shares, share_gigabytes, share_networks, share_groups } = data;
|
|
const shareReqBody = {
|
|
quota_set: this.omitNil({
|
|
shares,
|
|
gigabytes: share_gigabytes,
|
|
share_networks,
|
|
share_groups,
|
|
}),
|
|
};
|
|
return shareReqBody;
|
|
}
|
|
|
|
async updateQuota(project_id, data) {
|
|
const novaReqBody = this.getNovaQuotaBody(data);
|
|
const cinderReqBody = this.getCinderQuotaBody(data);
|
|
const neutronReqBody = this.getNeutronQuotaBody(data);
|
|
const shareReqBody = this.getShareQuotaBody(data);
|
|
const reqs = [];
|
|
if (!isEmpty(novaReqBody.quota_set)) {
|
|
reqs.push(client.nova.quotaSets.update(project_id, novaReqBody));
|
|
}
|
|
if (!isEmpty(cinderReqBody.quota_set)) {
|
|
reqs.push(client.cinder.quotaSets.update(project_id, cinderReqBody));
|
|
}
|
|
if (!isEmpty(neutronReqBody.quota)) {
|
|
reqs.push(client.neutron.quotas.update(project_id, neutronReqBody));
|
|
}
|
|
if (!isEmpty(shareReqBody.quota_set)) {
|
|
reqs.push(client.manila.quotaSets.update(project_id, shareReqBody));
|
|
}
|
|
const result = await Promise.all(reqs);
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
async updateProjectQuota({ project_id, data }) {
|
|
this.isSubmitting = true;
|
|
const result = await this.updateQuota(project_id, data);
|
|
this.isSubmitting = false;
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
async create(data) {
|
|
const body = {};
|
|
body[this.responseKey] = data;
|
|
this.isSubmitting = true;
|
|
const result = await this.client.create(body);
|
|
this.isSubmitting = false;
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
async assignUserRole({ id, userId, roleId }) {
|
|
const result = await this.client.users.roles.update(id, userId, roleId);
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
async removeUserRole({ id, userId, roleId }) {
|
|
const result = await this.client.users.roles.delete(id, userId, roleId);
|
|
return result;
|
|
}
|
|
|
|
@action
|
|
async getGroupRoleList({ id, groupId }) {
|
|
const result = await this.client.groups.roles.list(id, groupId);
|
|
this.groupRoleList = result.roles;
|
|
}
|
|
|
|
@action
|
|
async assignGroupRole({ id, groupId, roleId }) {
|
|
const result = await this.client.groups.roles.update(id, groupId, roleId);
|
|
return result;
|
|
}
|
|
|
|
async removeGroupRole({ id, groupId, roleId }) {
|
|
const result = await this.client.groups.roles.delete(id, groupId, roleId);
|
|
return result;
|
|
}
|
|
|
|
getLeftQuotaData = (data) => {
|
|
const { used = 0, limit = 0, reserved = 0 } = data;
|
|
if (limit === -1) {
|
|
return -1;
|
|
}
|
|
return limit - used - reserved;
|
|
};
|
|
|
|
updateQuotaData = (quota) => {
|
|
const newData = JSON.parse(JSON.stringify(quota));
|
|
Object.keys(newData).forEach((it) => {
|
|
if (isObject(newData[it])) {
|
|
if (newData[it].in_use !== undefined) {
|
|
newData[it].used = newData[it].in_use;
|
|
}
|
|
newData[it].left = this.getLeftQuotaData(newData[it]);
|
|
}
|
|
});
|
|
return newData;
|
|
};
|
|
|
|
@action
|
|
async fetchProjectNovaQuota() {
|
|
const result = await this.novaQuotaClient.detail(this.currentProjectId);
|
|
const { quota_set: quota } = result;
|
|
const novaQuota = this.updateQuotaData(quota);
|
|
this.novaQuota = novaQuota;
|
|
return novaQuota;
|
|
}
|
|
}
|
|
|
|
const globalProjectStore = new ProjectStore();
|
|
export default globalProjectStore;
|