From c5fa4cb717d87fe092d6670c5f9ec94e91ab314e Mon Sep 17 00:00:00 2001 From: resitdemir Date: Wed, 20 Mar 2024 08:17:26 +0000 Subject: [PATCH] feat: Adding log feature to Nova instance detail page. Log tab has been added to the Nova instance detail interface. Change-Id: I42005ff85d5c329aaf4a18a9d6181e901d091217 --- ...instance_log_to_nova-c14b17bdd1e4b708.yaml | 5 + .../containers/Instance/Detail/Log/index.jsx | 102 ++++++++++++++++++ .../containers/Instance/Detail/index.jsx | 6 ++ src/stores/nova/instance.js | 11 +- 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/feat_instance_log_to_nova-c14b17bdd1e4b708.yaml create mode 100644 src/pages/compute/containers/Instance/Detail/Log/index.jsx diff --git a/releasenotes/notes/feat_instance_log_to_nova-c14b17bdd1e4b708.yaml b/releasenotes/notes/feat_instance_log_to_nova-c14b17bdd1e4b708.yaml new file mode 100644 index 00000000..0d96cdeb --- /dev/null +++ b/releasenotes/notes/feat_instance_log_to_nova-c14b17bdd1e4b708.yaml @@ -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. \ No newline at end of file diff --git a/src/pages/compute/containers/Instance/Detail/Log/index.jsx b/src/pages/compute/containers/Instance/Detail/Log/index.jsx new file mode 100644 index 00000000..e88a2513 --- /dev/null +++ b/src/pages/compute/containers/Instance/Detail/Log/index.jsx @@ -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 = ` + + + ${title} + + +
${data.output}
+ + `; + newWindow.document.write(htmlContent); + newWindow.document.close(); + setLoading(false); + } + + return ( +
+
+ + + +

{t('Instance Console Log')}

+ + + + } + /> + + + +
+ + + +
+ +
+
+ +
+ {loading ? : logs ?
{logs}
: t('No Logs...')} +
+
+ ); +} \ No newline at end of file diff --git a/src/pages/compute/containers/Instance/Detail/index.jsx b/src/pages/compute/containers/Instance/Detail/index.jsx index 56b4d3af..3ae2516f 100644 --- a/src/pages/compute/containers/Instance/Detail/index.jsx +++ b/src/pages/compute/containers/Instance/Detail/index.jsx @@ -30,6 +30,7 @@ import SecurityGroup from './SecurityGroup'; import ActionLog from './ActionLog'; import Snapshots from '../../InstanceSnapshot'; import actionConfigs from '../actions'; +import Log from './Log'; export class InstanceDetail extends Base { get name() { @@ -148,6 +149,11 @@ export class InstanceDetail extends Base { key: 'action', component: ActionLog, }, + { + title: t('Logs'), + key: 'logs', + component: Log, + }, ]; if (this.enableCinder) { tabs.splice(1, 0, { diff --git a/src/stores/nova/instance.js b/src/stores/nova/instance.js index ad089b74..595f45ee 100644 --- a/src/stores/nova/instance.js +++ b/src/stores/nova/instance.js @@ -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 async fetchInterface({ id }) { this.interface.isLoading = true; @@ -226,7 +235,7 @@ export class ServerStore extends Base { sgItems = result.map((it) => this.mapperSecurityGroupRule(it.security_group) ); - } catch (e) {} + } catch (e) { } this.securityGroups = { data: sgItems || [], interfaces: ports,