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 { StorageCard, StorageDescription, ChildrenTable, new_page, new_card } from "../pages.jsx";
14 : import { fmt_size, validate_lvm2_name } from "../utils.js";
15 : import { dialog_open, TextInput, SizeSlider } from "../dialog.jsx";
16 : import { StorageLink } from "../storage-controls.jsx";
17 : import { grow_dialog } from "../block/resize.jsx";
18 :
19 : import { next_default_logical_volume_name } from "./utils.jsx";
20 : import { lvol_rename, lvol_delete } from "./block-logical-volume.jsx";
21 : import { make_lvm2_logical_volume_page } from "./volume-group.jsx";
22 :
23 113 : const _ = cockpit.gettext;
24 :
25 2 : export function make_thin_pool_logical_volume_page(parent, vgroup, lvol) {
26 1 : function create_thin() {
27 1 : dialog_open({
28 1 : Title: _("Create thin volume"),
29 1 : Fields: [
30 1 : TextInput("name", _("Name"),
31 1 : {
32 1 : value: next_default_logical_volume_name(client, vgroup, "lvol"),
33 1 : validate: validate_lvm2_name
34 1 : }),
35 1 : SizeSlider("size", _("Size"),
36 1 : {
37 1 : value: lvol.Size,
38 1 : max: lvol.Size * 3,
39 1 : allow_infinite: true,
40 1 : round: vgroup.ExtentSize
41 1 : })
42 1 : ],
43 1 : Action: {
44 1 : Title: _("Create"),
45 1 : action: function (vals) {
46 1 : return vgroup.CreateThinVolume(vals.name, vals.size, lvol.path, { });
47 1 : }
48 1 : }
49 1 : });
50 1 : }
51 :
52 2 : const pool_card = make_lvm2_thin_pool_card(null, vgroup, lvol);
53 :
54 2 : const thin_vols_card = new_card({
55 2 : title: _("Thinly provisioned LVM2 logical volumes"),
56 2 : next: pool_card,
57 2 : page_location: ["vg", vgroup.Name, lvol.Name],
58 2 : page_name: lvol.Name,
59 2 : page_size: lvol.Size,
60 2 : component: LVM2ThinPoolLogicalVolumeCard,
61 2 : props: { vgroup, lvol },
62 2 : actions: [
63 2 : {
64 2 : title: _("Create new thinly provisioned logical volume"),
65 2 : action: create_thin,
66 2 : tag: "pool",
67 2 : },
68 2 : ]
69 2 : });
70 :
71 2 : const p = new_page(parent, thin_vols_card);
72 :
73 2 : client.lvols_pool_members[lvol.path].forEach(member_lvol => {
74 2 : make_lvm2_logical_volume_page(p, vgroup, member_lvol);
75 2 : });
76 2 : }
77 :
78 2 : function make_lvm2_thin_pool_card(next, vgroup, lvol) {
79 2 : let grow_excuse = null;
80 2 : if (vgroup.FreeSize == 0)
81 1 : grow_excuse = _("Not enough space");
82 :
83 2 : const card = new_card({
84 2 : title: _("Pool for thinly provisioned LVM2 logical volumes"),
85 2 : next,
86 2 : component: LVM2ThinPoolCard,
87 2 : props: { vgroup, lvol },
88 2 : actions: [
89 2 : {
90 2 : title: _("Grow"),
91 1 : action: () => grow_dialog(client, lvol, { }),
92 2 : excuse: grow_excuse,
93 2 : },
94 2 : {
95 2 : title: _("Delete"),
96 1 : action: () => lvol_delete(lvol, card),
97 2 : danger: true,
98 2 : },
99 2 : ],
100 2 : });
101 2 : return card;
102 2 : }
103 :
104 1 : function perc(ratio) {
105 1 : return (ratio * 100).toFixed(0) + "%";
106 1 : }
107 :
108 1 : export const LVM2ThinPoolLogicalVolumeCard = ({ card, vgroup, lvol }) => {
109 1 : return (
110 1 : <StorageCard card={card}>
111 1 : <ChildrenTable
112 1 : emptyCaption={_("No logical volumes")}
113 1 : aria-label={_("Thinly provisioned LVM2 logical volumes")}
114 1 : page={card.page} />
115 1 : </StorageCard>);
116 1 : };
117 :
118 1 : export const LVM2ThinPoolCard = ({ card, vgroup, lvol }) => {
119 1 : return (
120 1 : <StorageCard card={card}>
121 1 : <CardBody>
122 1 : <DescriptionList className="pf-m-horizontal-on-sm">
123 1 : <StorageDescription title={_("Name")}
124 1 : value={lvol.Name}
125 0 : action={<StorageLink onClick={() => lvol_rename(lvol)}>
126 1 : {_("edit")}
127 1 : </StorageLink>} />
128 1 : <StorageDescription title={_("Size")} value={fmt_size(lvol.Size)} />
129 1 : <StorageDescription title={_("Data used")} value={perc(lvol.DataAllocatedRatio)} />
130 1 : <StorageDescription title={_("Metadata used")} value={perc(lvol.MetadataAllocatedRatio)} />
131 1 : </DescriptionList>
132 1 : </CardBody>
133 1 : </StorageCard>);
134 1 : };
|