Merge "feat: Action log in instance"

This commit is contained in:
Zuul 2021-08-27 06:33:21 +00:00 committed by Gerrit Code Review
commit 6e0e2724c4
7 changed files with 318 additions and 5 deletions

View File

@ -36,6 +36,7 @@
"Access Type": "Access Type",
"Access Type Setting": "Access Type Setting",
"Action": "Action",
"Action Log": "Action Log",
"Active": "Active",
"Active Status": "Active Status",
"Add": "Add",
@ -220,6 +221,8 @@
"Change password": "Change password",
"Change type": "Change type",
"Chassis ID": "Chassis ID",
"Check Can Live Migrate Destination": "Check Can Live Migrate Destination",
"Check Can Live Migrate Source": "Check Can Live Migrate Source",
"Check Complete": "Check Complete",
"Check Failed": "Check Failed",
"Check In Progress": "Check In Progress",
@ -244,17 +247,30 @@
"Close external gateway": "Close external gateway",
"Cloud": "Cloud",
"Cloud Platform": "Cloud Platform",
"Cold Migrate": "Cold Migrate",
"Commas , are not allowed to be in a tag name in order to simplify requests that specify lists of tags": "Commas , are not allowed to be in a tag name in order to simplify requests that specify lists of tags",
"Common Server": "Common Server",
"Compute": "Compute",
"Compute Hosts": "Compute Hosts",
"Compute Live Migration": "Compute Live Migration",
"Compute Live Resize Instance": "Compute Live Resize Instance",
"Compute Optimized": "Compute Optimized",
"Compute Optimized Info": "Compute Optimized Info",
"Compute Optimized Type": "Compute Optimized Type",
"Compute Optimized Type with GPU": "Compute Optimized Type with GPU",
"Compute Pause Instance": "Compute Pause Instance",
"Compute Reboot Instance": "Compute Reboot Instance",
"Compute Resume Instance": "Compute Resume Instance",
"Compute Service": "Compute Service",
"Compute Services": "Compute Services",
"Compute Start Instance": "Compute Start Instance",
"Compute Stop Instance": "Compute Stop Instance",
"Compute Suspend Instance": "Compute Suspend Instance",
"Compute Unpause Instance": "Compute Unpause Instance",
"Compute service:": "Compute service:",
"Conductor Live Migrate Instance": "Conductor Live Migrate Instance",
"Conductor Live Resize Instance": "Conductor Live Resize Instance",
"Conductor Migrate Server": "Conductor Migrate Server",
"Config Overview": "Config Overview",
"Configuration": "Configuration",
"Configuration Update": "Configuration Update",
@ -484,13 +500,13 @@
"Disk Info": "Disk Info",
"Disk Tag": "Disk Tag",
"Disk size is limited by the min disk of flavor, image, etc.": "Disk size is limited by the min disk of flavor, image, etc.",
"Do Build And Run Instance": "Do Build And Run Instance",
"Do not reset the normally mounted volume to the \"available\"、\"maintenance\" or \"error\" status. The reset state does not remove the volume from the instance. If you need to remove the volume from the instance, please go to the console of the corresponding project and use the \"detach\" operation.": "Do not reset the normally mounted volume to the \"available\"、\"maintenance\" or \"error\" status. The reset state does not remove the volume from the instance. If you need to remove the volume from the instance, please go to the console of the corresponding project and use the \"detach\" operation.",
"Do not set with a backend": "Do not set with a backend",
"Docker": "Docker",
"Domain": "Domain",
"Domain Detail": "Domain Detail",
"Domain Edit": "Domain Edit",
"Domain ID": "Domain ID",
"Domain ID/Name": "Domain ID/Name",
"Domain Manager": "Domain Manager",
"Domain Name": "Domain Name",
@ -569,6 +585,7 @@
"Encryption": "Encryption",
"Encryption Algorithm": "Encryption Algorithm",
"Encryption Info": "Encryption Info",
"End Time": "End Time",
"Endpoint Counts": "Endpoint Counts",
"Endpoints": "Endpoints",
"Engine ID": "Engine ID",
@ -585,6 +602,7 @@
"Error Restoring": "Error Restoring",
"Ether Type": "Ether Type",
"Event Time": "Event Time",
"Execution Result": "Execution Result",
"Expand Advanced Options": "Expand Advanced Options",
"Expired Time": "Expired Time",
"Extend Root Volume": "Extend Root Volume",
@ -614,6 +632,7 @@
"Fill In The Parameters": "Fill In The Parameters",
"Filter Project": "Filter Project",
"Fingerprint": "Fingerprint",
"Finish Resize": "Finish Resize",
"First time edit automatically creates health monitor When pool does not have a health monitor": "First time edit automatically creates health monitor When pool does not have a health monitor",
"Fixed IP": "Fixed IP",
"Fixed IP Address": "Fixed IP Address",
@ -888,6 +907,7 @@
"Listener Protocol": "Listener Protocol",
"Listener Protocol Port": "Listener Protocol Port",
"Live Migrate": "Live Migrate",
"Live Migration At Destination": "Live Migration At Destination",
"Load Balancer": "Load Balancer",
"Load Balancer Detail": "Load Balancer Detail",
"Load Balancer Name": "Load Balancer Name",
@ -1046,6 +1066,8 @@
"Open External Gateway": "Open External Gateway",
"Operating Status": "Operating Status",
"Operating System": "Operating System",
"Operation Name": "Operation Name",
"Operation Time": "Operation Time",
"Optimized Computing Type": "Optimized Computing Type",
"Optimized Parameters": "Optimized Parameters",
"Optional list": "Optional list",
@ -1190,11 +1212,13 @@
"Power State": "Power State",
"Powering Off": "Powering Off",
"Powering On": "Powering On",
"Pre Live Migration": "Pre Live Migration",
"Pre-Shared Key must be the same with Confirm Shared Key.": "Pre-Shared Key must be the same with Confirm Shared Key.",
"Pre-Shared Key(PSK) String": "Pre-Shared Key(PSK) String",
"Prefer": "Prefer",
"Prefer(Thread siblings are preferred)": "Prefer(Thread siblings are preferred)",
"Prefix": "Prefix",
"Prep Resize": "Prep Resize",
"Prepare Template": "Prepare Template",
"Previous": "Previous",
"Private": "Private",
@ -1281,6 +1305,7 @@
"Remove": "Remove",
"Remove Network": "Remove Network",
"Remove Router": "Remove Router",
"Request ID": "Request ID",
"Require": "Require",
"Require(Need multithreading)": "Require(Need multithreading)",
"Rescue": "Rescue",
@ -1290,6 +1315,7 @@
"Reset To Initial Value": "Reset To Initial Value",
"Reset failed, please retry": "Reset failed, please retry",
"Resize": "Resize",
"Resize Instance": "Resize Instance",
"Resized": "Resized",
"Resizing or Migrating": "Resizing or Migrating",
"Resource": "Resource",
@ -1320,7 +1346,6 @@
"Reverting Resize or Migrate": "Reverting Resize or Migrate",
"Role": "Role",
"Role Detail": "Role Detail",
"Role Id": "Role Id",
"Role Name": "Role Name",
"Role Power": "Role Power",
"Roles": "Roles",
@ -1376,6 +1401,7 @@
"Service Status": "Service Status",
"Service Unavailable (code: 503) ": "Service Unavailable (code: 503) ",
"Services": "Services",
"Set Admin Password": "Set Admin Password",
"Set Boot Device": "Set Boot Device",
"Set IP": "Set IP",
"Shared": "Shared",
@ -1407,9 +1433,11 @@
"Snapshot Detail": "Snapshot Detail",
"Snapshot Failed": "Snapshot Failed",
"Snapshot In Progress": "Snapshot In Progress",
"Snapshot Instance": "Snapshot Instance",
"Snapshot Name": "Snapshot Name",
"Snapshots": "Snapshots",
"Snapshotting": "Snapshotting",
"Soft Delete Instance": "Soft Delete Instance",
"Soft Deleted": "Soft Deleted",
"Soft Deleting": "Soft Deleting",
"Soft Power Off": "Soft Power Off",
@ -1437,6 +1465,7 @@
"Start Instance": "Start Instance",
"Start Source": "Start Source",
"Start Source Name": "Start Source Name",
"Start Time": "Start Time",
"Start auto refreshing data": "Start auto refreshing data",
"Start refreshing data every {num} seconds": "Start refreshing data every {num} seconds",
"Started At": "Started At",

