Skip to content

Commit

Permalink
WIP - card alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Nov 16, 2023
1 parent 589c1e6 commit bb02458
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 523 deletions.
2 changes: 1 addition & 1 deletion pkg/storaged/block/create-pages.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function make_block_page(parent, block, card) {
(block_pvol && client.vgroups[block_pvol.VolumeGroup])) {
card = make_lvm2_physical_volume_card(card, block, content_block);
} else if (is_stratis) {
card = make_stratis_blockdev_card(parent, block, content_block);
card = make_stratis_blockdev_card(card, block, content_block);
} else if ((content_block.IdUsage == "raid") ||
(client.mdraids[content_block.MDRaidMember])) {
card = make_mdraid_disk_card(card, block, content_block);
Expand Down
2 changes: 1 addition & 1 deletion pkg/storaged/block/resize.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export function free_space_after_part(client, part) {
for (const p of parts) {
if (p.type == "free" && p.start == part.Offset + part.Size)
return p.size;
if (p.type == "card") {
if (p.type == "container") {
const s = find_it(p.partitions);
if (s)
return s;
Expand Down
14 changes: 6 additions & 8 deletions pkg/storaged/filesystem/filesystem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,12 @@ export const FilesystemCard = ({
const mounted = content_block && is_mounted(client, content_block);

return (
<StorageCard card={card}>
<StorageCard card={card}
alert={mismount_warning &&
<MismountAlert warning={mismount_warning}
fstab_config={fstab_config}
backing_block={backing_block}
content_block={content_block} /> }>
<CardBody>
<DescriptionList className="pf-m-horizontal-on-sm">
<SDesc title={_("Name")}
Expand All @@ -156,12 +161,5 @@ export const FilesystemCard = ({
}
</DescriptionList>
</CardBody>
{ mismount_warning &&
<CardBody>
<MismountAlert warning={mismount_warning}
fstab_config={fstab_config}
backing_block={backing_block} content_block={content_block} />
</CardBody>
}
</StorageCard>);
};
5 changes: 2 additions & 3 deletions pkg/storaged/filesystem/mismounting.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,13 @@ export const MismountAlert = ({ warning, fstab_config, forced_options, backing_b
fix_config_text = cockpit.format(_("Mount automatically on $0 on boot"), other);
fix_mount_text = _("Unmount now");
} else if (type == "locked-on-boot-mount") {
text = _("The filesystem is configured to be automatically mounted on boot but its encryption card will not be unlocked at that time.");
text = _("The filesystem is configured to be automatically mounted on boot but its encryption container will not be unlocked at that time.");
fix_config_text = _("Do not mount automatically on boot");
fix_mount_text = _("Unlock automatically on boot");
}

return (
<Alert variant="warning"
isInline
<Alert variant="warning" isInline
title={_("Inconsistent filesystem mount")}>
{text}
<div className="storage_alert_action_buttons">
Expand Down
293 changes: 1 addition & 292 deletions pkg/storaged/filesystem/mounting-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,13 @@
*/

import cockpit from "cockpit";
import React from "react";
import client from "../client.js";

import { Alert } from "@patternfly/react-core/dist/esm/components/Alert/index.js";
import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js";
import { DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm } from "@patternfly/react-core/dist/esm/components/DescriptionList/index.js";

import {
encode_filename,
parse_options, unparse_options, extract_option, reload_systemd,
set_crypto_options, set_crypto_auto_option, is_mounted_synch,
set_crypto_options, is_mounted_synch,
get_active_usage, teardown_active_usage,
validate_fsys_label,
} from "../utils.js";
import { StorageButton, StorageLink } from "../storage-controls.jsx";

import {
dialog_open,
Expand Down Expand Up @@ -346,286 +338,3 @@ export function mounting_dialog(client, block, mode, forced_options) {
]
});
}

export class FilesystemTab extends React.Component {
constructor(props) {
super(props);
this.onSamplesChanged = this.onSamplesChanged.bind(this);
}

onSamplesChanged() {
if (!this.props.client.busy)
this.setState({});
}

componentDidMount() {
this.props.client.fsys_sizes.addEventListener("changed", this.onSamplesChanged);
}

componentWillUnmount() {
this.props.client.fsys_sizes.removeEventListener("changed", this.onSamplesChanged);
}

render() {
const self = this;
const block = self.props.block;
const forced_options = self.props.forced_options;
const is_locked = block && block.IdUsage == 'crypto';
const block_fsys = block && self.props.client.blocks_fsys[block.path];
const stratis_fsys = block && self.props.client.blocks_stratis_fsys[block.path];

const mismounted_fsys_warning = self.props.warnings.find(w => w.warning == "mismounted-fsys");

function rename_dialog() {
dialog_open({
Title: _("Filesystem name"),
Fields: [
TextInput("name", _("Name"),
{
validate: name => validate_fsys_label(name, block.IdType),
value: block.IdLabel
})
],
Action: {
Title: _("Save"),
action: function (vals) {
return block_fsys.SetLabel(vals.name, {});
}
}
});
}

const is_filesystem_mounted = is_mounted(self.props.client, block);
const [old_config, old_dir, old_opts, old_parents] = get_fstab_config(block, true);
const split_options = parse_options(old_opts);
extract_option(split_options, "noauto");
const opt_ro = extract_option(split_options, "ro");
const opt_never_auto = extract_option(split_options, "x-cockpit-never-auto");
const opt_nofail = extract_option(split_options, "nofail");
const opt_netdev = extract_option(split_options, "_netdev");
const split_options_for_fix_config = split_options.slice();
if (forced_options)
for (const opt of forced_options)
extract_option(split_options, opt);

let mount_point_text = null;
if (old_dir) {
let opt_texts = [];
if (opt_ro)
opt_texts.push(_("read only"));
if (opt_never_auto)
opt_texts.push(_("never mount at boot"));
else if (opt_netdev)
opt_texts.push(_("after network"));
else if (opt_nofail)
opt_texts.push(_("ignore failure"));
else
opt_texts.push(_("stop boot on failure"));
opt_texts = opt_texts.concat(split_options);
if (opt_texts.length) {
mount_point_text = cockpit.format("$0 ($1)", old_dir, opt_texts.join(", "));
} else {
mount_point_text = old_dir;
}
}

let extra_text = null;
if (!is_filesystem_mounted) {
if (!old_dir)
extra_text = _("The filesystem has no permanent mount point.");
else
extra_text = _("The filesystem is not mounted.");
} else if (block.CryptoBackingDevice != "/") {
if (!opt_never_auto)
extra_text = _("The filesystem will be unlocked and mounted on the next boot. This might require inputting a passphrase.");
}

if (extra_text && mount_point_text)
extra_text = <><br />{extra_text}</>;

function fix_config() {
const { type, other } = mismounted_fsys_warning;

let opts = [];
if (type == "mount-on-boot")
opts.push("noauto");
if (type == "locked-on-boot-mount") {
opts.push("noauto");
opts.push("x-cockpit-never-auto");
}
if (opt_ro)
opts.push("ro");
if (opt_nofail)
opts.push("nofail");
if (opt_netdev)
opts.push("_netdev");

// Add the forced options, but only to new entries. We
// don't want to modify existing entries beyond what we
// say on the button.
if (!old_config && forced_options)
opts = opts.concat(forced_options);

const new_opts = unparse_options(opts.concat(split_options_for_fix_config));
let all_new_opts;
if (new_opts && old_parents)
all_new_opts = new_opts + "," + old_parents;
else if (new_opts)
all_new_opts = new_opts;
else
all_new_opts = old_parents;

let new_dir = old_dir;
if (type == "change-mount-on-boot" || type == "mounted-no-config")
new_dir = other;

const new_config = [
"fstab", {
fsname: old_config ? old_config[1].fsname : undefined,
dir: { t: 'ay', v: encode_filename(new_dir) },
type: { t: 'ay', v: encode_filename("auto") },
opts: { t: 'ay', v: encode_filename(all_new_opts || "defaults") },
freq: { t: 'i', v: 0 },
passno: { t: 'i', v: 0 },
"track-parents": { t: 'b', v: !old_config }
}];

function fixup_crypto_backing() {
const crypto_backing = (block.IdUsage == "crypto") ? block : client.blocks[block.CryptoBackingDevice];
if (!crypto_backing)
return;
if (type == "no-mount-on-boot")
return set_crypto_auto_option(crypto_backing, true);
if (type == "locked-on-boot-mount")
return set_crypto_auto_option(crypto_backing, false);
}

function fixup_fsys() {
if (old_config)
return block.UpdateConfigurationItem(old_config, new_config, {}).then(reload_systemd);
else
return block.AddConfigurationItem(new_config, {}).then(reload_systemd);
}

return fixup_fsys().then(fixup_crypto_backing);
}

function fix_mount() {
const { type, other } = mismounted_fsys_warning;
const crypto_backing = (block.IdUsage == "crypto") ? block : client.blocks[block.CryptoBackingDevice];
const crypto_backing_crypto = crypto_backing && client.blocks_crypto[crypto_backing.path];

function do_mount() {
if (crypto_backing == block)
mounting_dialog(client, block, "mount", forced_options);
else
return client.mount_at(block, old_dir);
}

function do_unmount() {
return client.unmount_at(old_dir)
.then(() => {
if (crypto_backing)
return crypto_backing_crypto.Lock({});
});
}

if (type == "change-mount-on-boot")
return client.unmount_at(other).then(() => client.mount_at(block, old_dir));
else if (type == "mount-on-boot")
return do_mount();
else if (type == "no-mount-on-boot")
return do_unmount();
else if (type == "mounted-no-config")
return do_unmount();
else if (type == "locked-on-boot-mount") {
if (crypto_backing)
return set_crypto_auto_option(crypto_backing, true);
}
}

let mismounted_section = null;
if (mismounted_fsys_warning) {
const { type, other } = mismounted_fsys_warning;
let text;
let fix_config_text;
let fix_mount_text;

if (type == "change-mount-on-boot") {
text = cockpit.format(_("The filesystem is currently mounted on $0 but will be mounted on $1 on the next boot."), other, old_dir);
fix_config_text = cockpit.format(_("Mount automatically on $0 on boot"), other);
fix_mount_text = cockpit.format(_("Mount on $0 now"), old_dir);
} else if (type == "mount-on-boot") {
text = _("The filesystem is currently not mounted but will be mounted on the next boot.");
fix_config_text = _("Do not mount automatically on boot");
fix_mount_text = _("Mount now");
} else if (type == "no-mount-on-boot") {
text = _("The filesystem is currently mounted but will not be mounted after the next boot.");
fix_config_text = _("Mount also automatically on boot");
fix_mount_text = _("Unmount now");
} else if (type == "mounted-no-config") {
text = cockpit.format(_("The filesystem is currently mounted on $0 but will not be mounted after the next boot."), other);
fix_config_text = cockpit.format(_("Mount automatically on $0 on boot"), other);
fix_mount_text = _("Unmount now");
} else if (type == "locked-on-boot-mount") {
text = _("The filesystem is configured to be automatically mounted on boot but its encryption card will not be unlocked at that time.");
fix_config_text = _("Do not mount automatically on boot");
fix_mount_text = _("Unlock automatically on boot");
}

mismounted_section = (
<>
<br />
<Alert variant="warning"
isInline
title={_("Inconsistent filesystem mount")}>
{text}
<div className="storage_alert_action_buttons">
<StorageButton onClick={fix_config}>{fix_config_text}</StorageButton>
{ fix_mount_text && <StorageButton onClick={fix_mount}>{fix_mount_text}</StorageButton> }
</div>
</Alert>
</>);
}

return (
<div>
<DescriptionList className="pf-m-horizontal-on-sm">
{ !stratis_fsys &&
<DescriptionListGroup>
<DescriptionListTerm>{_("Name")}</DescriptionListTerm>
<DescriptionListDescription>
<Flex>
<FlexItem>{this.props.block.IdLabel || "-"}</FlexItem>
<FlexItem>
<StorageLink onClick={rename_dialog}
excuse={is_locked ? _("Filesystem is locked") : null}>
{_("edit")}
</StorageLink>
</FlexItem>
</Flex>
</DescriptionListDescription>
</DescriptionListGroup> }
<DescriptionListGroup>
<DescriptionListTerm>{_("Mount point")}</DescriptionListTerm>
<DescriptionListDescription>
{ mount_point_text &&
<Flex>
<FlexItem>{ mount_point_text }</FlexItem>
<FlexItem>
<StorageLink onClick={() => mounting_dialog(self.props.client, block, "update",
forced_options)}>
{_("edit")}
</StorageLink>
</FlexItem>
</Flex>
}
{ extra_text }
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
{ mismounted_section }
</div>
);
}
}
Loading

0 comments on commit bb02458

Please sign in to comment.