From 8fcf63f26902232617822f7b37cf7933fa726649 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Thu, 28 Sep 2023 10:34:26 +0300 Subject: [PATCH] storage: Move some fstab/crypttab to utils.js --- pkg/storaged/content-views.jsx | 39 ++------------- pkg/storaged/crypto-keyslots.jsx | 6 +-- pkg/storaged/crypto-tab.jsx | 34 ++----------- pkg/storaged/format-dialog.jsx | 35 +++----------- pkg/storaged/fsys-tab.jsx | 9 ++-- pkg/storaged/nfs-details.jsx | 14 +++--- pkg/storaged/utils.js | 82 ++++++++++++++++++++++++++++++++ test/reference | 2 +- 8 files changed, 107 insertions(+), 114 deletions(-) diff --git a/pkg/storaged/content-views.jsx b/pkg/storaged/content-views.jsx index 23531db5c8e2..836d123f9355 100644 --- a/pkg/storaged/content-views.jsx +++ b/pkg/storaged/content-views.jsx @@ -24,6 +24,7 @@ import { init_active_usage_processes } from "./dialog.jsx"; import * as utils from "./utils.js"; +import { set_crypto_auto_option } from "./utils.js"; import React from "react"; import { Card, CardBody, CardHeader, CardTitle } from '@patternfly/react-core/dist/esm/components/Card/index.js'; @@ -38,13 +39,11 @@ import { ListingTable } from "cockpit-components-table.jsx"; import { ListingPanel } from 'cockpit-components-listing-panel.jsx'; import { StorageButton, StorageBarMenu, StorageMenuItem, StorageUsageBar } from "./storage-controls.jsx"; import * as PK from "packagekit.js"; -import { - format_dialog, parse_options, extract_option, unparse_options -} from "./format-dialog.jsx"; +import { format_dialog } from "./format-dialog.jsx"; import { job_progress_wrapper } from "./jobs-panel.jsx"; import { FilesystemTab, is_mounted, mounting_dialog, get_fstab_config } from "./fsys-tab.jsx"; -import { CryptoTab, edit_config } from "./crypto-tab.jsx"; +import { CryptoTab } from "./crypto-tab.jsx"; import { get_existing_passphrase, unlock_with_type } from "./crypto-keyslots.jsx"; import { BlockVolTab, PoolVolTab, VDOPoolTab } from "./lvol-tabs.jsx"; import { PartitionTab } from "./part-tab.jsx"; @@ -75,38 +74,6 @@ function next_default_logical_volume_name(client, vgroup, prefix) { return name; } -export function set_crypto_options(block, readonly, auto, nofail, netdev) { - return edit_config(block, (config, commit) => { - const opts = config.options ? parse_options(utils.decode_filename(config.options.v)) : []; - if (readonly !== null) { - extract_option(opts, "readonly"); - if (readonly) - opts.push("readonly"); - } - if (auto !== null) { - extract_option(opts, "noauto"); - if (!auto) - opts.push("noauto"); - } - if (nofail !== null) { - extract_option(opts, "nofail"); - if (nofail) - opts.push("nofail"); - } - if (netdev !== null) { - extract_option(opts, "_netdev"); - if (netdev) - opts.push("_netdev"); - } - config.options = { t: 'ay', v: utils.encode_filename(unparse_options(opts)) }; - return commit(); - }); -} - -export function set_crypto_auto_option(block, flag) { - return set_crypto_options(block, null, flag, null, null); -} - function create_tabs(client, target, options) { function endsWith(str, suffix) { return str.indexOf(suffix, str.length - suffix.length) !== -1; diff --git a/pkg/storaged/crypto-keyslots.jsx b/pkg/storaged/crypto-keyslots.jsx index f8e86f5f7d62..358ea47f6c84 100644 --- a/pkg/storaged/crypto-keyslots.jsx +++ b/pkg/storaged/crypto-keyslots.jsx @@ -39,11 +39,9 @@ import { dialog_open, SelectOneRadio, TextInput, PassInput, Skip } from "./dialog.jsx"; -import { decode_filename, encode_filename, get_block_mntopts, block_name, for_each_async, get_children } from "./utils.js"; +import { decode_filename, encode_filename, get_block_mntopts, block_name, for_each_async, get_children, parse_options, unparse_options, edit_crypto_config } from "./utils.js"; import { fmt_to_fragments } from "utils.jsx"; import { StorageButton } from "./storage-controls.jsx"; -import { parse_options, unparse_options } from "./format-dialog.jsx"; -import { edit_config } from "./crypto-tab.jsx"; import clevis_luks_passphrase_sh from "./clevis-luks-passphrase.sh"; @@ -384,7 +382,7 @@ function ensure_crypto_option(steps, progress, client, block, option) { const new_crypto_options = crypto_options.concat([option]); progress(cockpit.format(_("Adding \"$0\" to encryption options"), option), null); - return edit_config(block, (config, commit) => { + return edit_crypto_config(block, (config, commit) => { config.options = { t: 'ay', v: encode_filename(unparse_options(new_crypto_options)) }; return commit(); }); diff --git a/pkg/storaged/crypto-tab.jsx b/pkg/storaged/crypto-tab.jsx index e17eab66cce4..6b1aa9c0e004 100644 --- a/pkg/storaged/crypto-tab.jsx +++ b/pkg/storaged/crypto-tab.jsx @@ -21,8 +21,7 @@ import { DescriptionList, DescriptionListDescription, DescriptionListGroup, Desc import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js"; import cockpit from "cockpit"; import { dialog_open, TextInput, PassInput } from "./dialog.jsx"; -import { encode_filename, decode_filename, block_name } from "./utils.js"; -import { parse_options, unparse_options, extract_option } from "./format-dialog.jsx"; +import { encode_filename, decode_filename, block_name, parse_options, unparse_options, extract_option, edit_crypto_config } from "./utils.js"; import { is_mounted } from "./fsys-tab.jsx"; import React from "react"; @@ -50,33 +49,6 @@ function parse_tag_mtime(tag) { return null; } -export function edit_config(block, modify) { - let old_config, new_config; - - function commit() { - new_config[1]["track-parents"] = { t: 'b', v: true }; - if (old_config) - return block.UpdateConfigurationItem(old_config, new_config, { }); - else - return block.AddConfigurationItem(new_config, { }); - } - - return block.GetSecretConfiguration({}).then( - function (items) { - old_config = items.find(c => c[0] == "crypttab"); - new_config = ["crypttab", old_config ? Object.assign({ }, old_config[1]) : { }]; - - // UDisks insists on always having a "passphrase-contents" field when - // adding a crypttab entry, but doesn't include one itself when returning - // an entry without a stored passphrase. - // - if (!new_config[1]['passphrase-contents']) - new_config[1]['passphrase-contents'] = { t: 'ay', v: encode_filename("") }; - - return modify(new_config[1], commit); - }); -} - export class CryptoTab extends React.Component { constructor() { super(); @@ -141,7 +113,7 @@ export class CryptoTab extends React.Component { this.monitor_slots(block); function edit_stored_passphrase() { - edit_config(block, function (config, commit) { + edit_crypto_config(block, function (config, commit) { dialog_open({ Title: _("Stored passphrase"), Fields: [ @@ -188,7 +160,7 @@ export class CryptoTab extends React.Component { const content_block = client.blocks_cleartext[block.path]; const is_fsys = fsys_config || (content_block && content_block.IdUsage == "filesystem"); - edit_config(block, function (config, commit) { + edit_crypto_config(block, function (config, commit) { dialog_open({ Title: _("Encryption options"), Fields: [ diff --git a/pkg/storaged/format-dialog.jsx b/pkg/storaged/format-dialog.jsx index 79460661ec41..5b8802a0e086 100644 --- a/pkg/storaged/format-dialog.jsx +++ b/pkg/storaged/format-dialog.jsx @@ -19,6 +19,7 @@ import cockpit from "cockpit"; import * as utils from "./utils.js"; +import { edit_crypto_config, parse_options, unparse_options, extract_option } from "./utils.js"; import React from "react"; import { FormHelperText } from "@patternfly/react-core/dist/esm/components/Form/index.js"; @@ -33,35 +34,11 @@ import { } from "./dialog.jsx"; import { get_fstab_config, is_valid_mount_point } from "./fsys-tab.jsx"; -import { edit_config } from "./crypto-tab.jsx"; import { init_existing_passphrase, unlock_with_type } from "./crypto-keyslots.jsx"; import { job_progress_wrapper } from "./jobs-panel.jsx"; const _ = cockpit.gettext; -export function parse_options(options) { - if (options) - return (options.split(",") - .map(function (s) { return s.trim() }) - .filter(function (s) { return s != "" })); - else - return []; -} - -export function unparse_options(split) { - return split.join(","); -} - -export function extract_option(split, opt) { - const index = split.indexOf(opt); - if (index >= 0) { - split.splice(index, 1); - return true; - } else { - return false; - } -} - export function initial_tab_options(client, block, for_fstab) { const options = { }; @@ -530,11 +507,11 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended, return block_ptable.CreatePartitionAndFormat(start, vals.size, "", "", { }, vals.type, options); } else if (keep_keys) { - return (edit_config(block, - (config, commit) => { - config.options = new_crypto_options; - return commit(); - }) + return (edit_crypto_config(block, + (config, commit) => { + config.options = new_crypto_options; + return commit(); + }) .then(() => maybe_unlock()) .then(content_block => { return content_block.Format(vals.type, options); diff --git a/pkg/storaged/fsys-tab.jsx b/pkg/storaged/fsys-tab.jsx index bc247d98fb4d..46c0c1e7d1ee 100644 --- a/pkg/storaged/fsys-tab.jsx +++ b/pkg/storaged/fsys-tab.jsx @@ -24,17 +24,14 @@ import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/ind import cockpit from "cockpit"; import * as utils from "./utils.js"; +import { parse_options, unparse_options, extract_option, set_crypto_options, set_crypto_auto_option } from "./utils.js"; import { dialog_open, TextInput, PassInput, CheckBoxes, SelectOne, StopProcessesMessage, stop_processes_danger_message } from "./dialog.jsx"; import { StorageButton, StorageLink } from "./storage-controls.jsx"; -import { - initial_tab_options, parse_options, unparse_options, extract_option, - mount_explanation -} from "./format-dialog.jsx"; -import { set_crypto_options, set_crypto_auto_option } from "./content-views.jsx"; +import { initial_tab_options, mount_explanation } from "./format-dialog.jsx"; import { init_existing_passphrase, unlock_with_type } from "./crypto-keyslots.jsx"; import client from "./client.js"; @@ -78,7 +75,7 @@ export function get_fstab_config(block, also_child_config) { return []; } -export function find_blocks_for_mount_point(client, mount_point, self) { +function find_blocks_for_mount_point(client, mount_point, self) { const blocks = []; function is_self(b) { diff --git a/pkg/storaged/nfs-details.jsx b/pkg/storaged/nfs-details.jsx index ecf247bb670c..15d082a6e801 100644 --- a/pkg/storaged/nfs-details.jsx +++ b/pkg/storaged/nfs-details.jsx @@ -26,10 +26,10 @@ import { dialog_open, TextInput, ComboBox, CheckBoxes, StopProcessesMessage, stop_processes_danger_message } from "./dialog.jsx"; -import * as format from "./format-dialog.jsx"; import { StdDetailsLayout } from "./details.jsx"; import { StorageButton, StorageUsageBar } from "./storage-controls.jsx"; +import { parse_options, unparse_options, extract_option } from "./utils.js"; const _ = cockpit.gettext; @@ -80,10 +80,10 @@ function get_exported_directories(server) { export function nfs_fstab_dialog(client, entry) { const mount_options = entry ? entry.fields[3] : "defaults"; - const split_options = format.parse_options(mount_options == "defaults" ? "" : mount_options); - const opt_auto = !format.extract_option(split_options, "noauto"); - const opt_ro = format.extract_option(split_options, "ro"); - const extra_options = format.unparse_options(split_options); + const split_options = parse_options(mount_options == "defaults" ? "" : mount_options); + const opt_auto = !extract_option(split_options, "noauto"); + const opt_ro = extract_option(split_options, "ro"); + const extra_options = unparse_options(split_options); function mounting_options(vals) { let opts = []; @@ -92,8 +92,8 @@ export function nfs_fstab_dialog(client, entry) { if (vals.mount_options.ro) opts.push("ro"); if (vals.mount_options.extra !== false) - opts = opts.concat(format.parse_options(vals.mount_options.extra)); - return format.unparse_options(opts); + opts = opts.concat(parse_options(vals.mount_options.extra)); + return unparse_options(opts); } function show(busy) { diff --git a/pkg/storaged/utils.js b/pkg/storaged/utils.js index b94b0a38730d..9434e4ff5f3c 100644 --- a/pkg/storaged/utils.js +++ b/pkg/storaged/utils.js @@ -47,6 +47,88 @@ export function compare_versions(a, b) { return a_ints.length - b_ints.length; } +export function parse_options(options) { + if (options) + return (options.split(",") + .map(function (s) { return s.trim() }) + .filter(function (s) { return s != "" })); + else + return []; +} + +export function unparse_options(split) { + return split.join(","); +} + +export function extract_option(split, opt) { + const index = split.indexOf(opt); + if (index >= 0) { + split.splice(index, 1); + return true; + } else { + return false; + } +} + +export function edit_crypto_config(block, modify) { + let old_config, new_config; + + function commit() { + new_config[1]["track-parents"] = { t: 'b', v: true }; + if (old_config) + return block.UpdateConfigurationItem(old_config, new_config, { }); + else + return block.AddConfigurationItem(new_config, { }); + } + + return block.GetSecretConfiguration({}).then( + function (items) { + old_config = items.find(c => c[0] == "crypttab"); + new_config = ["crypttab", old_config ? Object.assign({ }, old_config[1]) : { }]; + + // UDisks insists on always having a "passphrase-contents" field when + // adding a crypttab entry, but doesn't include one itself when returning + // an entry without a stored passphrase. + // + if (!new_config[1]['passphrase-contents']) + new_config[1]['passphrase-contents'] = { t: 'ay', v: encode_filename("") }; + + return modify(new_config[1], commit); + }); +} + +export function set_crypto_options(block, readonly, auto, nofail, netdev) { + return edit_crypto_config(block, (config, commit) => { + const opts = config.options ? parse_options(decode_filename(config.options.v)) : []; + if (readonly !== null) { + extract_option(opts, "readonly"); + if (readonly) + opts.push("readonly"); + } + if (auto !== null) { + extract_option(opts, "noauto"); + if (!auto) + opts.push("noauto"); + } + if (nofail !== null) { + extract_option(opts, "nofail"); + if (nofail) + opts.push("nofail"); + } + if (netdev !== null) { + extract_option(opts, "_netdev"); + if (netdev) + opts.push("_netdev"); + } + config.options = { t: 'ay', v: encode_filename(unparse_options(opts)) }; + return commit(); + }); +} + +export function set_crypto_auto_option(block, flag) { + return set_crypto_options(block, null, flag, null, null); +} + export let hostnamed = cockpit.dbus("org.freedesktop.hostname1").proxy(); // for unit tests diff --git a/test/reference b/test/reference index b0a214b926e8..444adbab6864 160000 --- a/test/reference +++ b/test/reference @@ -1 +1 @@ -Subproject commit b0a214b926e86a52b8cf3ad9a5681511fc03fca6 +Subproject commit 444adbab6864a348695889d5bb294566691ffab7