diff --git a/ui/webui/src/actions/storage-actions.js b/ui/webui/src/actions/storage-actions.js index be70c6573f8..0fe525b2279 100644 --- a/ui/webui/src/actions/storage-actions.js +++ b/ui/webui/src/actions/storage-actions.js @@ -19,15 +19,19 @@ import cockpit from "cockpit"; import { gatherRequests, - getAllDiskSelection, + getPartitioningMethod, +} from "../apis/storage_partitioning.js"; +import { getDeviceData, getDevices, getDiskFreeSpace, getDiskTotalSpace, getFormatData, - getPartitioningMethod, +} from "../apis/storage_devicetree.js"; +import { + getAllDiskSelection, getUsableDisks, -} from "../apis/storage.js"; +} from "../apis/storage_disks_selection.js"; import { setCriticalErrorAction, } from "../actions/miscellaneous-actions.js"; @@ -36,9 +40,8 @@ export const getDevicesAction = () => { return async (dispatch) => { try { const devices = await getDevices(); - const devicesData = await Promise.all(devices[0].map(async (device) => { - let devData = await getDeviceData({ disk: device }); - devData = devData[0]; + const devicesData = await Promise.all(devices.map(async (device) => { + const devData = await getDeviceData({ disk: device }); const free = await getDiskFreeSpace({ diskNames: [device] }); // extend it with variants to keep the format consistent @@ -77,7 +80,7 @@ export const getDiskSelectionAction = () => { diskSelection: { ignoredDisks: diskSelection[0].IgnoredDisks.v, selectedDisks: diskSelection[0].SelectedDisks.v, - usableDisks: usableDisks[0], + usableDisks, } }, }); @@ -98,7 +101,7 @@ export const getPartitioningDataAction = ({ requests, partitioning }) => { if (props.method === "MANUAL") { const reqs = await gatherRequests({ partitioning }); - props.requests = convertRequests(reqs[0]); + props.requests = convertRequests(reqs); } } else { props.requests = convertRequests(requests); diff --git a/ui/webui/src/apis/boss.js b/ui/webui/src/apis/boss.js index a90332c4861..052aca388e4 100644 --- a/ui/webui/src/apis/boss.js +++ b/ui/webui/src/apis/boss.js @@ -16,6 +16,14 @@ */ import cockpit from "cockpit"; +import { _callClient } from "./helpers.js"; + +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Boss"; +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Boss"; + +const callClient = (...args) => { + return _callClient(BossClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; /** * @param {string} address Anaconda bus address @@ -33,7 +41,7 @@ export class BossClient { BossClient.instance = this; this.client = cockpit.dbus( - "org.fedoraproject.Anaconda.Boss", + INTERFACE_NAME, { superuser: "try", bus: "none", address } ); this.address = address; @@ -63,21 +71,12 @@ export const getSteps = ({ task }) => { * @returns {Promise} Resolves a list of tasks */ export const installWithTasks = () => { - return new BossClient().client.call( - "/org/fedoraproject/Anaconda/Boss", - "org.fedoraproject.Anaconda.Boss", - "InstallWithTasks", [] - ) - .then(ret => ret[0]); + return callClient("InstallWithTasks", []); }; /** * @param {string} locale Locale id */ export const setLocale = ({ locale }) => { - return new BossClient().client.call( - "/org/fedoraproject/Anaconda/Boss", - "org.fedoraproject.Anaconda.Boss", - "SetLocale", [locale] - ); + return callClient("SetLocale", [locale]); }; diff --git a/ui/webui/src/apis/helpers.js b/ui/webui/src/apis/helpers.js new file mode 100644 index 00000000000..820fe5e813d --- /dev/null +++ b/ui/webui/src/apis/helpers.js @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ + +export const _callClient = (Client, OBJECT_PATH, INTERFACE_NAME, ...args) => { + return new Client().client.call(OBJECT_PATH, INTERFACE_NAME, ...args).then(res => res[0]); +}; + +export const _setProperty = (Client, OBJECT_PATH, INTERFACE_NAME, ...args) => { + return new Client().client.call( + OBJECT_PATH, "org.freedesktop.DBus.Properties", "Set", [INTERFACE_NAME, ...args] + ); +}; + +export const _getProperty = (Client, OBJECT_PATH, INTERFACE_NAME, ...args) => { + return new Client().client.call( + OBJECT_PATH, "org.freedesktop.DBus.Properties", "Get", [INTERFACE_NAME, ...args] + ).then(res => res[0].v); +}; diff --git a/ui/webui/src/apis/localization.js b/ui/webui/src/apis/localization.js index 130124ed4ee..05974091079 100644 --- a/ui/webui/src/apis/localization.js +++ b/ui/webui/src/apis/localization.js @@ -19,6 +19,20 @@ import cockpit from "cockpit"; import { getLanguageAction, getLanguagesAction } from "../actions/localization-actions.js"; import { debug } from "../helpers/log.js"; +import { _callClient, _setProperty, _getProperty } from "./helpers.js"; + +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Localization"; +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Localization"; + +const callClient = (...args) => { + return _callClient(LocalizationClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +const setProperty = (...args) => { + return _setProperty(LocalizationClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +const getProperty = (...args) => { + return _getProperty(LocalizationClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; export class LocalizationClient { constructor (address) { @@ -31,7 +45,7 @@ export class LocalizationClient { LocalizationClient.instance = this; this.client = cockpit.dbus( - "org.fedoraproject.Anaconda.Modules.Localization", + INTERFACE_NAME, { superuser: "try", bus: "none", address } ); this.address = address; @@ -46,29 +60,14 @@ export class LocalizationClient { * @returns {Promise} Resolves a list of language ids */ export const getLanguages = () => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.fedoraproject.Anaconda.Modules.Localization", - "GetLanguages", [] - ) - .then(res => res[0]) - ); + return callClient("GetLanguages", []); }; /** * @returns {Promise} The language the system will use */ export const getLanguage = () => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.freedesktop.DBus.Properties", - "Get", - ["org.fedoraproject.Anaconda.Modules.Localization", "Language"] - ) - .then(res => res[0].v) - ); + return getProperty("Language"); }; /** @@ -77,14 +76,7 @@ export const getLanguage = () => { * @returns {Promise} Resolves a language data object */ export const getLanguageData = ({ lang }) => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.fedoraproject.Anaconda.Modules.Localization", - "GetLanguageData", [lang] - ) - .then(res => res[0]) - ); + return callClient("GetLanguageData", [lang]); }; /** @@ -93,28 +85,14 @@ export const getLanguageData = ({ lang }) => { * @returns {Promise} Resolves a list of locales ids */ export const getLocales = ({ lang }) => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.fedoraproject.Anaconda.Modules.Localization", - "GetLocales", [lang] - ) - .then(res => res[0]) - ); + return callClient("GetLocales", [lang]); }; /** * @returns {Promise} Resolves a list of common locales id's. */ export const getCommonLocales = () => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.fedoraproject.Anaconda.Modules.Localization", - "GetCommonLocales" - ) - .then(res => res[0]) - ); + return callClient("GetCommonLocales"); }; /** @@ -123,32 +101,14 @@ export const getCommonLocales = () => { * @returns {Promise} Resolves a locale data object */ export const getLocaleData = ({ locale }) => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.fedoraproject.Anaconda.Modules.Localization", - "GetLocaleData", [locale] - ) - .then(res => res[0]) - ); + return callClient("GetLocaleData", [locale]); }; /** * @param {string} lang Language id */ export const setLanguage = ({ lang }) => { - return ( - new LocalizationClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Localization", - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Localization", - "Language", - cockpit.variant("s", lang) - ] - ) - ); + return setProperty("Language", cockpit.variant("s", lang)); }; export const startEventMonitorLocalization = ({ dispatch }) => { @@ -157,7 +117,7 @@ export const startEventMonitorLocalization = ({ dispatch }) => { (path, iface, signal, args) => { switch (signal) { case "PropertiesChanged": - if (args[0] === "org.fedoraproject.Anaconda.Modules.Localization" && Object.hasOwn(args[1], "Language")) { + if (args[0] === INTERFACE_NAME && Object.hasOwn(args[1], "Language")) { dispatch(getLanguageAction()); } else { debug(`Unhandled signal on ${path}: ${iface}.${signal}`, JSON.stringify(args)); diff --git a/ui/webui/src/apis/network.js b/ui/webui/src/apis/network.js index 7954aceedea..f10845b167f 100644 --- a/ui/webui/src/apis/network.js +++ b/ui/webui/src/apis/network.js @@ -19,6 +19,14 @@ import cockpit from "cockpit"; import { getConnectedAction } from "../actions/network-actions.js"; import { debug } from "../helpers/log.js"; +import { _getProperty } from "./helpers.js"; + +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Network"; +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Network"; + +const getProperty = (...args) => { + return _getProperty(NetworkClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; export class NetworkClient { constructor (address) { @@ -31,7 +39,7 @@ export class NetworkClient { NetworkClient.instance = this; this.client = cockpit.dbus( - "org.fedoraproject.Anaconda.Modules.Network", + INTERFACE_NAME, { superuser: "try", bus: "none", address } ); this.address = address; @@ -46,15 +54,7 @@ export class NetworkClient { * @returns {Promise} The bool state of the network connection */ export const getConnected = () => { - return ( - new NetworkClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Network", - "org.freedesktop.DBus.Properties", - "Get", - ["org.fedoraproject.Anaconda.Modules.Network", "Connected"] - ) - .then(res => res[0].v) - ); + return getProperty("Connected"); }; export const startEventMonitorNetwork = ({ dispatch }) => { @@ -63,7 +63,7 @@ export const startEventMonitorNetwork = ({ dispatch }) => { (path, iface, signal, args) => { switch (signal) { case "PropertiesChanged": - if (args[0] === "org.fedoraproject.Anaconda.Modules.Network" && Object.hasOwn(args[1], "Connected")) { + if (args[0] === INTERFACE_NAME && Object.hasOwn(args[1], "Connected")) { dispatch(getConnectedAction()); } else { debug(`Unhandled signal on ${path}: ${iface}.${signal}`, JSON.stringify(args)); diff --git a/ui/webui/src/apis/payloads.js b/ui/webui/src/apis/payloads.js index 0a36b7991ce..ed28b65c34f 100644 --- a/ui/webui/src/apis/payloads.js +++ b/ui/webui/src/apis/payloads.js @@ -15,6 +15,14 @@ * along with This program; If not, see . */ import cockpit from "cockpit"; +import { _callClient } from "./helpers.js"; + +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Payloads"; +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Payloads"; + +const callClient = (...args) => { + return _callClient(PayloadsClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; export class PayloadsClient { constructor (address) { @@ -27,7 +35,7 @@ export class PayloadsClient { PayloadsClient.instance = this; this.client = cockpit.dbus( - "org.fedoraproject.Anaconda.Modules.Payloads", + INTERFACE_NAME, { superuser: "try", bus: "none", address } ); this.address = address; @@ -45,10 +53,5 @@ export class PayloadsClient { * @returns {Promise} Resolves the total space required by the payload */ export const getRequiredSpace = () => { - return new PayloadsClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Payloads", - "org.fedoraproject.Anaconda.Modules.Payloads", - "CalculateRequiredSpace", [] - ) - .then(res => res[0]); + return callClient("CalculateRequiredSpace", []); }; diff --git a/ui/webui/src/apis/runtime.js b/ui/webui/src/apis/runtime.js index 6576e2cfaf6..5867b0a0065 100644 --- a/ui/webui/src/apis/runtime.js +++ b/ui/webui/src/apis/runtime.js @@ -19,6 +19,14 @@ import cockpit from "cockpit"; import { getPasswordPoliciesAction } from "../actions/runtime-actions.js"; import { debug } from "../helpers/log.js"; +import { _getProperty } from "./helpers.js"; + +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Runtime/UserInterface"; +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Runtime.UserInterface"; + +const getProperty = (...args) => { + return _getProperty(RuntimeClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; export class RuntimeClient { constructor (address) { @@ -49,18 +57,7 @@ export class RuntimeClient { * @returns {Promise} Reports if the given OS release is considered final */ export const getIsFinal = () => { - return ( - new RuntimeClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Runtime/UserInterface", - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Runtime.UserInterface", - "IsFinal", - ] - ) - .then(res => res[0].v) - ); + return getProperty("IsFinal"); }; /** @@ -68,18 +65,7 @@ export const getIsFinal = () => { * @returns {Promise} Returns the password policies */ export const getPasswordPolicies = () => { - return ( - new RuntimeClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Runtime/UserInterface", - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Runtime.UserInterface", - "PasswordPolicies", - ] - ) - .then(res => res[0].v) - ); + return getProperty("PasswordPolicies"); }; export const startEventMonitorRuntime = ({ dispatch }) => { @@ -88,7 +74,7 @@ export const startEventMonitorRuntime = ({ dispatch }) => { (path, iface, signal, args) => { switch (signal) { case "PropertiesChanged": - if (args[0] === "org.fedoraproject.Anaconda.Modules.Runtime.UserInterface" && Object.hasOwn(args[1], "PasswordPolicies")) { + if (args[0] === INTERFACE_NAME && Object.hasOwn(args[1], "PasswordPolicies")) { dispatch(getPasswordPoliciesAction()); } else { debug(`Unhandled signal on ${path}: ${iface}.${signal}`, JSON.stringify(args)); diff --git a/ui/webui/src/apis/storage.js b/ui/webui/src/apis/storage.js index 69a1de02286..a3ec1271a3c 100644 --- a/ui/webui/src/apis/storage.js +++ b/ui/webui/src/apis/storage.js @@ -23,6 +23,17 @@ import { } from "../actions/storage-actions.js"; import { debug } from "../helpers/log.js"; +import { _callClient, _getProperty } from "./helpers.js"; + +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Storage"; +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Storage"; + +const callClient = (...args) => { + return _callClient(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +const getProperty = (...args) => { + return _getProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; export class StorageClient { constructor (address) { @@ -35,7 +46,7 @@ export class StorageClient { StorageClient.instance = this; this.client = cockpit.dbus( - "org.fedoraproject.Anaconda.Modules.Storage", + INTERFACE_NAME, { superuser: "try", bus: "none", address } ); this.address = address; @@ -46,297 +57,6 @@ export class StorageClient { } } -/** - * @param {string} partitioning DBus path to a partitioning - * - * @returns {Promise} Resolves the DBus path to the partitioning - */ -export const applyPartitioning = ({ partitioning }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage", - "org.fedoraproject.Anaconda.Modules.Storage", - "ApplyPartitioning", [partitioning] - ); -}; - -/** - * @param {string} method A partitioning method - * - * @returns {Promise} Resolves the DBus path to the partitioning - */ -export const createPartitioning = ({ method }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage", - "org.fedoraproject.Anaconda.Modules.Storage", - "CreatePartitioning", [method] - ); -}; - -/** - * @returns {Promise} Resolves all properties of DiskSelection interface - */ -export const getAllDiskSelection = () => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskSelection", - "org.freedesktop.DBus.Properties", - "GetAll", - ["org.fedoraproject.Anaconda.Modules.Storage.DiskSelection"], - ); -}; - -/** - * @param {string} deviceName A device name - * @param {string} password A password - * - * @returns {Promise} Resolves true if success otherwise false - */ -export const unlockDevice = ({ deviceName, passphrase }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Handler", - "UnlockDevice", [deviceName, passphrase] - ); -}; - -/** - * @param {string} disk A device name - * - * @returns {Promise} Resolves an object with the device data - */ -export const getDeviceData = ({ disk }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetDeviceData", [disk] - ); -}; - -/** - * @param {Array[string]} diskNames A list of disk names - * - * @returns {Promise} Resolves the total free space on the given disks - */ -export const getDiskFreeSpace = ({ diskNames }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetDiskFreeSpace", [diskNames] - ) - .then(res => res[0]); -}; - -/** - * @param {string} disk Name A disk name - * - * @returns {Promise} Resolves the device format data - */ -export const getFormatData = ({ diskName }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetFormatData", [diskName] - ) - .then(res => res[0]); -}; - -/** - * @param {int} requiredSpace A required space in bytes - * - * @returns {Promise} Resolves the total free space on the given disks - */ -export const getRequiredDeviceSize = ({ requiredSpace }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetRequiredDeviceSize", [requiredSpace] - ) - .then(res => res[0]); -}; - -/** - * @returns {Promise} List of all mount points required on the platform - */ -export const getRequiredMountPoints = () => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetRequiredMountPoints", [] - ) - .then(res => res[0]); -}; - -/** - * @param {Array[string]} diskNames A list of disk names - * - * @returns {Promise} Resolves the total space on the given disks - */ -export const getDiskTotalSpace = ({ diskNames }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetDiskTotalSpace", [diskNames] - ) - .then(res => res[0]); -}; - -/** - * @returns {Promise} Resolves all devices in a device tree - */ -export const getDevices = () => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree", - "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer", - "GetDevices", [] - ); -}; - -/** - * @returns {Promise} Resolves a list with disk names - */ -export const getUsableDisks = () => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskSelection", - "org.fedoraproject.Anaconda.Modules.Storage.DiskSelection", - "GetUsableDisks", [] - ); -}; - -/** - * @returns {Promise} The list of selected disks - */ -export const getSelectedDisks = () => { - return ( - new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskSelection", - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Storage.DiskSelection", - "SelectedDisks" - ] - ) - .then(res => res[0].v) - ); -}; - -/** - * @param {string} partitioning DBus path to a partitioning - * @param {string} passphrase passphrase for disk encryption - */ -export const partitioningSetPassphrase = ({ partitioning, passphrase }) => { - return new StorageClient().client.call( - partitioning, - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Automatic", - "SetPassphrase", [passphrase] - ); -}; - -/** - * @param {string} partitioning DBus path to a partitioning - * @param {boolean} encrypt True if partitions should be encrypted, False otherwise - */ -export const partitioningSetEncrypt = ({ partitioning, encrypt }) => { - return getPartitioningRequest({ partitioning }) - .then(request => { - request.encrypted = cockpit.variant("b", encrypt); - return setPartitioningRequest({ partitioning, request }); - }); -}; - -/** - * @returns {Promise} The request of automatic partitioning - */ -export const getPartitioningRequest = ({ partitioning }) => { - return ( - new StorageClient().client.call( - partitioning, - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Automatic", - "Request", - ] - ) - .then(res => res[0].v) - ); -}; - -/** - * @param {string} partitioning DBus path to a partitioning - * - * @returns {Promise} The partitioning method - */ -export const getPartitioningMethod = ({ partitioning }) => { - return ( - new StorageClient().client.call( - partitioning, - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning", - "PartitioningMethod", - ] - ) - .then(res => res[0].v) - ); -}; - -/** - * @returns {Promise} The applied partitioning - */ -export const getAppliedPartitioning = () => { - return ( - new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage", - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Storage", - "AppliedPartitioning", - ] - ) - .then(res => res[0].v) - ); -}; - -/** - * @param {string} partitioning DBus path to a partitioning - * @param {Object} request A data object with the request - */ -export const setPartitioningRequest = ({ partitioning, request }) => { - return new StorageClient().client.call( - partitioning, - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Automatic", - "Request", - cockpit.variant("a{sv}", request) - ] - ); -}; - -/** - * @param {string} partitioning DBus path to a partitioning - * - * @returns {Promise} Resolves a DBus path to a task - */ -export const partitioningConfigureWithTask = ({ partitioning }) => { - return new StorageClient().client.call( - partitioning, - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning", - "ConfigureWithTask", [] - ); -}; - -export const resetPartitioning = () => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage", - "org.fedoraproject.Anaconda.Modules.Storage", - "ResetPartitioning", [] - ); -}; - /** * @param {string} task DBus path to a task * @param {string} onSuccess Callback to run after Succeeded signal is received @@ -371,124 +91,7 @@ export const runStorageTask = ({ task, onSuccess, onFail }) => { * @returns {Promise} Resolves a DBus path to a task */ export const scanDevicesWithTask = () => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage", - "org.fedoraproject.Anaconda.Modules.Storage", - "ScanDevicesWithTask", [] - ); -}; - -/** - * @returns {Promise} The number of the mode - */ -export const getInitializationMode = () => { - return ( - new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskInitialization", - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Storage.DiskInitialization", - "InitializationMode", - ] - ) - .then(res => res[0].v) - ); -}; - -/** - * @param {int} mode The number of the mode - */ -export const setInitializationMode = ({ mode }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskInitialization", - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Storage.DiskInitialization", - "InitializationMode", - cockpit.variant("i", mode) - ] - ); -}; - -/** - * @param {boolean} enabled True if allowed, otherwise False - */ -export const setInitializeLabelsEnabled = ({ enabled }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskInitialization", - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Storage.DiskInitialization", - "InitializeLabelsEnabled", - cockpit.variant("b", enabled) - ] - ); -}; - -/** - * @param {string} drive A drive name - */ -export const setBootloaderDrive = ({ drive }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/Bootloader", - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Storage.Bootloader", - "Drive", - cockpit.variant("s", drive) - ] - ); -}; - -/** - * @param {Array.} drives A list of drives names - */ -export const setSelectedDisks = ({ drives }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage/DiskSelection", - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Storage.DiskSelection", - "SelectedDisks", - cockpit.variant("as", drives) - ] - ); -}; - -/* - * @param {string} partitioning DBus path to a partitioning - * @param {Array.} requests An array of request objects - */ -export const setManualPartitioningRequests = ({ partitioning, requests }) => { - return new StorageClient().client.call( - partitioning, - "org.freedesktop.DBus.Properties", - "Set", - [ - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Manual", - "Requests", - cockpit.variant("aa{sv}", requests) - ] - ); -}; - -/** - * @param {string} partitioning DBus path to a partitioning - * - * @returns {Promise} The gathered requests for manual partitioning - */ -export const gatherRequests = ({ partitioning }) => { - return new StorageClient().client.call( - partitioning, - "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Manual", - "GatherRequests", - [] - ); + return callClient("ScanDevicesWithTask", []); }; export const startEventMonitorStorage = ({ dispatch }) => { @@ -501,7 +104,7 @@ export const startEventMonitorStorage = ({ dispatch }) => { dispatch(getDiskSelectionAction()); } else if (args[0] === "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Manual" && Object.hasOwn(args[1], "Requests")) { dispatch(getPartitioningDataAction({ requests: args[1].Requests.v, partitioning: path })); - } else if (args[0] === "org.fedoraproject.Anaconda.Modules.Storage" && Object.hasOwn(args[1], "CreatedPartitioning")) { + } else if (args[0] === INTERFACE_NAME && Object.hasOwn(args[1], "CreatedPartitioning")) { const last = args[1].CreatedPartitioning.v.length - 1; dispatch(getPartitioningDataAction({ partitioning: args[1].CreatedPartitioning.v[last] })); } else { @@ -515,44 +118,12 @@ export const startEventMonitorStorage = ({ dispatch }) => { }; export const initDataStorage = ({ dispatch }) => { - return new StorageClient().client.call( - "/org/fedoraproject/Anaconda/Modules/Storage", - "org.freedesktop.DBus.Properties", - "Get", - [ - "org.fedoraproject.Anaconda.Modules.Storage", - "CreatedPartitioning", - ] - ) - .then(([res]) => { - if (res.v.length !== 0) { - return Promise.all(res.v.map(path => dispatch(getPartitioningDataAction({ partitioning: path })))); + return getProperty("CreatedPartitioning") + .then(res => { + if (res.length !== 0) { + return Promise.all(res.map(path => dispatch(getPartitioningDataAction({ partitioning: path })))); } }) .then(() => dispatch(getDevicesAction())) .then(() => dispatch(getDiskSelectionAction())); }; - -export const applyStorage = async ({ partitioning, encrypt, encryptPassword, onFail, onSuccess }) => { - await setInitializeLabelsEnabled({ enabled: true }); - await setBootloaderDrive({ drive: "" }); - - const [part] = partitioning ? [partitioning] : await createPartitioning({ method: "AUTOMATIC" }); - - if (encrypt) { - await partitioningSetEncrypt({ partitioning: part, encrypt }); - } - if (encryptPassword) { - await partitioningSetPassphrase({ partitioning: part, passphrase: encryptPassword }); - } - - const tasks = await partitioningConfigureWithTask({ partitioning: part }); - - runStorageTask({ - task: tasks[0], - onFail, - onSuccess: () => applyPartitioning({ partitioning: part }) - .then(onSuccess) - .catch(onFail) - }); -}; diff --git a/ui/webui/src/apis/storage_bootloader.js b/ui/webui/src/apis/storage_bootloader.js new file mode 100644 index 00000000000..2069d4581a3 --- /dev/null +++ b/ui/webui/src/apis/storage_bootloader.js @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import cockpit from "cockpit"; +import { StorageClient } from "./storage.js"; +import { _setProperty } from "./helpers.js"; + +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Storage.Bootloader"; +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Storage/Bootloader"; + +const setProperty = (...args) => { + return _setProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; + +/** + * @param {string} drive A drive name + */ +export const setBootloaderDrive = ({ drive }) => { + return setProperty("Drive", cockpit.variant("s", drive)); +}; diff --git a/ui/webui/src/apis/storage_devicetree.js b/ui/webui/src/apis/storage_devicetree.js new file mode 100644 index 00000000000..c293b9bae63 --- /dev/null +++ b/ui/webui/src/apis/storage_devicetree.js @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import { StorageClient } from "./storage.js"; +import { _callClient } from "./helpers.js"; + +const INTERFACE_NAME_VIEWER = "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Viewer"; +const INTERFACE_NAME_HANDLER = "org.fedoraproject.Anaconda.Modules.Storage.DeviceTree.Handler"; +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Storage/DeviceTree"; + +const callViewer = (...args) => { + return _callClient(StorageClient, OBJECT_PATH, INTERFACE_NAME_VIEWER, ...args); +}; +const callHandler = (...args) => { + return _callClient(StorageClient, OBJECT_PATH, INTERFACE_NAME_HANDLER, ...args); +}; + +/** + * @param {string} deviceName A device name + * @param {string} password A password + * + * @returns {Promise} Resolves true if success otherwise false + */ +export const unlockDevice = ({ deviceName, passphrase }) => { + return callHandler("UnlockDevice", [deviceName, passphrase]); +}; + +/** + * @param {string} disk A device name + * + * @returns {Promise} Resolves an object with the device data + */ +export const getDeviceData = ({ disk }) => { + return callViewer("GetDeviceData", [disk]); +}; + +/** + * @param {Array[string]} diskNames A list of disk names + * + * @returns {Promise} Resolves the total free space on the given disks + */ +export const getDiskFreeSpace = ({ diskNames }) => { + return callViewer("GetDiskFreeSpace", [diskNames]); +}; + +/** + * @param {string} disk Name A disk name + * + * @returns {Promise} Resolves the device format data + */ +export const getFormatData = ({ diskName }) => { + return callViewer("GetFormatData", [diskName]); +}; + +/** + * @param {int} requiredSpace A required space in bytes + * + * @returns {Promise} Resolves the total free space on the given disks + */ +export const getRequiredDeviceSize = ({ requiredSpace }) => { + return callViewer("GetRequiredDeviceSize", [requiredSpace]); +}; + +/** + * @returns {Promise} List of all mount points required on the platform + */ +export const getRequiredMountPoints = () => { + return callViewer("GetRequiredMountPoints", []); +}; + +/** + * @param {Array[string]} diskNames A list of disk names + * + * @returns {Promise} Resolves the total space on the given disks + */ +export const getDiskTotalSpace = ({ diskNames }) => { + return callViewer("GetDiskTotalSpace", [diskNames]); +}; + +/** + * @returns {Promise} Resolves all devices in a device tree + */ +export const getDevices = () => { + return callViewer("GetDevices", []); +}; diff --git a/ui/webui/src/apis/storage_disk_initialization.js b/ui/webui/src/apis/storage_disk_initialization.js new file mode 100644 index 00000000000..6e10ac86fcc --- /dev/null +++ b/ui/webui/src/apis/storage_disk_initialization.js @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import cockpit from "cockpit"; + +import { StorageClient } from "./storage.js"; +import { _getProperty, _setProperty } from "./helpers.js"; + +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Storage.DiskInitialization"; +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Storage/DiskInitialization"; + +const getProperty = (...args) => { + return _getProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +const setProperty = (...args) => { + return _setProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; + +/** + * @returns {Promise} The number of the mode + */ +export const getInitializationMode = () => { + return getProperty("InitializationMode"); +}; + +/** + * @param {int} mode The number of the mode + */ +export const setInitializationMode = ({ mode }) => { + return setProperty("InitializationMode", cockpit.variant("i", mode)); +}; + +/** + * @param {boolean} enabled True if allowed, otherwise False + */ +export const setInitializeLabelsEnabled = ({ enabled }) => { + return setProperty("InitializeLabelsEnabled", cockpit.variant("b", enabled)); +}; diff --git a/ui/webui/src/apis/storage_disks_selection.js b/ui/webui/src/apis/storage_disks_selection.js new file mode 100644 index 00000000000..8c3b018e51d --- /dev/null +++ b/ui/webui/src/apis/storage_disks_selection.js @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import cockpit from "cockpit"; + +import { StorageClient } from "./storage.js"; +import { _callClient, _setProperty, _getProperty } from "./helpers.js"; + +const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Storage.DiskSelection"; +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Storage/DiskSelection"; + +const callClient = (...args) => { + return _callClient(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +const setProperty = (...args) => { + return _setProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +const getProperty = (...args) => { + return _getProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME, ...args); +}; +/** + * @returns {Promise} Resolves all properties of DiskSelection interface + */ +export const getAllDiskSelection = () => { + return new StorageClient().client.call(OBJECT_PATH, "org.freedesktop.DBus.Properties", "GetAll", [INTERFACE_NAME]); +}; + +/** + * @returns {Promise} Resolves a list with disk names + */ +export const getUsableDisks = () => { + return callClient("GetUsableDisks", []); +}; + +/** + * @returns {Promise} The list of selected disks + */ +export const getSelectedDisks = () => { + return getProperty("SelectedDisks"); +}; + +/** + * @param {Array.} drives A list of drives names + */ +export const setSelectedDisks = ({ drives }) => { + return setProperty("SelectedDisks", cockpit.variant("as", drives)); +}; diff --git a/ui/webui/src/apis/storage_partitioning.js b/ui/webui/src/apis/storage_partitioning.js new file mode 100644 index 00000000000..b8a187e7c1e --- /dev/null +++ b/ui/webui/src/apis/storage_partitioning.js @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import cockpit from "cockpit"; + +import { + StorageClient, + runStorageTask, +} from "./storage.js"; +import { + setBootloaderDrive, +} from "./storage_bootloader.js"; +import { + setInitializeLabelsEnabled, +} from "./storage_disk_initialization.js"; +import { _callClient, _getProperty } from "./helpers.js"; + +const INTERFACE_NAME_STORAGE = "org.fedoraproject.Anaconda.Modules.Storage"; +const INTERFACE_NAME_PARTITIONING = "org.fedoraproject.Anaconda.Modules.Storage.Partitioning"; +const INTERFACE_NAME_PARTITIONING_MANUAL = "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Manual"; +const INTERFACE_NAME_PARTITIONING_AUTOMATIC = "org.fedoraproject.Anaconda.Modules.Storage.Partitioning.Automatic"; +const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Storage"; + +const callClient = (...args) => { + return _callClient(StorageClient, OBJECT_PATH, INTERFACE_NAME_STORAGE, ...args); +}; +const getProperty = (...args) => { + return _getProperty(StorageClient, OBJECT_PATH, INTERFACE_NAME_STORAGE, ...args); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * + * @returns {Promise} Resolves the DBus path to the partitioning + */ +export const applyPartitioning = ({ partitioning }) => { + return callClient("ApplyPartitioning", [partitioning]); +}; + +/** + * @param {string} method A partitioning method + * + * @returns {Promise} Resolves the DBus path to the partitioning + */ +export const createPartitioning = ({ method }) => { + return callClient("CreatePartitioning", [method]); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * @param {string} passphrase passphrase for disk encryption + */ +export const partitioningSetPassphrase = ({ partitioning, passphrase }) => { + return new StorageClient().client.call( + partitioning, + INTERFACE_NAME_PARTITIONING_AUTOMATIC, + "SetPassphrase", [passphrase] + ); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * @param {boolean} encrypt True if partitions should be encrypted, False otherwise + */ +export const partitioningSetEncrypt = ({ partitioning, encrypt }) => { + return getPartitioningRequest({ partitioning }) + .then(request => { + request.encrypted = cockpit.variant("b", encrypt); + return setPartitioningRequest({ partitioning, request }); + }); +}; + +/** + * @returns {Promise} The request of automatic partitioning + */ +export const getPartitioningRequest = ({ partitioning }) => { + return ( + new StorageClient().client.call( + partitioning, + "org.freedesktop.DBus.Properties", + "Get", + [ + INTERFACE_NAME_PARTITIONING_AUTOMATIC, + "Request", + ] + ) + .then(res => res[0].v) + ); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * + * @returns {Promise} The partitioning method + */ +export const getPartitioningMethod = ({ partitioning }) => { + return ( + new StorageClient().client.call( + partitioning, + "org.freedesktop.DBus.Properties", + "Get", + [ + INTERFACE_NAME_PARTITIONING, + "PartitioningMethod", + ] + ) + .then(res => res[0].v) + ); +}; + +/** + * @returns {Promise} The applied partitioning + */ +export const getAppliedPartitioning = () => { + return getProperty("AppliedPartitioning"); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * @param {Object} request A data object with the request + */ +export const setPartitioningRequest = ({ partitioning, request }) => { + return new StorageClient().client.call( + partitioning, + "org.freedesktop.DBus.Properties", + "Set", + [ + INTERFACE_NAME_PARTITIONING_AUTOMATIC, + "Request", + cockpit.variant("a{sv}", request) + ] + ); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * + * @returns {Promise} Resolves a DBus path to a task + */ +export const partitioningConfigureWithTask = ({ partitioning }) => { + return new StorageClient().client.call( + partitioning, + INTERFACE_NAME_PARTITIONING, + "ConfigureWithTask", [] + ); +}; + +export const resetPartitioning = () => { + return callClient("ResetPartitioning", []); +}; + +/* + * @param {string} partitioning DBus path to a partitioning + * @param {Array.} requests An array of request objects + */ +export const setManualPartitioningRequests = ({ partitioning, requests }) => { + return new StorageClient().client.call( + partitioning, + "org.freedesktop.DBus.Properties", + "Set", + [ + INTERFACE_NAME_PARTITIONING_MANUAL, + "Requests", + cockpit.variant("aa{sv}", requests) + ] + ); +}; + +/** + * @param {string} partitioning DBus path to a partitioning + * + * @returns {Promise} The gathered requests for manual partitioning + */ +export const gatherRequests = ({ partitioning }) => { + return new StorageClient().client.call( + partitioning, + INTERFACE_NAME_PARTITIONING_MANUAL, + "GatherRequests", + [] + ).then(res => res[0]); +}; + +export const applyStorage = async ({ partitioning, encrypt, encryptPassword, onFail, onSuccess }) => { + await setInitializeLabelsEnabled({ enabled: true }); + await setBootloaderDrive({ drive: "" }); + + const part = partitioning || await createPartitioning({ method: "AUTOMATIC" }); + + if (encrypt) { + await partitioningSetEncrypt({ partitioning: part, encrypt }); + } + if (encryptPassword) { + await partitioningSetPassphrase({ partitioning: part, passphrase: encryptPassword }); + } + + const tasks = await partitioningConfigureWithTask({ partitioning: part }); + + runStorageTask({ + task: tasks[0], + onFail, + onSuccess: () => applyPartitioning({ partitioning: part }) + .then(onSuccess) + .catch(onFail) + }); +}; diff --git a/ui/webui/src/components/AnacondaWizard.jsx b/ui/webui/src/components/AnacondaWizard.jsx index 430fc0aeaec..eb6beff0d8a 100644 --- a/ui/webui/src/components/AnacondaWizard.jsx +++ b/ui/webui/src/components/AnacondaWizard.jsx @@ -43,11 +43,13 @@ import { InstallationProgress } from "./installation/InstallationProgress.jsx"; import { ReviewConfiguration, ReviewConfigurationConfirmModal, getPageProps as getReviewConfigurationProps } from "./review/ReviewConfiguration.jsx"; import { exitGui } from "../helpers/exit.js"; import { usePageLocation } from "hooks"; +import { + getRequiredMountPoints, +} from "../apis/storage_devicetree.js"; import { applyStorage, resetPartitioning, - getRequiredMountPoints, -} from "../apis/storage.js"; +} from "../apis/storage_partitioning.js"; import { SystemTypeContext, OsReleaseContext } from "./Common.jsx"; const _ = cockpit.gettext; diff --git a/ui/webui/src/components/review/ReviewConfiguration.jsx b/ui/webui/src/components/review/ReviewConfiguration.jsx index f158e61bfb1..9229eb94d91 100644 --- a/ui/webui/src/components/review/ReviewConfiguration.jsx +++ b/ui/webui/src/components/review/ReviewConfiguration.jsx @@ -31,7 +31,7 @@ import { getAppliedPartitioning, getPartitioningRequest, getPartitioningMethod, -} from "../../apis/storage.js"; +} from "../../apis/storage_partitioning.js"; import { checkDeviceInSubTree } from "../../helpers/storage.js"; import { getScenario } from "../storage/InstallationScenario.jsx"; diff --git a/ui/webui/src/components/storage/EncryptedDevices.jsx b/ui/webui/src/components/storage/EncryptedDevices.jsx index 03df99a9de2..2aaba860975 100644 --- a/ui/webui/src/components/storage/EncryptedDevices.jsx +++ b/ui/webui/src/components/storage/EncryptedDevices.jsx @@ -43,7 +43,7 @@ import { getDevicesAction } from "../../actions/storage-actions.js"; import { unlockDevice, -} from "../../apis/storage.js"; +} from "../../apis/storage_devicetree.js"; const _ = cockpit.gettext; @@ -118,11 +118,11 @@ const UnlockDialog = ({ isLoadingNewPartitioning, lockedLUKSDevices, onClose, di ).then( res => { if (res.every(r => r.status === "fulfilled")) { - if (res.every(r => r.value[0])) { + if (res.every(r => r.value)) { onClose(); } else { const unlockedDevs = res.reduce((acc, r, i) => { - if (r.value[0]) { + if (r.value) { acc.push(lockedLUKSDevices[i]); } return acc; diff --git a/ui/webui/src/components/storage/InstallationDestination.jsx b/ui/webui/src/components/storage/InstallationDestination.jsx index c3b32aeb2c2..ca2a556ba5d 100644 --- a/ui/webui/src/components/storage/InstallationDestination.jsx +++ b/ui/webui/src/components/storage/InstallationDestination.jsx @@ -42,11 +42,11 @@ import { SystemTypeContext } from "../Common.jsx"; import { ModifyStorage } from "./ModifyStorage.jsx"; import { - resetPartitioning, runStorageTask, scanDevicesWithTask, - setSelectedDisks, } from "../../apis/storage.js"; +import { resetPartitioning } from "../../apis/storage_partitioning.js"; +import { setSelectedDisks } from "../../apis/storage_disks_selection.js"; import { getDevicesAction, getDiskSelectionAction } from "../../actions/storage-actions.js"; import { debug } from "../../helpers/log.js"; @@ -285,9 +285,9 @@ const rescanDisks = (setIsRescanningDisks, refUsableDisks, dispatch, errorHandle setIsFormDisabled(true); refUsableDisks.current = undefined; scanDevicesWithTask() - .then(res => { + .then(task => { return runStorageTask({ - task: res[0], + task, onSuccess: () => resetPartitioning() .then(() => Promise.all([ dispatch(getDevicesAction()), diff --git a/ui/webui/src/components/storage/InstallationScenario.jsx b/ui/webui/src/components/storage/InstallationScenario.jsx index f8b2b13bc50..96490e89598 100644 --- a/ui/webui/src/components/storage/InstallationScenario.jsx +++ b/ui/webui/src/components/storage/InstallationScenario.jsx @@ -33,8 +33,10 @@ import { getRequiredDeviceSize, getDiskTotalSpace, getDiskFreeSpace, +} from "../../apis/storage_devicetree.js"; +import { setInitializationMode, -} from "../../apis/storage.js"; +} from "../../apis/storage_disk_initialization.js"; import { getRequiredSpace, @@ -173,7 +175,7 @@ const InstallationScenarioSelector = ({ deviceData, selectedDisks, idPrefix, isF useEffect(() => { getDevices().then(res => { - const _duplicateDeviceNames = findDuplicatesInArray(res[0]); + const _duplicateDeviceNames = findDuplicatesInArray(res); setDuplicateDeviceNames(_duplicateDeviceNames); setIsFormValid(_duplicateDeviceNames.length === 0); }, onCritFail({ context: N_("Failed to get device names.") })); @@ -184,7 +186,7 @@ const InstallationScenarioSelector = ({ deviceData, selectedDisks, idPrefix, isF const diskTotalSpace = await getDiskTotalSpace({ diskNames: selectedDisks }).catch(console.error); const diskFreeSpace = await getDiskFreeSpace({ diskNames: selectedDisks }).catch(console.error); const devices = await getDevices().catch(console.error); - const _duplicateDeviceNames = findDuplicatesInArray(devices[0]); + const _duplicateDeviceNames = findDuplicatesInArray(devices); setDuplicateDeviceNames(_duplicateDeviceNames); setDiskTotalSpace(diskTotalSpace); diff --git a/ui/webui/src/components/storage/MountPointMapping.jsx b/ui/webui/src/components/storage/MountPointMapping.jsx index b422bf3f3db..0c4c057048e 100644 --- a/ui/webui/src/components/storage/MountPointMapping.jsx +++ b/ui/webui/src/components/storage/MountPointMapping.jsx @@ -42,10 +42,12 @@ import { EmptyStatePanel } from "cockpit-components-empty-state.jsx"; import { EncryptedDevices } from "./EncryptedDevices.jsx"; import { - createPartitioning, setBootloaderDrive, - setManualPartitioningRequests, -} from "../../apis/storage.js"; +} from "../../apis/storage_bootloader.js"; +import { + createPartitioning, + setManualPartitioningRequests +} from "../../apis/storage_partitioning.js"; import { getDeviceChildren, getLockedLUKSDevices, @@ -624,7 +626,7 @@ export const MountPointMapping = ({ setBootloaderDrive({ drive: "" }) .then(() => createPartitioning({ method: "MANUAL" })) .then(path => { - setUsedPartitioning(path[0]); + setUsedPartitioning(path); setReusePartitioning(true); }); }