* Copyright (C) 2024 Red Hat, Inc.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
import { useContext, useEffect, useState } from "react";
import { getAutopartReuseDBusRequest } from "../../../../apis/storage_partitioning.js";
import { debug as loggerDebug } from "../../../../helpers/log.js";
import {
bootloaderTypes,
hasReusableFedoraWithWindowsOS,
isCompleteOSOnDisks,
} from "../../../../helpers/storage.js";
import { AvailabilityState } from "../helpers.js";
import { StorageContext } from "../../../../contexts/Common.jsx";
import {
useHomeReuseOptions,
useOriginalDevices,
useOriginalExistingSystems,
} from "../../../../hooks/Storage.jsx";
const debug = loggerDebug.bind(null, "home reuse:");
export const useAvailabilityHomeReuse = () => {
const [scenarioAvailability, setScenarioAvailability] = useState();
const devices = useOriginalDevices();
const { diskSelection } = useContext(StorageContext);
const selectedDisks = diskSelection.selectedDisks;
const originalExistingSystems = useOriginalExistingSystems();
const { reuseEFIPart, scheme } = useHomeReuseOptions();
useEffect(() => {
const availability = new AvailabilityState();
let reusedOS = null;
const autopartScheme = scheme;
availability.hidden = false;
availability.available = !!selectedDisks.length;
const getUnknownMountPoints = (scheme, existingOS) => {
const reuseRequest = getAutopartReuseDBusRequest({ reuseEFIPart, scheme });
const isBootloader = (device) => bootloaderTypes.includes(devices[device].formatData.type.v);
const existingMountPoints = Object.entries(existingOS["mount-points"].v)
.filter(mp => !isBootloader(mp[1]))
.map((mp) => mp[0]);
const managedMountPoints = reuseRequest["reformatted-mount-points"].v
.concat(reuseRequest["reused-mount-points"].v, reuseRequest["removed-mount-points"].v);
const unknownMountPoints = existingMountPoints.filter(i => !managedMountPoints.includes(i));
return unknownMountPoints;
};
const linuxSystems = originalExistingSystems.filter(osdata => osdata["os-name"].v.includes("Linux"))
.filter(osdata => isCompleteOSOnDisks(devices, selectedDisks, osdata));
if (linuxSystems.length === 0) {
availability.available = false;
availability.hidden = true;
debug("No existing Linux system found.");
} else if (linuxSystems.length > 1) {
availability.available = false;
availability.hidden = true;
debug("Multiple existing Linux systems found.");
} else {
reusedOS = linuxSystems[0];
if (!linuxSystems.some(osdata => osdata["os-name"].v.includes("Fedora"))) {
availability.available = false;
availability.hidden = true;
debug("No existing Fedora Linux system found.");
}
}
const allSystems = originalExistingSystems.filter(osdata => isCompleteOSOnDisks(devices, selectedDisks, osdata));
if (allSystems.length > linuxSystems.length) {
availability.available = false;
availability.hidden = true;
debug("Non-linux existing systems found.");
}
if (hasReusableFedoraWithWindowsOS(devices, selectedDisks, originalExistingSystems)) {
availability.available = true;
availability.hidden = false;
debug("Reusable Fedora with a Windows system along found.");
}
debug(`Default scheme is ${autopartScheme}.`);
if (reusedOS) {
const homeDevice = reusedOS["mount-points"].v["/home"];
const homeDeviceType = devices[homeDevice]?.type.v;
const requiredSchemeTypes = {
BTRFS: "btrfs subvolume",
LVM: "lvmlv",
LVM_THINP: "lvmthinlv",
PLAIN: "partition",
STRATIS: "stratis filesystem",
};
if (homeDeviceType !== requiredSchemeTypes[autopartScheme]) {
availability.available = false;
availability.hidden = true;
debug(`No reusable existing Linux system found, reused devices must have ${requiredSchemeTypes[autopartScheme]} type`);
}
}
if (reusedOS) {
const unknownMountPoints = getUnknownMountPoints(autopartScheme, reusedOS);
if (unknownMountPoints.length > 0) {
availability.available = false;
availability.hidden = true;
debug(`Unknown existing mountpoints found ${unknownMountPoints}`);
}
}
setScenarioAvailability(availability);
}, [devices, originalExistingSystems, reuseEFIPart, selectedDisks, scheme]);
return scenarioAvailability;
};