#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, ""); }