feat: Adding log feature to Nova instance detail page.
Log tab has been added to the Nova instance detail interface. Change-Id: I42005ff85d5c329aaf4a18a9d6181e901d091217
This commit is contained in:
parent
e1a9d17f4c
commit
c5fa4cb717
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
feat: Adding log feature to Nova instance detail page.
|
||||||
|
Log tab has been added to the Nova instance detail interface.
|
102
src/pages/compute/containers/Instance/Detail/Log/index.jsx
Normal file
102
src/pages/compute/containers/Instance/Detail/Log/index.jsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import globalInstanceLogStore from 'src/stores/nova/instance';
|
||||||
|
import { Button, Col, Form, InputNumber, Row, Skeleton } from 'antd';
|
||||||
|
import { SearchOutlined, SettingOutlined } from '@ant-design/icons';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import styles from 'src/components/Tables/Base/index.less';
|
||||||
|
|
||||||
|
export default function Log(props) {
|
||||||
|
const [logs, setLogs] = useState('');
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getLogs(35);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getLogs = async (tailSize) => {
|
||||||
|
setLoading(true);
|
||||||
|
const data = await globalInstanceLogStore.fetchLogs(props.detail.id, tailSize);
|
||||||
|
setLogs(data.output);
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
function onFinish(value) {
|
||||||
|
getLogs(value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function viewFullLog() {
|
||||||
|
setLoading(true);
|
||||||
|
const data = await globalInstanceLogStore.fetchLogs(props.detail.id, null);
|
||||||
|
const newWindow = window.open('console', '_blank');
|
||||||
|
const title = t('Console Log');
|
||||||
|
const htmlContent = `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>${title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre>${data.output}</pre>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
newWindow.document.write(htmlContent);
|
||||||
|
newWindow.document.close();
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Form
|
||||||
|
initialValues={{ number: 35 }}
|
||||||
|
onFinish={onFinish}>
|
||||||
|
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col className="gutter-row" span={16}>
|
||||||
|
<h2 style={{ paddingLeft: 16 }}>{t('Instance Console Log')}</h2>
|
||||||
|
</Col>
|
||||||
|
<Col className="gutter-row" span={4}>
|
||||||
|
<Form.Item name="number" label={t('Log Length')}>
|
||||||
|
<InputNumber
|
||||||
|
min={1}
|
||||||
|
max={100000}
|
||||||
|
placeholder={t("Log Length")}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
addonafter={<SettingOutlined />}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col className="gutter-row" span={4}>
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
styles['table-header-btns'])}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit">
|
||||||
|
<SearchOutlined />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => viewFullLog()}>
|
||||||
|
{t("View Full Log")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
margin: 'auto 16px 16px 16px',
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: '#90a4ae',
|
||||||
|
borderRadius: 4,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{loading ? <Skeleton loading={loading} active /> : logs ? <pre>{logs}</pre> : t('No Logs...')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -30,6 +30,7 @@ import SecurityGroup from './SecurityGroup';
|
|||||||
import ActionLog from './ActionLog';
|
import ActionLog from './ActionLog';
|
||||||
import Snapshots from '../../InstanceSnapshot';
|
import Snapshots from '../../InstanceSnapshot';
|
||||||
import actionConfigs from '../actions';
|
import actionConfigs from '../actions';
|
||||||
|
import Log from './Log';
|
||||||
|
|
||||||
export class InstanceDetail extends Base {
|
export class InstanceDetail extends Base {
|
||||||
get name() {
|
get name() {
|
||||||
@ -148,6 +149,11 @@ export class InstanceDetail extends Base {
|
|||||||
key: 'action',
|
key: 'action',
|
||||||
component: ActionLog,
|
component: ActionLog,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('Logs'),
|
||||||
|
key: 'logs',
|
||||||
|
component: Log,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
if (this.enableCinder) {
|
if (this.enableCinder) {
|
||||||
tabs.splice(1, 0, {
|
tabs.splice(1, 0, {
|
||||||
|
@ -179,6 +179,15 @@ export class ServerStore extends Base {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchLogs(id, tailSize) {
|
||||||
|
const logs = await this.client.action(id, {
|
||||||
|
"os-getConsoleOutput": {
|
||||||
|
"length": tailSize
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return logs;
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async fetchInterface({ id }) {
|
async fetchInterface({ id }) {
|
||||||
this.interface.isLoading = true;
|
this.interface.isLoading = true;
|
||||||
@ -226,7 +235,7 @@ export class ServerStore extends Base {
|
|||||||
sgItems = result.map((it) =>
|
sgItems = result.map((it) =>
|
||||||
this.mapperSecurityGroupRule(it.security_group)
|
this.mapperSecurityGroupRule(it.security_group)
|
||||||
);
|
);
|
||||||
} catch (e) {}
|
} catch (e) { }
|
||||||
this.securityGroups = {
|
this.securityGroups = {
|
||||||
data: sgItems || [],
|
data: sgItems || [],
|
||||||
interfaces: ports,
|
interfaces: ports,
|
||||||
|
Loading…
Reference in New Issue
Block a user