Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Dec 13, 2024
1 parent 3722ed6 commit 9f3bea4
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 30 deletions.
20 changes: 16 additions & 4 deletions web/src/api/storage/types/config-model.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
/* eslint-disable */
/**
* This file was automatically generated by json-schema-to-typescript.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run json-schema-to-typescript to regenerate this file.
*/

/**
* Alias used to reference a device.
*/
export type Alias = string;
export type FilesystemType =
| "bcachefs"
| "btrfs"
Expand All @@ -29,11 +34,20 @@ export type PartitionId = "linux" | "swap" | "lvm" | "raid" | "esp" | "prep" | "
* Config model
*/
export interface Config {
boot?: Boot;
drives?: Drive[];
}
export interface Boot {
configure: boolean;
device?: BootDevice;
}
export interface BootDevice {
default: boolean;
value?: Alias;
}
export interface Drive {
name: string;
alias?: string;
alias?: Alias;
mountPath?: string;
filesystem?: Filesystem;
spacePolicy?: SpacePolicy;
Expand All @@ -49,15 +63,13 @@ export interface Filesystem {
}
export interface Partition {
name?: string;
alias?: string;
alias?: Alias;
id?: PartitionId;
mountPath?: string;
filesystem?: Filesystem;
size?: Size;
delete?: boolean;
// TODO: ignore
deleteIfNeeded?: boolean;
// TODO: ignore
resize?: boolean;
resizeIfNeeded?: boolean;
}
Expand Down
55 changes: 33 additions & 22 deletions web/src/components/storage/BootSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ import { DevicesFormSelect } from "~/components/storage";
import { Page } from "~/components/core";
import { deviceLabel } from "~/components/storage/utils";
import { StorageDevice } from "~/types/storage";
import { useAvailableDevices, useProposalMutation, useProposalResult } from "~/queries/storage";
import { useAvailableDevices } from "~/queries/storage";
import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
import { sprintf } from "sprintf-js";
import { _ } from "~/i18n";
import { useBootDevice, useConfigModel } from "~/queries/storage";

// FIXME: improve classNames
// FIXME: improve and rename to BootSelectionDialog
Expand All @@ -39,50 +40,56 @@ const BOOT_AUTO_ID = "boot-auto";
const BOOT_MANUAL_ID = "boot-manual";
const BOOT_DISABLED_ID = "boot-disabled";

type BootSelectionState = {
load: boolean;
selectedOption?: string;
configureBoot?: boolean;
bootDevice?: StorageDevice;
defaultBootDevice?: StorageDevice;
availableDevices?: StorageDevice[];
};

/**
* Allows the user to select the boot configuration.
*/
export default function BootSelectionDialog() {
type BootSelectionState = {
load: boolean;
selectedOption?: string;
configureBoot?: boolean;
bootDevice?: StorageDevice;
defaultBootDevice?: StorageDevice;
availableDevices?: StorageDevice[];
};

const [state, setState] = useState<BootSelectionState>({ load: false });
const { settings } = useProposalResult();
// const { settings } = useProposalResult();
const availableDevices = useAvailableDevices();
const updateProposal = useProposalMutation();
// const updateProposal = useProposalMutation();
const navigate = useNavigate();
const configModel = useConfigModel();
const bootDeviceModel = useBootDevice();

console.log(configModel);

useEffect(() => {
if (state.load) return;

let selectedOption: string;
const { bootDevice, configureBoot, defaultBootDevice } = settings;
const bootModel = configModel?.boot;
const configureBoot = bootModel?.configure || false;
const defaultBootDevice = bootModel?.device?.default || false;

if (!configureBoot) {
selectedOption = BOOT_DISABLED_ID;
} else if (configureBoot && bootDevice === "") {
} else if (configureBoot && defaultBootDevice) {
selectedOption = BOOT_AUTO_ID;
} else {
selectedOption = BOOT_MANUAL_ID;
}

const findDevice = (name: string) => availableDevices.find((d) => d.name === name);
const bootDevice = availableDevices.find((d) => d.name === bootDeviceModel.name);

setState({
load: true,
bootDevice: findDevice(bootDevice) || findDevice(defaultBootDevice) || availableDevices[0],
bootDevice: bootDevice || availableDevices[0],
configureBoot,
defaultBootDevice: findDevice(defaultBootDevice),
defaultBootDevice: bootDevice,
availableDevices,
selectedOption,
});
}, [availableDevices, settings, state.load]);
}, [availableDevices, configModel, bootDeviceModel, state.load]);

if (!state.load) return;