View File

@ -36,6 +36,7 @@
"Access Type": "访问类型",
"Access Type Setting": "访问类型设置",
"Action": "操作",
"Action Log": "操作日志",
"Active": "运行中",
"Active Status": "运行",
"Add": "添加",
@ -220,6 +221,8 @@
"Change password": "修改密码",
"Change type": "修改类型",
"Chassis ID": "机架ID",
"Check Can Live Migrate Destination": "检查可以热迁移目标",
"Check Can Live Migrate Source": "检查可以热迁移源",
"Check Complete": "检查完成",
"Check Failed": "检查失败",
"Check In Progress": "正在检查",
@ -244,17 +247,30 @@
"Close external gateway": "关闭公网网关",
"Cloud": "云",
"Cloud Platform": "云平台",
"Cold Migrate": "冷迁移",
"Commas , are not allowed to be in a tag name in order to simplify requests that specify lists of tags": "标记名称中不允许使用逗号“,”,以简化指定标记列表的请求",
"Common Server": "云主机",
"Compute": "计算",
"Compute Hosts": "计算节点",
"Compute Live Migration": "计算热迁移",
"Compute Live Resize Instance": "完成在线配置调整",
"Compute Optimized": "计算型",
"Compute Optimized Info": "计算优化信息",
"Compute Optimized Type": "计算优化型",
"Compute Optimized Type with GPU": "GPU计算型",
"Compute Pause Instance": "暂停",
"Compute Reboot Instance": "重启",
"Compute Resume Instance": "恢复",
"Compute Service": "计算服务",
"Compute Services": "计算服务",
"Compute Start Instance": "启动",
"Compute Stop Instance": "关闭",
"Compute Suspend Instance": "挂起",
"Compute Unpause Instance": "恢复",
"Compute service:": "计算服务(nova):",
"Conductor Live Migrate Instance": "执行热迁移实例",
"Conductor Live Resize Instance": "执行在线配置调整",
"Conductor Migrate Server": "执行迁移服务器",
"Config Overview": "配置概览",
"Configuration": "配置",
"Configuration Update": "配置变更",
@ -484,13 +500,13 @@
"Disk Info": "硬盘信息",
"Disk Tag": "硬盘标签",
"Disk size is limited by the min disk of flavor, image, etc.": "根磁盘大小受云主机类型、镜像等的最小磁盘限制。",
"Do Build And Run Instance": "构建并运行实例",
"Do not reset the normally mounted volume to the \"available\"、\"maintenance\" or \"error\" status. The reset state does not remove the volume from the instance. If you need to remove the volume from the instance, please go to the console of the corresponding project and use the \"detach\" operation.": "请勿将正常的挂载中的云硬盘重置为“可用”、“维护”或”错误“状态。重置状态并不会将云硬盘从云主机上卸载下来。如果您需要将云硬盘从云主机上移除,请进入相应项目的控制台使用“解绑”操作。",
"Do not set with a backend": "不设置后端",
"Docker": "Docker",
"Domain": "域",
"Domain Detail": "域详情",
"Domain Edit": "编辑域",
"Domain ID": "域ID",
"Domain ID/Name": "域ID/名称",
"Domain Manager": "域管理员",
"Domain Name": "域名称",
@ -569,6 +585,7 @@
"Encryption": "加密",
"Encryption Algorithm": "加密算法",
"Encryption Info": "加密信息",
"End Time": "结束时间",
"Endpoint Counts": "端点数量",
"Endpoints": "服务地址",
"Engine ID": "引擎ID",
@ -585,6 +602,7 @@
"Error Restoring": "恢复错误",
"Ether Type": "以太网类型",
"Event Time": "发生时间",
"Execution Result": "执行结果",
"Expand Advanced Options": "展开高级选项",
"Expired Time": "到期时间",
"Extend Root Volume": "扩容根硬盘",
@ -614,6 +632,7 @@
"Fill In The Parameters": "参数填写",
"Filter Project": "筛选项目",
"Fingerprint": "指纹",
"Finish Resize": "完成调整",
"First time edit automatically creates health monitor When pool does not have a health monitor": "资源池无健康检查器时,首次编辑会自动创建健康检查器",
"Fixed IP": "内网IP",
"Fixed IP Address": "内网IP地址",
@ -888,6 +907,7 @@
"Listener Protocol": "监听器协议",
"Listener Protocol Port": "监听器协议端口",
"Live Migrate": "热迁移",
"Live Migration At Destination": "热迁移至目标地址",
"Load Balancer": "负载均衡",
"Load Balancer Detail": "负载均衡详情",
"Load Balancer Name": "负载均衡名称",
@ -1046,6 +1066,8 @@
"Open External Gateway": "开启公网网关",
"Operating Status": "操作状态",
"Operating System": "操作系统",
"Operation Name": "操作名称",
"Operation Time": "操作时间",
"Optimized Computing Type": "计算优化型",
"Optimized Parameters": "优化参数",
"Optional list": "可选列表",
@ -1190,11 +1212,13 @@
"Power State": "电源状态",
"Powering Off": "关闭中",
"Powering On": "启动中",
"Pre Live Migration": "预热迁移",
"Pre-Shared Key must be the same with Confirm Shared Key.": "确认共享密钥必须和预共享密钥一致。",
"Pre-Shared Key(PSK) String": "预共享密钥(PSK)",
"Prefer": "",
"Prefer(Thread siblings are preferred)": "Prefer最好有多线程, 若有的话则使用线程的兄弟节点)",
"Prefix": "前缀",
"Prep Resize": "预调整",
"Prepare Template": "准备模板",
"Previous": "上一步",
"Private": "私有",
@ -1281,6 +1305,7 @@
"Remove": "移除",
"Remove Network": "移除网络",
"Remove Router": "移除路由器",
"Request ID": "请求ID",
"Require": "强制",
"Require(Need multithreading)": "Require必须有多线程",
"Rescue": "救援",
@ -1290,6 +1315,7 @@
"Reset To Initial Value": "重置为初始值",
"Reset failed, please retry": "重置失败,请重试",
"Resize": "修改配置",
"Resize Instance": "修改配置",
"Resized": "已修改配置",
"Resizing or Migrating": "正在修改配置/迁移",
"Resource": "资源",
@ -1320,7 +1346,6 @@
"Reverting Resize or Migrate": "正在回滚修改配置/迁移",
"Role": "角色",
"Role Detail": "角色详情",
"Role Id": "角色Id",
"Role Name": "角色名称",
"Role Power": "角色权限",
"Roles": "角色",
@ -1376,6 +1401,7 @@
"Service Status": "管理状态",
"Service Unavailable (code: 503) ": "服务不可用错误码503 ",
"Services": "服务",
"Set Admin Password": "设置管理员密码",
"Set Boot Device": "设置引导设备",
"Set IP": "设置IP",
"Shared": "共享",
@ -1407,9 +1433,11 @@
"Snapshot Detail": "快照详情",
"Snapshot Failed": "生成快照失败",
"Snapshot In Progress": "快照进行中",
"Snapshot Instance": "创建云主机快照",
"Snapshot Name": "快照名称",
"Snapshots": "快照",
"Snapshotting": "创建快照中",
"Soft Delete Instance": "软删除云主机",
"Soft Deleted": "软删除",
"Soft Deleting": "软删除中",
"Soft Power Off": "软关机",
@ -1437,6 +1465,7 @@
"Start Instance": "启动云主机",
"Start Source": "启动源",
"Start Source Name": "启动源名称",
"Start Time": "开始时间",
"Start auto refreshing data": "启动自动刷新数据",
"Start refreshing data every {num} seconds": "启动每{num}秒自动刷新数据",
"Started At": "开始于",

