LCOV - code coverage report
Current view: top level - pkg/storaged/filesystem - filesystem.jsx Coverage Total Hit
Test: cockpit Lines: 98.9 % 93 92
Test Date: 2026-07-13 10:00:01

            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              : import { useEvent } from "hooks";
      13              : 
      14              : import {
      15              :     block_name, fmt_size, validate_fsys_label
      16              : } from "../utils.js";
      17              : import {
      18              :     dialog_open, TextInput,
      19              : } from "../dialog.jsx";
      20              : import { StorageLink, StorageUsageBar, StorageSize } from "../storage-controls.jsx";
      21              : import { StorageCard, StorageDescription, new_card, useIsNarrow } from "../pages.jsx";
      22              : 
      23              : import { std_format_action } from "../block/actions.jsx";
      24              : import { is_mounted, MountPoint, mount_point_text, edit_mount_point } from "./utils.jsx";
      25              : import { mounting_dialog } from "./mounting-dialog.jsx";
      26              : import { check_mismounted_fsys, MismountAlert } from "./mismounting.jsx";
      27              : 
      28          113 : const _ = cockpit.gettext;
      29              : 
      30              : /* This page is used in a variety of cases, which can be distinguished
      31              :  * by looking at the "backing_block" and "content_block" parameters:
      32              :  *
      33              :  * not-encrypted: backing_block == content_block,
      34              :  *                content_block != null
      35              :  *
      36              :  * encrypted and unlocked: backing_block != content_block,
      37              :  *                         backing_block != null,
      38              :  *                         content_block != null
      39              :  *
      40              :  * encrypted and locked: backing_block != null,
      41              :  *                       content_block == null
      42              :  *
      43              :  * "backing_block" is always non-null and always refers to the block
      44              :  * device that we want to talk about in the UI. "content_block" (when
      45              :  * non-null) is the block that we need to use for filesystem related
      46              :  * actions, such as mounting. It's the one with the
      47              :  * "o.fd.UDisks2.Filesystem" interface.
      48              :  *
      49              :  * When "content_block" is null, then "backing_block" is a locked LUKS
      50              :  * device, but we could figure out the fstab entry for the filesystem
      51              :  * that's on it.
      52              :  */
      53              : 
      54          101 : const MountPointUsageBar = ({ mount_point, block, short }) => {
      55          101 :     useEvent(client.fsys_sizes, "changed");
      56          101 :     const narrow = useIsNarrow();
      57              : 
      58          101 :     const stats = client.fsys_sizes.data[mount_point];
      59          101 :     if (stats)
      60           98 :         return <StorageUsageBar stats={stats} critical={0.95} block={block_name(block)} short={short} />;
      61          101 :     else if (short && !narrow)
      62           28 :         return <StorageSize size={block.Size} />;
      63              :     else
      64           28 :         return fmt_size(block.Size);
      65          101 : };
      66              : 
      67          106 : export function make_filesystem_card(next, backing_block, content_block, fstab_config) {
      68          106 :     const [, mount_point] = fstab_config;
      69          106 :     const mismount_warning = check_mismounted_fsys(backing_block, content_block, fstab_config);
      70          106 :     const mounted = content_block && is_mounted(client, content_block);
      71              : 
      72          106 :     const mp_text = mount_point_text(mount_point, mounted);
      73          106 :     if (mp_text == null)
      74           12 :         return null;
      75              : 
      76          106 :     return new_card({
      77           22 :         title: content_block ? cockpit.format(_("$0 filesystem"), content_block.IdType) : _("Filesystem"),
      78          106 :         location: mp_text,
      79          106 :         next,
      80          106 :         page_size: <MountPointUsageBar mount_point={mount_point} block={backing_block} short />,
      81          106 :         has_warning: !!mismount_warning,
      82          106 :         component: FilesystemCard,
      83          106 :         props: { backing_block, content_block, fstab_config, mismount_warning },
      84          106 :         actions: [
      85          106 :             client.in_anaconda_mode() &&
      86            0 :                 { title: _("Edit mount point"), action: () => edit_mount_point(content_block || backing_block) },
      87          106 :             content_block && mounted
      88            8 :                 ? { title: _("Unmount"), action: () => mounting_dialog(client, content_block, "unmount") }
      89          106 :                 : null,
      90          106 :             !(content_block && mounted) && !client.in_anaconda_mode()
      91            4 :                 ? { title: _("Mount"), action: () => mounting_dialog(client, content_block || backing_block, "mount") }
      92          106 :                 : null,
      93          106 :             std_format_action(backing_block, content_block),
      94          106 :         ]
      95          106 :     });
      96          106 : }
      97              : 
      98           37 : export const FilesystemCard = ({
      99           37 :     card, backing_block, content_block, fstab_config, mismount_warning
     100           37 : }) => {
     101            1 :     function rename_dialog() {
     102              :         // assert(content_block)
     103            1 :         const block_fsys = client.blocks_fsys[content_block.path];
     104              : 
     105            1 :         dialog_open({
     106            1 :             Title: _("Filesystem name"),
     107            1 :             Fields: [
     108            1 :                 TextInput("name", _("Name"),
     109            1 :                           {
     110            1 :                               validate: name => validate_fsys_label(name, content_block.IdType),
     111            1 :                               value: content_block.IdLabel
     112            1 :                           })
     113            1 :             ],
     114            1 :             Action: {
     115            1 :                 Title: _("Save"),
     116            1 :                 action: function (vals) {
     117            1 :                     return block_fsys.SetLabel(vals.name, {});
     118            1 :                 }
     119            1 :             }
     120            1 :         });
     121            1 :     }
     122              : 
     123           37 :     const [, mount_point] = fstab_config;
     124           36 :     const mounted = content_block && is_mounted(client, content_block);
     125              : 
     126           37 :     return (
     127           37 :         <StorageCard card={card}>
     128           37 :             <CardBody>
     129           37 :                 <DescriptionList className="pf-m-horizontal-on-sm">
     130           37 :                     <StorageDescription title={_("Name")}
     131           18 :                            value={content_block?.IdLabel || "-"}
     132           37 :                            action={<StorageLink onClick={rename_dialog}
     133            8 :                                                 excuse={!content_block ? _("Filesystem is locked") : null}>
     134           37 :                                {_("edit")}
     135           37 :                            </StorageLink>} />
     136           37 :                     <StorageDescription title={_("Mount point")}>
     137           37 :                         <MountPoint fstab_config={fstab_config}
     138           37 :                                     backing_block={backing_block} content_block={content_block} />
     139           37 :                     </StorageDescription>
     140           37 :                     { mounted &&
     141           25 :                     <StorageDescription title={_("Usage")}>
     142           25 :                         <MountPointUsageBar mount_point={mount_point} block={backing_block} />
     143           25 :                     </StorageDescription>
     144              :                     }
     145           37 :                 </DescriptionList>
     146           37 :             </CardBody>
     147           37 :             { mismount_warning &&
     148            9 :             <CardBody>
     149            9 :                 <MismountAlert warning={mismount_warning}
     150            9 :                                  fstab_config={fstab_config}
     151            9 :                                  backing_block={backing_block} content_block={content_block} />
     152            9 :             </CardBody>
     153              :             }
     154           37 :         </StorageCard>);
     155           37 : };
        

Generated by: LCOV version 2.0-1