LCOV - code coverage report
Current view: top level - pkg/storaged/drive - drive.jsx Coverage Total Hit
Test: cockpit Lines: 100.0 % 91 91
Test Date: 2026-06-25 09:20:42

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2023 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5              : 
       6          113 : import cockpit from "cockpit";
       7          113 : import React from "react";
       8              : import client from "../client";
       9              : 
      10              : import { CardBody } from "@patternfly/react-core/dist/esm/components/Card/index.js";
      11              : import { DescriptionList } from "@patternfly/react-core/dist/esm/components/DescriptionList/index.js";
      12              : 
      13              : import { HDDIcon, SSDIcon, MediaDriveIcon } from "../icons/gnome-icons.jsx";
      14              : import { StorageCard, StorageDescription, new_card, new_page } from "../pages.jsx";
      15              : import { block_name, drive_name, fmt_size_long, should_ignore } from "../utils.js";
      16              : import { make_block_page } from "../block/create-pages.jsx";
      17              : import { partitionable_block_actions } from "../partitions/actions.jsx";
      18              : import { isSmartOK, SmartCard } from "./smart-details.jsx";
      19              : 
      20          113 : const _ = cockpit.gettext;
      21              : 
      22          112 : export function make_drive_page(parent, drive) {
      23          112 :     let block = client.drives_block[drive.path];
      24              : 
      25           20 :     if (!block) {
      26              :         // A drive without a primary block device might be
      27              :         // a unconfigured multipath device.  Try to hobble
      28              :         // along here by arbitrarily picking one of the
      29              :         // multipath devices.
      30           20 :         block = client.drives_multipath_blocks[drive.path][0];
      31           20 :     }
      32              : 
      33          112 :     if (!block)
      34          112 :         return;
      35              : 
      36          112 :     if (should_ignore(client, block.path))
      37          112 :         return;
      38              : 
      39          109 :     let cls;
      40          109 :     if (client.drives_iscsi_session[drive.path])
      41           14 :         cls = "iscsi";
      42          109 :     else if (drive.MediaRemovable || drive.Media)
      43          102 :         cls = "media";
      44              :     else
      45           58 :         cls = (drive.RotationRate === 0) ? "ssd" : "hdd";
      46              : 
      47          109 :     const drive_title = {
      48          109 :         media: _("Media drive"),
      49          109 :         ssd: _("Solid State Drive"),
      50          109 :         hdd: _("Hard Disk Drive"),
      51          109 :         iscsi: _("iSCSI Drive"),
      52          109 :     };
      53              : 
      54          109 :     const drive_icon = {
      55          109 :         media: MediaDriveIcon,
      56          109 :         ssd: SSDIcon,
      57          109 :         hdd: HDDIcon,
      58          109 :     };
      59              : 
      60          109 :     let card = new_card({
      61           13 :         title: drive_title[cls] || _("Drive"),
      62          112 :         next: null,
      63          112 :         page_block: block,
      64          112 :         page_icon: drive_icon[cls],
      65          112 :         for_summary: true,
      66          112 :         id_extra: drive_name(drive),
      67          112 :         job_path: drive.path,
      68          112 :         component: DriveCard,
      69          112 :         props: { drive },
      70           13 :         actions: block.Size > 0 ? partitionable_block_actions(block) : [],
      71          112 :     });
      72              : 
      73          112 :     let smart_info, drive_type;
      74          102 :     if (client.drives_ata[drive.path]) {
      75          102 :         smart_info = client.drives_ata[drive.path];
      76          102 :         drive_type = "ata";
      77           13 :     } else if (client.nvme_controller[drive.path]) {
      78           13 :         smart_info = client.nvme_controller[drive.path];
      79           13 :         drive_type = "nvme";
      80           13 :     }
      81              : 
      82           14 :     if (smart_info !== undefined && (cls === "hdd" || cls === "ssd")) {
      83           14 :         card = new_card({
      84           14 :             title: _("Device health (SMART)"),
      85           14 :             next: card,
      86           14 :             has_danger: !isSmartOK(drive_type, smart_info),
      87           14 :             has_warning: (smart_info.SmartNumBadSectors > 0 || smart_info.SmartNumAttributesFailing > 0),
      88           14 :             component: SmartCard,
      89           14 :             props: { smart_info, drive_type },
      90           14 :         });
      91           14 :     }
      92              : 
      93          109 :     if (block.Size > 0) {
      94          109 :         make_block_page(parent, block, card, { partitionable: true });
      95           13 :     } else {
      96           13 :         new_page(parent, card);
      97           13 :     }
      98          112 : }
      99              : 
     100           37 : const DriveCard = ({ card, page, drive }) => {
     101           37 :     const block = client.drives_block[drive.path];
     102           37 :     const multipath_blocks = client.drives_multipath_blocks[drive.path];
     103              : 
     104           37 :     return (
     105           37 :         <StorageCard card={card}>
     106           37 :             <CardBody>
     107           37 :                 <DescriptionList className="pf-m-horizontal-on-sm">
     108           37 :                     <StorageDescription title={_("Vendor")} value={drive.Vendor} />
     109           37 :                     <StorageDescription title={_("Model")} value={drive.Model} />
     110           37 :                     <StorageDescription title={_("Firmware version")} value={drive.Revision} />
     111           37 :                     <StorageDescription title={_("Serial number")} value={drive.Serial} />
     112           37 :                     <StorageDescription title={_("World wide name")} value={drive.WWN} />
     113           37 :                     <StorageDescription title={_("Capacity")}>
     114           37 :                         {drive.Size
     115           37 :                             ? fmt_size_long(drive.Size)
     116            2 :                             : _("No media inserted")
     117              :                         }
     118           37 :                     </StorageDescription>
     119           37 :                     <StorageDescription title={_("Device file")}
     120            3 :                            value={block ? block_name(block) : "-"} />
     121           37 :                     { multipath_blocks.length > 0 &&
     122            3 :                     <StorageDescription title={_("Multipathed devices")}
     123            3 :                              value={multipath_blocks.map(block_name).join(" ")} />
     124              :                     }
     125           37 :                 </DescriptionList>
     126           37 :             </CardBody>
     127           37 :         </StorageCard>
     128              :     );
     129           37 : };
        

Generated by: LCOV version 2.0-1