View File

@ -0,0 +1,22 @@
import { observer, inject } from 'mobx-react';
import Base from 'containers/List';
import globalActionLogStore from 'stores/nova/action-log';
import { actionColumn } from 'resources/instance';
@inject('rootStore')
@observer
export default class ActionLog extends Base {
init() {
this.store = globalActionLogStore;
}
get rowKey() {
return 'request_id';
}
getColumns = () => actionColumn(this);
get hideSearch() {
return true;
}
}

View File

@ -27,6 +27,7 @@ import actionConfigsRecycleBin from 'pages/management/containers/RecycleBin/acti
import { toJS } from 'mobx';
import BaseDetail from './BaseDetail';
import SecurityGroup from './SecurityGroup';
import ActionLog from './ActionLog';
import actionConfigs from '../actions';
@inject('rootStore')
@ -141,6 +142,11 @@ export default class InstanceDetail extends Base {
key: 'securityGroup',
component: SecurityGroup,
},
{
title: t('Action Log'),
key: 'action',
component: ActionLog,
},
];
if (isIronicInstance(this.detailData)) {
return tabs.filter(

View File

@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import React from 'react';
import React, { useEffect, useState } from 'react';
import ImageType from 'components/ImageType';
import globalRootStore from 'stores/root';
import { getLocalTimeStr } from 'utils/time';
import { Table, Popover } from 'antd';
import globalActionLogStore from 'stores/nova/action-log';
import { Link } from 'react-router-dom';
import lockSvg from 'src/asset/image/lock.svg';
import unlockSvg from 'src/asset/image/unlock.svg';
@ -392,3 +396,178 @@ export const hasOnlineResizeFlavor = (item) => {
} = (item || {}).flavor_info || {};
return !!liveResize;
};
export const actionMap = {
attach_interface: t('Attach Interface'),
detach_interface: t('Detach Interface'),
attach_volume: t('Attach Volume'),
detach_volume: t('Detach Volume'),
create: t('Create'),
stop: t('Stop'),
reboot: t('Reboot'),
suspend: t('Suspend'),
resume: t('Resume'),
shelve: t('Shelve'),
unshelve: t('Unshelve'),
start: t('Start'),
lock: t('Lock'),
unlock: t('Unlock'),
pause: t('Pause'),
unpause: t('Unpause'),
createImage: t('Create Snapshot'),
resize: t('Extend Root Volume'),
confirmResize: t('Resize'),
'live-resize': t('Online Resize'),
extend_volume: t('Extend Volume'),
changePassword: t('Change Password'),
rebuild: t('Rebuild'),
migrate: t('Migrate'),
'live-migration': t('Live Migrate'),
delete: t('Delete'),
restore: t('Recover'),
};
export const actionEvent = {
compute_restore_instance: t('Resume Instance'),
compute_soft_delete_instance: t('Soft Delete Instance'),
compute_post_live_migration_at_destination: t(
'Live Migration At Destination'
),
compute_pre_live_migration: t('Pre Live Migration'),
compute_live_migration: t('Compute Live Migration'),
compute_check_can_live_migrate_source: t('Check Can Live Migrate Source'),
compute_check_can_live_migrate_destination: t(
'Check Can Live Migrate Destination'
),
conductor_live_migrate_instance: t('Conductor Live Migrate Instance'),
compute_confirm_resize: t('Resized'),
compute_finish_resize: t('Finish Resize'),
compute_resize_instance: t('Resize Instance'),
compute_prep_resize: t('Prep Resize'),
cold_migrate: t('Cold Migrate'),
conductor_migrate_server: t('Conductor Migrate Server'),
compute_rebuild_instance: t('Rebuild Instance'),
rebuild_server: t('Rebuild Instance'),
compute_set_admin_password: t('Set Admin Password'),
compute_extend_volume: t('Extend Volume'),
compute_live_resize_instance: t('Compute Live Resize Instance'),
conductor_live_resize_instance: t('Conductor Live Resize Instance'),
api_snapshot_instance: t('Snapshot Instance'),
api_lock: t('Lock'),
api_unlock: t('Unlock'),
compute_detach_volume: t('Detach Volume'),
compute_attach_volume: t('Attach Volume'),
compute_detach_interface: t('Detach Interface'),
compute_attach_interface: t('Attach Interface'),
compute__do_build_and_run_instance: t('Do Build And Run Instance'),
compute_suspend_instance: t('Compute Suspend Instance'),
compute_start_instance: t('Compute Start Instance'),
compute_stop_instance: t('Compute Stop Instance'),
compute_resume_instance: t('Compute Resume Instance'),
compute_pause_instance: t('Compute Pause Instance'),
compute_unpause_instance: t('Compute Unpause Instance'),
compute_reboot_instance: t('Compute Reboot Instance'),
};
function PopUpContent({ id, requestId }) {
const [event, setEvent] = useState([]);
const [isLoading, setLoaidng] = useState(false);
useEffect(() => {
(async function () {
setLoaidng(true);
const cb = await globalActionLogStore.fetchDetail({ id, requestId });
const { events = [] } = cb;
setEvent(events.reverse());
setLoaidng(false);
})();
}, []);
const columns = [
{
title: t('Operation Name'),
dataIndex: 'event',
key: 'event',
render: (value) => actionEvent[value],
},
{
title: t('Start Time'),
dataIndex: 'start_time',
key: 'start_time',
render: (value) => getLocalTimeStr(value),
},
{
title: t('End Time'),
dataIndex: 'finish_time',
key: 'finish_time',
render: (value) => (value ? getLocalTimeStr(value) : '-'),
},
{
title: t('Execution Result'),
dataIndex: 'result',
key: 'result',
render: (value) => (value === 'Success' ? t('Success') : '-'),
},
];
const table = (
<Table
columns={columns}
dataSource={event}
pagination={false}
loading={isLoading}
size="small"
rowKey="event"
/>
);
return table;
}
export const actionColumn = (self) => {
return [
{
title: t('Operation Name'),
dataIndex: 'action',
render: (value) => actionMap[value],
},
{
title: t('Project ID/Name'),
dataIndex: 'project_name',
isHideable: true,
hidden: !self.isAdminPage,
},
{
title: t('Operation Time'),
dataIndex: 'start_time',
valueRender: 'toLocalTimeMoment',
},
{
title: t('Request ID'),
dataIndex: 'request_id',
isHideable: true,
render: (value, record) => {
const content = (
<PopUpContent id={record.instance_uuid} requestId={value} />
);
return (
<>
{value && (
<Popover content={content} destroyTooltipOnHide trigger="click">
<span className="linkClass">{value}</span>
</Popover>
)}
</>
);
},
},
{
title: t('User ID'),
dataIndex: 'user_id',
isHideable: true,
hidden: !self.isAdminPage,
render: (value) => (
<Link to={`${self.getUrl('/identity/user')}/detail/${value}`}>
{value}
</Link>
),
},
];
};

View File

@ -0,0 +1,38 @@
// 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 client from 'client';
import Base from '../base';
export class ActionLogStore extends Base {
get client() {
return client.nova.servers.instanceActions;
}
get isSubResource() {
return true;
}
get paramsFunc() {
return () => ({});
}
detailFetchByClient(resourceParams) {
const { id, requestId } = resourceParams;
return this.client.show(id, requestId);
}
}
const globalActionLogStore = new ActionLogStore();
export default globalActionLogStore;

View File

@ -190,4 +190,14 @@
.tip{
color: @color-text-body;
}
.linkClass{
color:@blue-1;
cursor: pointer;
-moz-user-select:none; /*Firefox*/
-webkit-user-select:none; /*Webkit*/
-ms-user-select:none; /*IE10*/
-khtml-user-select:none; /*Early browsers*/
user-select:none;
}
}