diff --git a/virtweb_backend/src/libvirt_lib_structures.rs b/virtweb_backend/src/libvirt_lib_structures.rs
index 39ecaa3..a64eb4f 100644
--- a/virtweb_backend/src/libvirt_lib_structures.rs
+++ b/virtweb_backend/src/libvirt_lib_structures.rs
@@ -11,6 +11,7 @@ impl DomainXMLUuid {
}
pub fn is_valid(&self) -> bool {
+ log::debug!("UUID version ({}): {}", self.0, self.0.get_version_num());
self.0.get_version_num() == 4
}
}
diff --git a/virtweb_backend/src/libvirt_rest_structures.rs b/virtweb_backend/src/libvirt_rest_structures.rs
index d29f57f..5f26929 100644
--- a/virtweb_backend/src/libvirt_rest_structures.rs
+++ b/virtweb_backend/src/libvirt_rest_structures.rs
@@ -84,13 +84,13 @@ impl VMInfo {
}
if let Some(n) = &self.uuid {
- if n.is_valid() {
+ if !n.is_valid() {
return Err(StructureExtraction("VM UUID is invalid!").into());
}
}
if let Some(n) = &self.genid {
- if n.is_valid() {
+ if !n.is_valid() {
return Err(StructureExtraction("VM genid is invalid!").into());
}
}
diff --git a/virtweb_frontend/src/App.tsx b/virtweb_frontend/src/App.tsx
index ea87f5f..33a96d3 100644
--- a/virtweb_frontend/src/App.tsx
+++ b/virtweb_frontend/src/App.tsx
@@ -41,7 +41,7 @@ export function App() {
} />
} />
- } />
+ } />
} />
} />
diff --git a/virtweb_frontend/src/api/VMApi.ts b/virtweb_frontend/src/api/VMApi.ts
index cc97f6e..3c501e2 100644
--- a/virtweb_frontend/src/api/VMApi.ts
+++ b/virtweb_frontend/src/api/VMApi.ts
@@ -63,7 +63,11 @@ export class VMInfo implements VMInfoInterface {
}
get ViewURL(): string {
- return `/api/vm/${this.uuid}`;
+ return `/vm/${this.uuid}`;
+ }
+
+ get EditURL(): string {
+ return `/vm/${this.uuid}/edit`;
}
}
@@ -93,6 +97,33 @@ export class VMApi {
).data.map((i: VMInfoInterface) => new VMInfo(i));
}
+ /**
+ * Get the information about a single VM
+ */
+ static async GetSingle(uuid: string): Promise {
+ const data = (
+ await APIClient.exec({
+ uri: `/vm/${uuid}`,
+ method: "GET",
+ })
+ ).data;
+ return new VMInfo(data);
+ }
+
+ /**
+ * Update the information about a single VM
+ */
+ static async UpdateSingle(vm: VMInfo): Promise {
+ const data = (
+ await APIClient.exec({
+ uri: `/vm/${vm.uuid!}`,
+ method: "PUT",
+ jsonData: vm,
+ })
+ ).data;
+ return new VMInfo(data);
+ }
+
/**
* Get the state of a VM
*/
diff --git a/virtweb_frontend/src/routes/EditVMRoute.tsx b/virtweb_frontend/src/routes/EditVMRoute.tsx
index 5cecbef..38e5c29 100644
--- a/virtweb_frontend/src/routes/EditVMRoute.tsx
+++ b/virtweb_frontend/src/routes/EditVMRoute.tsx
@@ -1,5 +1,5 @@
import React, { PropsWithChildren } from "react";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useParams } from "react-router-dom";
import { VMApi, VMInfo } from "../api/VMApi";
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
@@ -9,6 +9,8 @@ import { ServerApi } from "../api/ServerApi";
import { validate as validateUUID } from "uuid";
import { SelectInput } from "../widgets/forms/SelectInput";
import { CheckboxInput } from "../widgets/forms/CheckboxInput";
+import { useAlert } from "../hooks/providers/AlertDialogProvider";
+import { AsyncWidget } from "../widgets/AsyncWidget";
export function CreateVMRoute(): React.ReactElement {
const snackbar = useSnackbar();
@@ -17,10 +19,15 @@ export function CreateVMRoute(): React.ReactElement {
const [vm] = React.useState(VMInfo.NewEmpty);
const create = async (v: VMInfo) => {
- const res = await VMApi.Create(v);
- snackbar("The virtual machine was successfully created!");
- v.uuid = res.uuid;
- navigate(v.ViewURL);
+ try {
+ const res = await VMApi.Create(v);
+ snackbar("The virtual machine was successfully created!");
+ v.uuid = res.uuid;
+ navigate(v.ViewURL);
+ } catch (e) {
+ console.error(e);
+ alert("Failed to create VM!");
+ }
};
return (
@@ -34,7 +41,53 @@ export function CreateVMRoute(): React.ReactElement {
}
export function EditVMRoute(): React.ReactElement {
- return <>todo>;
+ const navigate = useNavigate();
+ const alert = useAlert();
+ const snackbar = useSnackbar();
+
+ const { uuid } = useParams();
+
+ const [vm, setVM] = React.useState(undefined);
+
+ const load = async () => {
+ const vm = await VMApi.GetSingle(uuid!);
+ setVM(vm);
+
+ const state = await VMApi.GetState(vm);
+ if (state !== "Shutdown" && state !== "Shutoff") {
+ await alert("The Virtual machine is running, you cannot edit it!");
+ navigate(vm.ViewURL);
+ }
+ };
+
+ const save = async (v: VMInfo) => {
+ try {
+ await VMApi.UpdateSingle(v);
+ snackbar("The virtual machine was successfully updated!");
+ navigate(v.ViewURL);
+ } catch (e) {
+ console.error(e);
+ alert("Failed to update VM info!");
+ }
+ };
+
+ return (
+ (
+ {
+ navigate(vm!.ViewURL);
+ }}
+ onSave={save}
+ />
+ )}
+ />
+ );
}
function EditVMInner(p: {