Implemented basic xml generation
This commit is contained in:
parent
b746e30627
commit
18eefa93c3
15
src/domain.h
15
src/domain.h
@ -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);
|
250
src/xml.c
Normal file
250
src/xml.c
Normal file
@ -0,0 +1,250 @@
|
||||
#include "xml.h"
|
||||
|
||||
#include "pci.h"
|
||||
#include "container.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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, "<domain type='kvm'>\n"
|
||||
"<name>%s</name>\n"
|
||||
"\n<!-- Resources -->\n"
|
||||
"<memory unit='B'>%lu</memory>\n"
|
||||
"<vcpu>%d</vcpu>\n"
|
||||
"<cpu mode='host-passthrough'/>\n"
|
||||
"\n<!-- OS -->\n"
|
||||
"<os>\n"
|
||||
"<type arch='x86_64' machine='q35'>hvm</type>\n"
|
||||
"<bootmenu enable='no'/>\n"
|
||||
"</os>\n"
|
||||
"\n<!-- Features -->\n"
|
||||
"<features>\n"
|
||||
"<acpi/>\n"
|
||||
"<apic/>\n"
|
||||
"</features>\n"
|
||||
"\n<!-- Clock -->\n"
|
||||
"<clock offset='utc'>\n"
|
||||
"<timer name='rtc' tickpolicy='catchup'/>\n"
|
||||
"<timer name='pit' tickpolicy='delay'/>\n"
|
||||
"<timer name='hpet' present='no'/>\n"
|
||||
"</clock>\n"
|
||||
"\n<!-- Behavior -->\n"
|
||||
"<on_poweroff>destroy</on_poweroff>\n"
|
||||
"<on_reboot>destroy</on_reboot>\n"
|
||||
"<on_crash>destroy</on_crash>\n"
|
||||
"<pm>\n"
|
||||
"<suspend-to-mem enabled='yes'/>\n"
|
||||
"<suspend-to-disk enabled='yes'/>\n"
|
||||
"</pm>\n"
|
||||
"\n<!-- Devices -->\n"
|
||||
"<devices>\n"
|
||||
"<emulator>/usr/bin/qemu-system-x86_64</emulator>\n"
|
||||
"\n<!-- Disks -->\n"
|
||||
"<disk type='file' device='disk'>\n"
|
||||
"<driver name='qemu' type='qcow2'/>\n"
|
||||
"<source file='%s'/>\n"
|
||||
"<target dev='hda' bus='sata'/>\n"
|
||||
"<boot order='1'/>\n"
|
||||
"</disk>\n"
|
||||
"\n<!-- PCI devices -->\n"
|
||||
"%s"
|
||||
"\n<!-- ISO images -->\n"
|
||||
"%s"
|
||||
"\n<!-- VNC server -->\n"
|
||||
"%s"
|
||||
"\n<!-- Misc -->\n"
|
||||
"<watchdog model='itco' action='poweroff'/>\n"
|
||||
"<memballoon model='none'/>\n"
|
||||
"</devices>\n"
|
||||
"</domain>\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, "<hostdev mode='subsystem' type='pci' managed='yes'>\n"
|
||||
"<source>\n"
|
||||
"<address domain='0x%04x' bus='0x%02x' slot='0x%02x' function='0x%x'/>\n"
|
||||
"</source>\n"
|
||||
"</hostdev>\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, "<disk type='file' device='cdrom'>\n"
|
||||
"<driver name='qemu' type='raw'/>\n"
|
||||
"<source file='%s'/>\n"
|
||||
"<target dev='hd%c' bus='sata'/>\n"
|
||||
"<readonly/>\n"
|
||||
"<boot order='%d'/>\n"
|
||||
"</disk>\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, "<graphics type='vnc' port='%d' autoport='no' listen='0.0.0.0' passwd='%s'/>", vnc_port, vnc_password);
|
||||
|
||||
return format(_xml, "");
|
||||
}
|
Loading…
Reference in New Issue
Block a user