Skip to content

Commit

Permalink
chore(meshwide): implement remote reboot
Browse files Browse the repository at this point in the history
  • Loading branch information
selankon committed May 7, 2024
1 parent 0c3c160 commit d8ddc72
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Trans } from "@lingui/macro";

import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components";
import RemoteRebootBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn";
import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn";
import {
Row,
Expand Down Expand Up @@ -39,10 +40,7 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => {
<div>
<Row>
<div className={"text-3xl"}>{name}</div>
{/*todo(kon): implement safe_reboot*/}
{/*<Button color={"danger"} outline={true} size={"sm"}>*/}
{/* <PowerIcon />*/}
{/*</Button>*/}
<RemoteRebootBtn node={nodeToShow} />
</Row>
<Row>
{!isDown ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Trans } from "@lingui/macro";
import { useMutation } from "@tanstack/react-query";
import { useEffect, useState } from "preact/hooks";
import { useCallback } from "react";

import { useModal } from "components/Modal/Modal";
import { Button } from "components/buttons/button";
import { ErrorMsg } from "components/form";
import Loading from "components/loading";

import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api";
import { PowerIcon } from "plugins/lime-plugin-mesh-wide/src/icons/power";
import { INodeInfo } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes";

interface IRemoteRebotProps {
ip: string;
password: string;
}

export async function remoteReboot({ ip, password }: IRemoteRebotProps) {
return await callToRemoteNode({
ip,
apiCall: (customApi) =>
customApi.call("system", "reboot", {}).then(() => true),
username: "root",
password,
});
}

const useRemoteReboot = (opts?) => {
return useMutation((props: IRemoteRebotProps) => remoteReboot(props), {
mutationKey: ["system", "reboot"],
...opts,
});
};

const useRebootNodeModal = ({ node }: { node: INodeInfo }) => {
const { toggleModal, setModalState, isModalOpen } = useModal();
const [password, setPassword] = useState("");
const { mutate, isLoading, error } = useRemoteReboot({
onSuccess: () => {
toggleModal();
},
});

function changePassword(e) {
setPassword(e.target.value || "");
}

const doLogin = useCallback(() => {
mutate({ ip: node.ipv4, password });
}, [mutate, node.ipv4, password]);

const updateModalState = useCallback(() => {
setModalState({
title: <Trans>Reboot node {node.hostname}</Trans>,
content: (
<div>
<Trans>
Are you sure you want to reboot this node? This action
will disconnect the node from the network for a few
minutes. <br />
Add shared password or let it empty if no password is
set.
</Trans>
{isLoading && <Loading />}
{!isLoading && (
<div className={"mt-4"}>
<label htmlFor={"password"}>Node password</label>
<input
type="password"
id={"password"}
value={password}
onInput={changePassword}
/>
{error && (
<ErrorMsg>
<Trans>
Error performing reboot: {error}
</Trans>
</ErrorMsg>
)}
</div>
)}
</div>
),
successCb: doLogin,
successBtnText: <Trans>Reboot</Trans>,
});
}, [doLogin, error, isLoading, node.hostname, password, setModalState]);

const rebootModal = useCallback(() => {
updateModalState();
toggleModal();
}, [toggleModal, updateModalState]);

// Update modal state with mutation result
useEffect(() => {
if (isModalOpen) {
updateModalState();
}
}, [isLoading, error, isModalOpen, updateModalState]);

return { rebootModal, toggleModal, isModalOpen };
};

const RemoteRebootBtn = ({ node }: { node: INodeInfo }) => {
const { rebootModal, isModalOpen } = useRebootNodeModal({
node,
});

return (
<Button
color={"danger"}
outline={true}
size={"sm"}
onClick={() => !isModalOpen && rebootModal()}
>
<PowerIcon />
</Button>
);
};

export default RemoteRebootBtn;
2 changes: 1 addition & 1 deletion src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const Modal = ({

<div
onClick={stopPropagation}
className="flex flex-col px-6 justify-between w-full md:w-10/12 h-96 md:mx-24 self-center bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all "
className="flex flex-col px-6 justify-between w-full min-h-96 md:w-10/12 md:mx-24 self-center bg-white rounded-lg overflow-auto text-left shadow-xl transform transition-all "
>
<div className="bg-white pt-5 pb-4 sm:p-6 sm:pb-4">
<div className="mt-3 text-start sm:mt-0 sm:text-left">
Expand Down
2 changes: 1 addition & 1 deletion src/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const App = () => {
}, [session, login]);

if (!session?.username || !boardData) {
return <div>"Loading..."</div>;
return <div>Loading...</div>;
}

return (
Expand Down

0 comments on commit d8ddc72

Please sign in to comment.