LCOV - code coverage report
Current view: top level - pkg/storaged/lvm2 - physical-volume.jsx Coverage Total Hit
Test: cockpit Lines: 89.8 % 88 79
Test Date: 2026-07-03 14:25:32

            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 { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
      11              : import { CardBody } from "@patternfly/react-core/dist/esm/components/Card/index.js";
      12              : import { DescriptionList } from "@patternfly/react-core/dist/esm/components/DescriptionList/index.js";
      13              : 
      14              : import { StorageCard, StorageDescription, new_card, register_crossref } from "../pages.jsx";
      15              : import { std_format_action } from "../block/actions.jsx";
      16              : import { std_lock_action } from "../crypto/actions.jsx";
      17              : import { StorageUsageBar } from "../storage-controls.jsx";
      18              : 
      19          113 : const _ = cockpit.gettext;
      20              : 
      21           25 : export function make_lvm2_physical_volume_card(next, backing_block, content_block) {
      22           25 :     const block_pvol = client.blocks_pvol[content_block.path];
      23           25 :     const vgroup = block_pvol && client.vgroups[block_pvol.VolumeGroup];
      24              : 
      25           25 :     const pv_card = new_card({
      26           25 :         title: _("LVM2 physical volume"),
      27           25 :         location: {
      28           25 :             label: vgroup ? vgroup.Name : null,
      29           25 :             to: vgroup ? ["vg", vgroup.Name] : null,
      30           25 :         },
      31           25 :         next,
      32           25 :         page_size: (block_pvol
      33           25 :             ? <StorageUsageBar stats={[block_pvol.Size - block_pvol.FreeSize, block_pvol.Size]} short />
      34           25 :             : backing_block.Size),
      35           25 :         component: LVM2PhysicalVolumeCard,
      36           25 :         props: { backing_block, content_block },
      37           25 :         actions: [
      38           25 :             std_lock_action(backing_block, content_block),
      39           25 :             std_format_action(backing_block, content_block),
      40           25 :         ]
      41           25 :     });
      42              : 
      43            1 :     function pvol_remove() {
      44            1 :         return vgroup.RemoveDevice(block_pvol.path, true, {});
      45            1 :     }
      46              : 
      47            0 :     function pvol_empty_and_remove() {
      48            0 :         return (vgroup.EmptyDevice(block_pvol.path, {})
      49            0 :                 .then(function() {
      50            0 :                     vgroup.RemoveDevice(block_pvol.path, true, {});
      51            0 :                 }));
      52            0 :     }
      53              : 
      54           25 :     if (vgroup) {
      55            0 :         const pvols = client.vgroups_pvols[vgroup.path] || [];
      56           25 :         let remove_action = null;
      57           25 :         let remove_excuse = null;
      58              : 
      59            3 :         if (vgroup.MissingPhysicalVolumes && vgroup.MissingPhysicalVolumes.length > 0) {
      60            3 :             remove_excuse = _("Volume group is missing physical volumes");
      61            3 :         } else if (pvols.length === 1) {
      62           25 :             remove_excuse = _("Last cannot be removed");
      63            8 :         } else if (block_pvol.FreeSize < block_pvol.Size) {
      64            8 :             if (block_pvol.Size <= vgroup.FreeSize)
      65            5 :                 remove_action = pvol_empty_and_remove;
      66              :             else
      67            7 :                 remove_excuse = _("Not enough free space");
      68            7 :         } else {
      69            9 :             remove_action = pvol_remove;
      70            9 :         }
      71              : 
      72           25 :         register_crossref({
      73           25 :             key: vgroup,
      74           25 :             card: pv_card,
      75           25 :             actions: [
      76           25 :                 {
      77           25 :                     title: _("Remove"),
      78           25 :                     action: remove_action,
      79           25 :                     excuse: remove_excuse,
      80           25 :                 },
      81           25 :             ],
      82           25 :             size: <StorageUsageBar stats={[block_pvol.Size - block_pvol.FreeSize, block_pvol.Size]} short />,
      83           25 :         });
      84           25 :     }
      85              : 
      86           25 :     return pv_card;
      87           25 : }
      88              : 
      89            1 : export const LVM2PhysicalVolumeCard = ({ card, backing_block, content_block }) => {
      90            1 :     const block_pvol = client.blocks_pvol[content_block.path];
      91            1 :     const vgroup = block_pvol && client.vgroups[block_pvol.VolumeGroup];
      92              : 
      93            1 :     return (
      94            1 :         <StorageCard card={card}>
      95            1 :             <CardBody>
      96            1 :                 <DescriptionList className="pf-m-horizontal-on-sm">
      97            1 :                     <StorageDescription title={_("Volume group")}>
      98            1 :                         {vgroup
      99            1 :                             ? <Button variant="link" isInline role="link"
     100            0 :                                    onClick={() => cockpit.location.go(["vg", vgroup.Name])}>
     101            1 :                                 {vgroup.Name}
     102            1 :                             </Button>
     103            0 :                             : "-"
     104              :                         }
     105            1 :                     </StorageDescription>
     106            1 :                     <StorageDescription title={_("UUID")} value={content_block.IdUUID} />
     107            1 :                     { block_pvol &&
     108            1 :                     <StorageDescription title={_("Usage")}>
     109            1 :                         <StorageUsageBar key="s"
     110            1 :                                            stats={[block_pvol.Size - block_pvol.FreeSize,
     111            1 :                                                block_pvol.Size]} />
     112            1 :                     </StorageDescription>
     113              :                     }
     114            1 :                 </DescriptionList>
     115            1 :             </CardBody>
     116            1 :         </StorageCard>);
     117            1 : };
        

Generated by: LCOV version 2.0-1