diff --git a/src/domain.h b/src/domain.h deleted file mode 100644 index 8208573..0000000 --- a/src/domain.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "utils.h" - -/// @brief Converts a container identifier to a domain identifier. -/// @param _domain The string pointer to store the resulting domain identifier in. The caller is responsible for freeing the string. -/// @param container The container identifier to convert. -/// @return The result of the operation. -result_t container_to_domain_identifier(char** _domain, const char* container); - -/// @brief Converts a domain identifier to a container identifier. -/// @param _container The string pointer to store the resulting container identifier in. The caller is responsible for freeing the string. -/// @param domain The domain identifier to convert. -/// @return The result of the operation. -result_t domain_to_container_identifier(char** _container, const char* domain); diff --git a/src/xml.c b/src/xml.c new file mode 100644 index 0000000..a8553e7 --- /dev/null +++ b/src/xml.c @@ -0,0 +1,250 @@ +#include "xml.h" + +#include "pci.h" +#include "container.h" + +#include +#include + +result_t generate_domain_xml(char** _xml, const char* container, uint64_t memory, int vcpus, const char** pci_addresses, const char** iso_paths, int vnc_port, const char* vnc_password) { + // Initialize the output parameters + *_xml = NULL; + + // Generate the XML configuration for the PCI devices + char* pci_xml; + result_t result = generate_pci_xml(&pci_xml, pci_addresses); + if (result != success()) + return result; + + // Generate the XML configuration for the ISO images + char* iso_xml; + result = generate_iso_xml(&iso_xml, iso_paths); + if (result != success()) { + free(pci_xml); + return result; + } + + // Generate the XML configuration for the VNC server + char* vnc_xml; + result = generate_vnc_xml(&vnc_xml, vnc_port, vnc_password); + if (result != success()) { + free(pci_xml); + free(iso_xml); + return result; + } + + // Get the container path + char* container_path; + result = get_container_path(&container_path, container); + if (result != success()) { + free(pci_xml); + free(iso_xml); + free(vnc_xml); + return result; + } + + // Generate the XML configuration for the domain + char* xml; + result = format(&xml, "\n" + "%s\n" + "\n\n" + "%lu\n" + "%d\n" + "\n" + "\n\n" + "\n" + "hvm\n" + "\n" + "\n" + "\n\n" + "\n" + "\n" + "\n" + "\n" + "\n\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n\n" + "destroy\n" + "destroy\n" + "destroy\n" + "\n" + "\n" + "\n" + "\n" + "\n\n" + "\n" + "/usr/bin/qemu-system-x86_64\n" + "\n\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n\n" + "%s" + "\n\n" + "%s" + "\n\n" + "%s" + "\n\n" + "\n" + "\n" + "\n" + "\n", + container, memory, vcpus, container_path, pci_xml, iso_xml, vnc_xml); + free(pci_xml); + free(iso_xml); + free(vnc_xml); + free(container_path); + + if (result != success()) + return result; + + // Return the result + *_xml = xml; + return success(); +} + +result_t generate_pci_xml(char** _xml, const char** pci_addresses) { + // Initialize the output parameters + *_xml = NULL; + + // Get the IOMMU group for each PCI address + int* iommu_groups; + int iommu_groups_count; + result_t result = get_iommu_groups(&iommu_groups, &iommu_groups_count, pci_addresses); + if (result != success()) + return result; + + // Get the PCI devices for each IOMMU group (the devices that should be passed through) + char** pci_devices; + result = get_iommu_groups_devices(&pci_devices, iommu_groups, iommu_groups_count); + + // Free the IOMMU groups as they are no longer needed + free(iommu_groups); + + if (result != success()) + return result; + + // Generate the XML configuration for the PCI devices + char* xml = strdup(""); + + // For each PCI device, generate the XML configuration, and append it to the result + for (int i = 0; pci_devices[i] != NULL; i++) { + // Split the PCI address into domain, bus, device, and function + int domain, bus, device, function; + if (sscanf(pci_devices[i], "%04x:%02x:%02x.%x", &domain, &bus, &device, &function) != 4) { + free(xml); + for (int j = 0; pci_devices[j] != NULL; j++) + free(pci_devices[j]); + free(pci_devices); + return failure("Failed to parse PCI address."); + } + + // Generate the XML configuration for the PCI device + char* device_xml; + result = format(&device_xml, "\n" + "\n" + "
\n" + "\n" + "\n", + domain, bus, device, function); + if (result != success()) { + free(xml); + for (int j = 0; pci_devices[j] != NULL; j++) + free(pci_devices[j]); + free(pci_devices); + return result; + } + + // Append the new XML configuration to the result + char* new_xml; + result = format(&new_xml, "%s%s", xml, device_xml); + free(device_xml); + + if (result != success()) { + free(xml); + for (int j = 0; pci_devices[j] != NULL; j++) + free(pci_devices[j]); + free(pci_devices); + return result; + } + + // Swap the old and new XML configurations + free(xml); + xml = new_xml; + } + + // Free the PCI devices as they are no longer needed + for (int i = 0; pci_devices[i] != NULL; i++) + free(pci_devices[i]); + free(pci_devices); + + // Return the result + *_xml = xml; + return success(); +} + +result_t generate_iso_xml(char** _xml, const char** iso_paths) { + // Initialize the output parameters + *_xml = NULL; + + // Generate the XML configuration for the ISO images + char* xml = strdup(""); + + // For each ISO image, generate the XML configuration, and append it to the result + for (int i = 0; iso_paths[i] != NULL; i++) { + if (i > 25) { + free(xml); + return failure("Too many ISO images."); + } + + char* iso_xml; + result_t result = format(&iso_xml, "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", + iso_paths[i], 'b' + i, 2 + i); // hda is reserved for the main disk + if (result != success()) { + free(xml); + return result; + } + + // Append the new XML configuration to the result + char* new_xml; + result = format(&new_xml, "%s%s", xml, iso_xml); + free(iso_xml); + + if (result != success()) { + free(xml); + return result; + } + + // Swap the old and new XML configurations + free(xml); + xml = new_xml; + } + + // Return the result + *_xml = xml; + return success(); +} + +result_t generate_vnc_xml(char** _xml, int vnc_port, const char* vnc_password) { + // Initialize the output parameters + *_xml = NULL; + + // Generate the XML configuration for the VNC server (if enabled) + if (vnc_port != 0) + return format(_xml, "", vnc_port, vnc_password); + + return format(_xml, ""); +}