LCOV - code coverage report
Current view: top level - pkg/systemd/overview-cards - systemInformationCard.jsx Coverage Total Hit
Test: cockpit Lines: 85.7 % 105 90
Test Date: 2026-06-25 09:20:42

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2019 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5           95 : import React from 'react';
       6              : import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
       7              : import { Card, CardBody, CardFooter, CardTitle } from "@patternfly/react-core/dist/esm/components/Card/index.js";
       8              : 
       9           95 : import cockpit from "cockpit";
      10              : import * as machine_info from "machine-info.js";
      11              : import * as timeformat from "timeformat";
      12              : 
      13              : import "./systemInformationCard.scss";
      14              : 
      15           95 : const _ = cockpit.gettext;
      16              : 
      17           95 : export class SystemInformationCard extends React.Component {
      18           95 :     constructor(props) {
      19           95 :         super(props);
      20              : 
      21           95 :         this.state = {
      22           95 :             machineID: null,
      23           95 :             model: null,
      24           95 :             assetTag: null,
      25           95 :             systemUptime: null,
      26           95 :         };
      27           95 :         this.getSystemUptime = this.getSystemUptime.bind(this);
      28           95 :     }
      29              : 
      30           95 :     componentDidMount() {
      31           95 :         this.getDMIInfo();
      32           95 :         this.getMachineId();
      33           95 :         this.getSystemUptime();
      34              : 
      35           95 :         this.uptimeTimer = setInterval(this.getSystemUptime, 60000);
      36           95 :     }
      37              : 
      38            0 :     componentWillUnmount() {
      39            0 :         clearInterval(this.uptimeTimer); // not-covered: callers currently never unmount this
      40            0 :     }
      41              : 
      42           95 :     getMachineId() {
      43           95 :         const machine_id = cockpit.file("/etc/machine-id");
      44              : 
      45           95 :         machine_id.read()
      46           95 :                 .then(machineID => this.setState({ machineID }))
      47            0 :                 .catch(ex => console.error("Error reading machine id", ex.toString())) // not-covered: OS error
      48           95 :                 .finally(machine_id.close);
      49           95 :     }
      50              : 
      51           95 :     getDMIInfo() {
      52           95 :         machine_info.dmi_info()
      53           87 :                 .then(fields => {
      54           87 :                     let vendor = fields.sys_vendor;
      55           87 :                     let name = fields.product_name;
      56           17 :                     if (!vendor || !name) {
      57           17 :                         vendor = fields.board_vendor;
      58           17 :                         name = fields.board_name;
      59           17 :                     }
      60           87 :                     if (!vendor || !name)
      61           17 :                         this.setState({ model: null });
      62              :                     else
      63           87 :                         this.setState({ model: vendor + " " + name });
      64              : 
      65           87 :                     this.setState({ assetTag: fields.product_serial || fields.chassis_serial });
      66           87 :                 })
      67            0 :                 .catch(ex => {
      68              :                     // try DeviceTree
      69            0 :                     machine_info.devicetree_info() // not-covered: coverage only runs on x86_64
      70            0 :                             .then(fields => this.setState({ assetTag: fields.serial, model: fields.model }))
      71            0 :                             .catch(dmiex => {
      72            0 :                                 console.debug("couldn't read dmi info: " + ex.toString());
      73            0 :                                 console.debug("couldn't read DeviceTree info: " + dmiex.toString());
      74            0 :                                 this.setState({ assetTag: null, model: null });
      75            0 :                             });
      76            0 :                 });
      77           95 :     }
      78              : 
      79           95 :     getSystemUptime() {
      80           95 :         cockpit.file("/proc/uptime").read()
      81           95 :                 .then(content => {
      82           95 :                     const uptime = parseFloat(content.split(' ')[0]);
      83           95 :                     const bootTime = new Date().valueOf() - uptime * 1000;
      84           95 :                     this.setState({ systemUptime: timeformat.distanceToNow(bootTime) });
      85           95 :                 })
      86            0 :                 .catch(ex => console.error("Error reading system uptime", ex.toString())); // not-covered: OS error
      87           95 :     }
      88              : 
      89           95 :     render() {
      90           95 :         return (
      91           95 :             <Card className="system-information">
      92           95 :                 <CardTitle>{_("System information")}</CardTitle>
      93           95 :                 <CardBody>
      94           95 :                     <table className="pf-v6-c-table pf-m-grid-md pf-m-compact">
      95           95 :                         <tbody className="pf-v6-c-table__tbody">
      96           87 :                             {this.state.model && <tr className="pf-v6-c-table__tr">
      97           87 :                                 <th className="pf-v6-c-table__th" scope="row">{_("Model")}</th>
      98           87 :                                 <td className="pf-v6-c-table__td">
      99           87 :                                     <div id="system_information_hardware_text">{this.state.model}</div>
     100           87 :                                 </td>
     101           87 :                             </tr>}
     102           17 :                             {this.state.assetTag && <tr className="pf-v6-c-table__tr">
     103           17 :                                 <th className="pf-v6-c-table__th" scope="row">{_("Asset tag")}</th>
     104           17 :                                 <td className="pf-v6-c-table__td">
     105           17 :                                     <div id="system_information_asset_tag_text">{this.state.assetTag}</div>
     106           17 :                                 </td>
     107           17 :                             </tr>}
     108           95 :                             <tr className="pf-v6-c-table__tr">
     109           95 :                                 <th className="pf-v6-c-table__th system-information-machine-id" scope="row">{_("Machine ID")}</th>
     110           95 :                                 <td className="pf-v6-c-table__td">
     111           95 :                                     <div id="system_machine_id">{this.state.machineID}</div>
     112           95 :                                 </td>
     113           95 :                             </tr>
     114           95 :                             <tr className="pf-v6-c-table__tr">
     115           95 :                                 <th className="pf-v6-c-table__th system-information-uptime" scope="row">{_("Up since")}</th>
     116           95 :                                 <td className="pf-v6-c-table__td">
     117           95 :                                     <div id="system_uptime">{this.state.systemUptime}</div>
     118           95 :                                 </td>
     119           95 :                             </tr>
     120           95 :                         </tbody>
     121           95 :                     </table>
     122           95 :                 </CardBody>
     123           95 :                 <CardFooter>
     124            0 :                     <Button isInline variant="link" component="a" onClick={ev => { ev.preventDefault(); cockpit.jump("/system/hwinfo", cockpit.transport.host) }}>
     125           95 :                         {_("View hardware details")}
     126           95 :                     </Button>
     127           95 :                 </CardFooter>
     128           95 :             </Card>
     129              :         );
     130           95 :     }
     131           95 : }
        

Generated by: LCOV version 2.0-1