skyline/src/stores/keystone/project.js
Jingwei.Zhang 38403a2280 feat: Support update share quota && reset status
1. Support update share quota in project page
2. Support reset share status in administrator
3. Update share network required when choose special share type
4. Update check share group status when choose share group

Change-Id: I15443d418ec5dd841ca33d05dc2540999ecbcf5f
2022-05-10 11:55:44 +08:00

649 lines
17 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 { getGBValue } from 'utils/index';
import { get, isNil, isEmpty } from 'lodash';
import client from 'client';
import Base from 'stores/base';
import globalRootStore from 'stores/root';
export class ProjectStore extends Base {
@observable
quota = {};
@observable
userRoleList = [];
@observable
groupRoleList = [];
@observable
domains = [];
@observable
projectsOnly = [];
get client() {
return client.keystone.projects;
}
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;
}
async fetchProjects(filters) {
const { tags } = filters;
const [roleAssignmentsResult, projectsResult, roleResult] =
await Promise.all([
this.roleAssignmentClient.list(),
this.client.list(tags ? { tags } : {}),
this.roleClient.list(),
]);
const { projects } = projectsResult;
const { roles } = roleResult;
const projectRoles = roles.filter(
(it) =>
(it.name.indexOf('project_') !== -1 &&
it.name.indexOf('_project_') === -1) ||
it.name === 'admin'
);
const projectRoleId = projectRoles.map((it) => it.id);
projects.map((project) => {
const userMapRole = {}; // all user include system role and project role: { user_id: [roles_id] }
const projectGroups = {};
const userMapProjectRoles = {}; // { user_id: [projectRoles_id] }
roleAssignmentsResult.role_assignments.forEach((roleAssignment) => {
this.getUsersAndGroups(
project,
roleAssignment,
userMapRole,
projectGroups
);
});
this.getUsersProjectRole(userMapRole, userMapProjectRoles, projectRoleId);
project.users = userMapRole;
project.userMapProjectRoles = userMapProjectRoles;
project.groups = projectGroups;
project.user_num = Object.keys(userMapRole).length;
project.group_num = Object.keys(projectGroups).length;
return project;
});
return projects;
}
@action
async fetchList({
limit,
page,
sortKey,
sortOrder,
conditions,
...filters
} = {}) {
this.list.isLoading = true;
const items = await this.fetchProjects(filters);
const data = await this.listDidFetch(items, true, filters);
const newData = data.map(this.mapper);
this.list.update({
data: newData,
total: newData.length || 0,
limit: Number(limit) || 10,
page: Number(page) || 1,
sortKey,
sortOrder,
filters,
isLoading: false,
...(this.list.silent ? {} : { selectedRowKeys: [] }),
});
return items;
}
@action
getUsersProjectRole = (userMapRole, userMapProjectRoles, projectRoleId) => {
const projectUser = Object.keys(userMapRole);
projectUser.forEach((user_id) => {
const roles = userMapRole[user_id].filter(
(role_id) => projectRoleId.indexOf(role_id) !== -1
);
if (roles[0]) {
userMapProjectRoles[user_id] = roles;
}
});
};
@action
getUsersAndGroups = (project, roleAssignment, userMapRole, projectGroups) => {
if (roleAssignment.user) {
const {
user: { id: user_id },
role: { id: role_id },
scope: { project: { id } = {} } = {},
} = roleAssignment;
if (id && id === project.id) {
if (userMapRole[user_id]) {
userMapRole[user_id].push(role_id);
} else {
userMapRole[user_id] = [role_id];
}
}
}
if (roleAssignment.group) {
const {
group: { id: group_id },
role: { id: role_id },
scope: { project: { id } = {} } = {},
} = roleAssignment;
if (id && id === project.id) {
if (projectGroups[group_id]) {
projectGroups[group_id].push(role_id);
} else {
projectGroups[group_id] = [role_id];
}
}
}
};
get mapper() {
return (item) => {
const domain = this.domains.filter((it) => it.id === item.domain_id);
if (domain[0]) {
item.domain_name = domain[0].name;
}
return item;
};
}
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 fetchDomain() {
const domainsResult = await this.skylineClient.domains();
this.domains = domainsResult.domains;
}
@action
async createProject(data) {
const reqBody = {
project: data,
};
return this.submitting(this.client.create(reqBody));
}
async fetchProject(id) {
const [roleAssignmentsResult, projectResult, roleResult] =
await Promise.all([
this.roleAssignmentClient.list(),
this.client.show(id),
this.roleClient.list(),
]);
const { roles } = roleResult;
const projectRoles = roles.filter(
(it) =>
(it.name.indexOf('project_') !== -1 &&
it.name.indexOf('_project_') === -1) ||
it.name === 'admin'
);
const projectRoleId = projectRoles.map((it) => it.id);
const { project } = projectResult;
const userMapRole = {};
const projectGroups = {};
const userMapProjectRoles = {};
roleAssignmentsResult.role_assignments.forEach((roleAssignment) => {
this.getUsersAndGroups(
project,
roleAssignment,
userMapRole,
projectGroups
);
});
this.getUsersProjectRole(userMapRole, userMapProjectRoles, projectRoleId);
project.users = userMapRole;
project.userMapProjectRoles = userMapProjectRoles;
project.groups = projectGroups;
project.user_num = Object.keys(userMapRole).length;
project.group_num = Object.keys(projectGroups).length;
const newItem = await this.detailDidFetch(project);
return newItem;
}
@action
async fetchDetail({ id, silent }) {
if (!silent) {
this.isLoading = true;
}
const item = await this.fetchProject(id);
const detail = this.mapper(item);
this.detail = detail;
this.isLoading = false;
return detail;
}
@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: getGBValue(ram.in_use),
limit: ram.limit === -1 ? ram.limit : getGBValue(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 quotaKey = Object.keys(quota);
quotaKey.forEach((it) => {
if (quota[it].in_use !== undefined) {
quota[it].used = quota[it].in_use;
}
});
this.quota = quota;
return quota;
}
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 getUserRoleList({ id, user_id }) {
const result = await this.client.users.roles.list(id, user_id);
this.userRoleList = result.roles;
}
@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, user_id, role_id }) {
const result = await this.client.users.roles.update(id, user_id, role_id);
return result;
}
@action
async removeUserRole({ id, user_id, role_id }) {
const result = await this.client.users.roles.delete(id, user_id, role_id);
return result;
}
@action
async getGroupRoleList({ id, group_id }) {
const result = await this.client.groups.roles.list(id, group_id);
this.groupRoleList = result.roles;
}
@action
async assignGroupRole({ id, group_id, role_id }) {
const result = await this.client.groups.roles.update(id, group_id, role_id);
return result;
}
async removeGroupRole({ id, group_id, role_id }) {
const result = await this.client.groups.roles.delete(id, group_id, role_id);
return result;
}
@action
async fetchListInUserDetail({
limit,
page,
sortKey,
sortOrder,
conditions,
...filters
} = {}) {
this.list.isLoading = true;
const { userId } = filters;
const [roleAssignmentsResult, projectsResult, roleResult, groupResult] =
await Promise.all([
this.roleAssignmentClient.list(),
this.userClient.projects.list(userId),
this.roleClient.list(),
this.userClient.groups.list(userId),
]);
const projects = get(projectsResult, this.listResponseKey, []);
projects.map((project) => {
const userMapRole = {};
const projectGroups = {};
roleAssignmentsResult.role_assignments.forEach((roleAssignment) => {
this.getUsersAndGroups(
project,
roleAssignment,
userMapRole,
projectGroups
);
});
project.users = userMapRole;
project.groups = projectGroups;
project.projectRole = [];
if (userMapRole[userId]) {
project.projectRole = userMapRole[userId].map(
(it) => roleResult.roles.filter((role) => role.id === it)[0].name
);
}
groupResult.groups.forEach((group) => {
if (projectGroups[group.id]) {
project.groupProjectRole = projectGroups[group.id].map(
(it) =>
`${roleResult.roles.filter((role) => role.id === it)[0].name}(${t(
'user group'
)}: ${group.name})`
);
}
});
project.user_num = Object.keys(userMapRole).length;
project.group_num = Object.keys(projectGroups).length;
return project;
});
this.list.update({
data: projects,
total: projects.length || 0,
limit: Number(limit) || 10,
page: Number(page) || 1,
sortKey,
sortOrder,
filters,
isLoading: false,
...(this.list.silent ? {} : { selectedRowKeys: [] }),
});
return projects;
}
@action
async fetchListInGroupDetail({
limit,
page,
sortKey,
sortOrder,
conditions,
...filters
} = {}) {
this.list.isLoading = true;
const { groupId } = filters;
const [roleAssignmentsResult, projectsResult, roleResult] =
await Promise.all([
this.roleAssignmentClient.list(),
this.client.list(),
this.roleClient.list(),
]);
const projects = get(projectsResult, this.listResponseKey, []);
projects.map((project) => {
const userMapRole = {};
const projectGroups = {};
roleAssignmentsResult.role_assignments.forEach((roleAssignment) => {
this.getUsersAndGroups(
project,
roleAssignment,
userMapRole,
projectGroups
);
});
project.users = userMapRole;
project.groups = projectGroups;
project.projectRole = [];
if (projectGroups[groupId]) {
project.projectRole = projectGroups[groupId].map(
(it) => roleResult.roles.filter((role) => role.id === it)[0].name
);
}
project.user_num = Object.keys(userMapRole).length;
project.group_num = Object.keys(projectGroups).length;
return project;
});
const groupProjects = projects.filter(
(it) => Object.keys(it.groups).indexOf(groupId) >= 0
);
this.list.update({
data: groupProjects,
total: groupProjects.length || 0,
limit: Number(limit) || 10,
page: Number(page) || 1,
sortKey,
sortOrder,
filters,
isLoading: false,
...(this.list.silent ? {} : { selectedRowKeys: [] }),
});
return groupProjects;
}
@action
async fetchProjectListOnly() {
this.list.isLoading = true;
const result = await this.client.list();
this.projectsOnly = get(result, this.listResponseKey, []);
this.list.isLoading = false;
return result;
}
}
const globalProjectStore = new ProjectStore();
export default globalProjectStore;