From c66d035a1cedabea45edba04699938517f631b6e Mon Sep 17 00:00:00 2001 From: niku Date: Tue, 21 Mar 2023 22:45:56 +0100 Subject: [PATCH] Added LXC resource page --- app/nodes/[node]/index.tsx | 42 ++++---- app/nodes/[node]/lxc/[vmid]/console.tsx | 7 +- app/nodes/[node]/lxc/[vmid]/index.tsx | 137 +++++++++++++++++++++--- app/nodes/index.tsx | 2 +- components/Card/index.tsx | 2 +- components/Login/index.tsx | 6 +- hooks/useNode.ts | 14 +-- hooks/useNodes.ts | 16 --- hooks/useResource.ts | 52 +++++++++ hooks/useTicket.ts | 2 +- 10 files changed, 212 insertions(+), 68 deletions(-) create mode 100644 hooks/useResource.ts diff --git a/app/nodes/[node]/index.tsx b/app/nodes/[node]/index.tsx index 3628fc0..9edf425 100644 --- a/app/nodes/[node]/index.tsx +++ b/app/nodes/[node]/index.tsx @@ -1,16 +1,16 @@ import { Link, useSearchParams } from "expo-router"; -import { View, Text, SafeAreaView, ScrollView, Button } from "react-native"; -import { NodeResource, useNode } from "../../../hooks/useNode"; +import { View, Text, ScrollView } from "react-native"; +import { NodeResource, ResourceType, useNode } from "../../../hooks/useNode"; import Icon from "@expo/vector-icons/Feather"; import tw from "twrnc"; -import { formatBytes, formatPercentage } from "../../../lib/helper/format"; -import { useEffect, useMemo } from "react"; +import { formatBytes } from "../../../lib/helper/format"; +import { useMemo } from "react"; import { Gauge } from "../../../components/Gauge"; import ProgressBar from "../../../components/ProgressBar"; import Card from "../../../components/Card"; interface ResourceListItemProps { - type: "LXC" | "QEMU"; + type: ResourceType; resource: NodeResource; } @@ -23,7 +23,7 @@ export function ResourceListItem({ type, resource }: ResourceListItemProps) { resource.status === "running" ? "bg-green-200" : "bg-slate-200" )} > - {type === "LXC" ? ( + {type === "lxc" ? ( ) : ( @@ -72,24 +72,28 @@ export default function NodePage() { )} - {node.rdd.isSuccess && ( + {node.rddData.isSuccess && ( - + @@ -101,13 +105,13 @@ export default function NodePage() { @@ -120,12 +124,12 @@ export default function NodePage() { - + ))} @@ -134,12 +138,12 @@ export default function NodePage() { - + ))} diff --git a/app/nodes/[node]/lxc/[vmid]/console.tsx b/app/nodes/[node]/lxc/[vmid]/console.tsx index e01b898..c12eed4 100644 --- a/app/nodes/[node]/lxc/[vmid]/console.tsx +++ b/app/nodes/[node]/lxc/[vmid]/console.tsx @@ -14,21 +14,20 @@ function buildConsoleUrl(domain: string, node: string, vmid: string) { } export default function QEMUResourceConsolePage() { - const { name, vmid } = useSearchParams<{ name: string; vmid: string }>(); + const { node, vmid } = useSearchParams<{ node: string; vmid: string }>(); const { domain, ticketData } = useAuthStore(); + console.log({ ticketData }, buildConsoleUrl(domain, node, vmid)); return ( - - Currently not supported - + const router = useRouter(); + const { node, vmid } = useSearchParams<{ node: string; vmid: string }>(); + const { rddData, config } = useResource(node, "lxc", vmid); + const { lxc: lxcs } = useNode(node); - Config - { + if (lxcs.isSuccess) { + return lxcs.data.find((lxc) => lxc.vmid.toString() === vmid); + } + }, [lxcs]); + + return ( + + + + + + + + + + + {vmid}: {status.name} + + Node: {node} + + + + + + + {rddData.isSuccess && ( + + + + + + + + + + + + + + + + + + + + )} + + + + + router.push({ + pathname: "/nodes/[node]/lxc/[vmid]/console", + params: { node, vmid }, + }) + } > - - Currently not supported - - - + + + Open terminal + + + + + + {config.isSuccess && + Object.entries(config.data).map(([key, val]) => { + return ( + + {key}: + {val} + + ); + })} + + + ); } diff --git a/app/nodes/index.tsx b/app/nodes/index.tsx index 1cc298b..a83ce75 100644 --- a/app/nodes/index.tsx +++ b/app/nodes/index.tsx @@ -1,5 +1,5 @@ import { Link } from "expo-router"; -import { View, Text, SafeAreaView } from "react-native"; +import { View, Text } from "react-native"; import { ProxmoxNode, useNodes } from "../../hooks/useNodes"; import Icon from "@expo/vector-icons/Feather"; import tw from "twrnc"; diff --git a/components/Card/index.tsx b/components/Card/index.tsx index d958b40..900f61b 100644 --- a/components/Card/index.tsx +++ b/components/Card/index.tsx @@ -9,7 +9,7 @@ interface CardProps { export default function Card({ label, children }: CardProps) { return ( <> - {label && {label}} + {label && {label}} diff --git a/components/Login/index.tsx b/components/Login/index.tsx index da8242d..bb5bab1 100644 --- a/components/Login/index.tsx +++ b/components/Login/index.tsx @@ -1,10 +1,10 @@ import { View, - TouchableOpacity, Text, TextInput, SafeAreaView, TextInputProps, + TouchableHighlight, } from "react-native"; import React, { useState } from "react"; import tw from "twrnc"; @@ -92,14 +92,14 @@ export default function Login() { secureTextEntry /> - ticketMut.mutate({ domain, username, password })} > Sign In - + ); diff --git a/hooks/useNode.ts b/hooks/useNode.ts index bc6c349..28dd30d 100644 --- a/hooks/useNode.ts +++ b/hooks/useNode.ts @@ -1,7 +1,7 @@ import { useQueries, useQuery } from "react-query"; import useAuthStore from "../stores/useAuthStore"; -export type ResourceType = "LXC" | "QEMU"; +export type ResourceType = "lxc" | "qemu"; export interface NodeResource { status: "stopped" | "running"; @@ -18,7 +18,7 @@ export interface NodeStatus { kversion: string; } -export interface NodeRDD { +export interface NodeRddData { netin: number; netout: number; rootused: number; @@ -30,17 +30,17 @@ export interface NodeRDD { export function useNode(name: string) { const http = useAuthStore((state) => state.http); - const [rdd, status, lxc, qemu] = useQueries([ + const [rddData, status, lxc, qemu] = useQueries([ { - queryKey: ["nodes", name, "rdd"], + queryKey: ["nodes", name, "rddData"], queryFn: () => - http.get<{ data: NodeRDD[] }>(`/api2/json/nodes/${name}/rrddata`, { + http.get<{ data: NodeRddData[] }>(`/api2/json/nodes/${name}/rrddata`, { params: { timeframe: "hour", }, }), enabled: !!name, - select: (data): NodeRDD => data.data.data.at(-1), + select: (data): NodeRddData => data.data.data.at(-1), }, { queryKey: ["nodes", name, "status"], @@ -66,7 +66,7 @@ export function useNode(name: string) { ]); return { - rdd, + rddData, status, lxc, qemu, diff --git a/hooks/useNodes.ts b/hooks/useNodes.ts index 81b7da6..444eee8 100644 --- a/hooks/useNodes.ts +++ b/hooks/useNodes.ts @@ -21,22 +21,6 @@ export function useNodes() { ["nodes"], async () => { return http.get("/api2/json/nodes"); - // return { - // data: { - // data: [ - // { - // cpu: 0.0166442953020134, - // mem: 21713018880, - // maxmem: 29306216448, - // uptime: 4854322, - // status: "online", - // maxcpu: 12, - // node: "pve", - // }, - // ] as ProxmoxNode[], - // }, - // isSuccess: true, - // }; }, { select: (data) => data.data.data, refetchInterval: 6000 } ); diff --git a/hooks/useResource.ts b/hooks/useResource.ts new file mode 100644 index 0000000..a6dc659 --- /dev/null +++ b/hooks/useResource.ts @@ -0,0 +1,52 @@ +import { useQueries } from "react-query"; +import useAuthStore from "../stores/useAuthStore"; +import { ResourceType } from "./useNode"; + +interface ResourceRddData { + cpu: number; + disk: number; + maxdisk: number; + mem: number; + maxmem: number; + netin: number; + netout: number; +} + +export function useResource( + node: string, + type: ResourceType, + vmid: string | number +) { + console.log({ node, type, vmid }); + const http = useAuthStore((state) => state.http); + const [rddData, config] = useQueries([ + { + queryKey: ["nodes", node, type, vmid, "rdd"], + queryFn: () => + http.get<{ data: ResourceRddData[] }>( + `/api2/json/nodes/${node}/${type}/${vmid}/rrddata`, + { + params: { + timeframe: "hour", + }, + } + ), + enabled: !!(node && vmid), + select: (data): ResourceRddData => data.data.data.at(-1), + }, + { + queryKey: ["nodes", node, type, vmid, "config"], + queryFn: () => + http.get<{ data: object }>( + `/api2/json/nodes/${node}/${type}/${vmid}/config` + ), + enabled: !!(node && vmid), + select: (data): object => data.data.data, + }, + ]); + + return { + rddData, + config, + }; +} diff --git a/hooks/useTicket.ts b/hooks/useTicket.ts index 0c15e33..f6253a8 100644 --- a/hooks/useTicket.ts +++ b/hooks/useTicket.ts @@ -19,7 +19,7 @@ export async function createTicket({ username, password, }: CreateTicketOpts) { - const url = `${domain}/api2/json/access/ticket`; + const url = new URL("/api2/json/access/ticket", domain).toString(); const headers = { "Content-Type": "application/json" }; return axios.post(url, { username, password }, { headers }); }