Expand All @@ -92,12 +99,16 @@ export default function BootSelectionDialog() {
// const formData = new FormData(e.target);
// const mode = formData.get("bootMode");
// const device = formData.get("bootDevice");
const newSettings = {
configureBoot: state.selectedOption !== BOOT_DISABLED_ID,
bootDevice: state.selectedOption === BOOT_MANUAL_ID ? state.bootDevice.name : undefined,
const bootModel = {
configure: state.selectedOption !== BOOT_DISABLED_ID,
device: {
default: state.selectedOption === BOOT_AUTO_ID,
device: state.bootDevice?.name,
},
};

await updateProposal.mutateAsync({ ...settings, ...newSettings });
// await updateProposal.mutateAsync({ ...settings, ...newSettings });
console.log(bootModel);
navigate("..");
};

Expand Down
7 changes: 6 additions & 1 deletion web/src/components/storage/ConfigEditorMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { _ } from "~/i18n";
import { useHref } from "react-router-dom";
import {
Expand All @@ -31,8 +32,10 @@ import {
DropdownItem,
Divider,
} from "@patternfly/react-core";
import { STORAGE as PATHS } from "~/routes/paths";

export default function ConfigEditorMenu() {
const navigate = useNavigate();
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(!isOpen);

Expand All @@ -58,7 +61,9 @@ export default function ConfigEditorMenu() {
<DropdownItem key="vg">{_("Add LVM volume group")}</DropdownItem>
<DropdownItem key="raid">{_("Add MD RAID")}</DropdownItem>
<Divider />
<DropdownItem key="boot">{_("Change boot options")}</DropdownItem>
<DropdownItem key="boot" onClick={() => navigate(PATHS.bootDevice)}>
{_("Change boot options")}
</DropdownItem>
<DropdownItem key="reinstall">{_("Reinstall an existing system")}</DropdownItem>
<Divider />
<DropdownItem key="iscsi-link" to={useHref("/storage/iscsi")}>
Expand Down
6 changes: 5 additions & 1 deletion web/src/components/storage/DriveEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
MenuToggle,
} from "@patternfly/react-core";

import { useChangeDrive, useSetSpacePolicy } from "~/queries/storage";
import { useConfigModel, useChangeDrive, useSetSpacePolicy } from "~/queries/storage";
import { Drive } from "~/api/storage/types/config-model";

type DriveEditorProps = { drive: configModel.Drive; driveDevice: StorageDevice };
Expand Down Expand Up @@ -649,6 +649,10 @@ const PartitionsSelector = ({ drive }) => {
};

export default function DriveEditor({ drive, driveDevice }: DriveEditorProps) {
const model = useConfigModel();

console.log("model: ", model);

return (
<Card isCompact>
<CardHeader>
Expand Down
38 changes: 38 additions & 0 deletions web/src/queries/storage/config-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ function changeDrive(model: configModel.Config, driveName: string, newDriveName:
if (drive.spacePolicy === "custom") drive.spacePolicy = "keep";
}

function generateAlias(deviceName: string): string {
return `device-${deviceName.split("/").pop()}`;
}

function setSpacePolicy(
model: configModel.Config,
driveName: string,
Expand Down Expand Up @@ -91,6 +95,21 @@ function setCustomSpacePolicy(
});
}

function setBoot(model: configModel.Config, configure: boolean, driveName: string | undefined) {
model.boot ||= { configure };

if (driveName === undefined) {
model.boot.device = { default: true };
return;
}

const drive = findDrive(model, driveName);
if (drive === undefined) return;

if (drive.alias === undefined) drive.alias = generateAlias(drive.name);
model.boot.device = { default: false, value: drive.alias };
}

const configModelQuery = {
queryKey: ["storage", "configModel"],
queryFn: fetchConfigModel,
Expand All @@ -107,6 +126,16 @@ export function useConfigModel(options?: QueryHookOptions): configModel.Config {
return data;
}

export function useBootDevice(): configModel.Drive {
const model = useConfigModel();
const boot_device_alias = model.boot?.device?.value;

if (boot_device_alias === undefined) return;

const drives = model.drives || [];
return drives.find((d) => d.alias === boot_device_alias);
}

/**
* Hook for setting a new config model.
*/
Expand Down Expand Up @@ -160,3 +189,12 @@ export function useSetCustomSpacePolicy() {
applyModelAction(action);
};
}

export function useSetBoot() {
const applyModelAction = useApplyModelAction();

return (configure: boolean, deviceName: string | undefined) => {
const action: ModelActionF = (model) => setBoot(model, configure, deviceName);
applyModelAction(action);
};
}
2 changes: 1 addition & 1 deletion web/src/routes/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const SOFTWARE = {
const STORAGE = {
root: "/storage",
targetDevice: "/storage/target-device",
bootingPartition: "/storage/booting-partition",
bootDevice: "/storage/boot-device",
spacePolicy: "/storage/space-policy/:id",
iscsi: "/storage/iscsi",
dasd: "/storage/dasd",
Expand Down
2 changes: 1 addition & 1 deletion web/src/routes/storage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const routes = (): Route => ({
element: <DeviceSelection />,
},
{
path: PATHS.bootingPartition,
path: PATHS.bootDevice,
element: <BootSelection />,
},
{
Expand Down

0 comments on commit 9f3bea4

Please sign in to comment.