@unraid/libvirt
Version:
Libvirt bindings for Node.js® - forked from vmngr/libvirt
447 lines • 15.1 kB
JavaScript
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable no-case-declarations */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/**
* Copyright 2019 Leon Rinkel <leon@rinkel.me> and vmngr/libvirt contributers.
*
* This file is part of the vmngr/libvirt project and is subject to the MIT
* license as in the LICENSE file in the project root.
*
* @brief Contains helper functions to deserialize / serialize domain
* descriptions from / to XML.
*/
import xml2js from 'xml2js';
const $ = {};
export const domainOsXml = {
serialize(osDesc) {
return {
$,
...(osDesc.type ? {
type: {
$: {
...(osDesc.type.arch ? {
arch: osDesc.type.arch
} : {}),
...(osDesc.type.machine ? {
machine: osDesc.type.machine
} : {})
},
...(osDesc.type.value ? {
_: osDesc.type.value
} : {})
}
} : {}),
...(osDesc.boot ? {
boot: {
$: {
...(osDesc.boot.dev ? {
dev: osDesc.boot.dev
} : {})
}
}
} : {}),
...(osDesc.loader ? {
loader: Array.isArray(osDesc.loader) ? osDesc.loader.map(loader => ({
$: {
...(loader.readonly ? {
readonly: loader.readonly
} : {}),
...(loader.type ? {
type: loader.type
} : {})
},
...(loader.value ? {
_: loader.value
} : {})
})) : [{
$: {
...(osDesc.loader.readonly ? {
readonly: osDesc.loader.readonly
} : {}),
...(osDesc.loader.type ? {
type: osDesc.loader.type
} : {})
},
...(osDesc.loader.value ? {
_: osDesc.loader.value
} : {})
}]
} : {})
};
},
deserialize(os) {
const osDesc = {};
if (os.type?.[0]) {
osDesc.type = {};
if (os.type[0].$.arch) {
osDesc.type.arch = os.type[0].$.arch;
}
if (os.type[0].$.machine) {
osDesc.type.machine = os.type[0].$.machine;
}
if (os.type[0]._) {
osDesc.type.value = os.type[0]._;
}
}
if (os.boot?.[0]) {
osDesc.boot = {};
if (os.boot[0].$.dev) {
osDesc.boot.dev = os.boot[0].$.dev;
}
}
if (os.loader?.[0]) {
osDesc.loader = {};
if (os.loader[0].$.readonly) {
osDesc.loader.readonly = os.loader[0].$.readonly;
}
if (os.loader[0].$.type) {
osDesc.loader.type = os.loader[0].$.type;
}
if (os.loader[0]._) {
osDesc.loader.value = os.loader[0]._;
}
}
return osDesc;
}
};
export const domainDiskXml = {
serialize(diskDesc) {
return {
$: {
...(diskDesc.type ? { type: diskDesc.type } : {}),
...(diskDesc.device ? { device: diskDesc.device } : {})
},
...(diskDesc.driver ? {
driver: {
$: {
...(diskDesc.driver.name ? { name: diskDesc.driver.name } : {}),
...(diskDesc.driver.type ? { type: diskDesc.driver.type } : {})
}
}
} : {}),
...(diskDesc.source ? {
source: {
$: {
...(diskDesc.source.file ? { file: diskDesc.source.file } : {})
}
}
} : {}),
...(diskDesc.target ? {
target: {
$: {
...(diskDesc.target.dev ? { dev: diskDesc.target.dev } : {}),
...(diskDesc.target.bus ? { bus: diskDesc.target.bus } : {})
}
}
} : {})
};
},
deserialize(disk) {
const diskDesc = {};
if (disk.$.type) {
diskDesc.type = disk.$.type;
}
if (disk.$.device) {
diskDesc.device = disk.$.device;
}
if (disk.driver && disk.driver[0]) {
diskDesc.driver = {};
if (disk.driver[0].$.name) {
diskDesc.driver.name = disk.driver[0].$.name;
}
if (disk.driver[0].$.type) {
diskDesc.driver.type = disk.driver[0].$.type;
}
}
if (disk.source && disk.source[0]) {
diskDesc.source = {};
if (disk.source[0].$.file) {
diskDesc.source.file = disk.source[0].$.file;
}
}
if (disk.target && disk.target[0]) {
diskDesc.target = {};
if (disk.target[0].$.dev) {
diskDesc.target.dev = disk.target[0].$.dev;
}
if (disk.target[0].$.bus) {
diskDesc.target.bus = disk.target[0].$.bus;
}
}
return diskDesc;
}
};
export const domainInterfaceXml = {
serialize(interfaceDesc) {
return {
$: {
...(interfaceDesc.type ? { type: interfaceDesc.type } : {})
},
...(interfaceDesc.source ? {
source: {
$: {
...(interfaceDesc.source.network ? { network: interfaceDesc.source.network } : {})
}
}
} : {}),
...(interfaceDesc.mac ? {
mac: {
$: {
...(interfaceDesc.mac.address ? { address: interfaceDesc.mac.address } : {})
}
}
} : {}),
...(interfaceDesc.model ? {
model: {
$: {
...(interfaceDesc.model.type ? { type: interfaceDesc.model.type } : {})
}
}
} : {})
};
},
deserialize(iface) {
const interfaceDesc = {};
if (iface.$.type) {
interfaceDesc.type = iface.$.type;
}
if (iface.source && iface.source[0]) {
interfaceDesc.source = {};
if (iface.source[0].$.network) {
interfaceDesc.source.network = iface.source[0].$.network;
}
}
if (iface.mac && iface.mac[0]) {
interfaceDesc.mac = {};
if (iface.mac[0].$.address) {
interfaceDesc.mac.address = iface.mac[0].$.address;
}
}
if (iface.model && iface.model[0]) {
interfaceDesc.model = {};
if (iface.model[0].$.type) {
interfaceDesc.model.type = iface.model[0].$.type;
}
}
return interfaceDesc;
}
};
export const domainGraphicsXml = {
serialize(graphicsDesc) {
return {
$: {
...(graphicsDesc.type ? { type: graphicsDesc.type } : {}),
...(graphicsDesc.port ? { port: graphicsDesc.port } : {}),
...(graphicsDesc.listen ? { listen: graphicsDesc.listen } : {}),
...(graphicsDesc.passwd ? { passwd: graphicsDesc.passwd } : {})
}
};
},
deserialize(graphics) {
return {
...(graphics.$.type ? { type: graphics.$.type } : {}),
...(graphics.$.port ? { port: Number(graphics.$.port) } : {}),
...(graphics.$.listen ? { listen: graphics.$.listen } : {}),
...(graphics.$.passwd ? { passwd: graphics.$.passwd } : {})
};
}
};
export function domainDescToXml(desc) {
const domain = { $: {} };
if (desc.type) {
domain.$.type = desc.type;
}
if (desc.id) {
domain.$.id = desc.id;
}
if (desc.name) {
domain.name = desc.name;
}
if (desc.uuid) {
domain.uuid = desc.uuid;
}
if (desc.memory) {
domain.memory = { $: {} };
if (desc.memory.unit) {
domain.memory.$.unit = desc.memory.unit;
}
if (desc.memory.value) {
domain.memory._ = desc.memory.value;
}
}
if (desc.currentMemory) {
domain.currentMemory = { $: {} };
if (desc.currentMemory.unit) {
domain.currentMemory.$.unit = desc.currentMemory.unit;
}
if (desc.currentMemory.value) {
domain.currentMemory._ = desc.currentMemory.value;
}
}
if (desc.vcpu) {
domain.vcpu = { $: {} };
if (desc.vcpu.placement) {
domain.vcpu.$.placement = desc.vcpu.placement;
}
if (desc.vcpu.value) {
domain.vcpu._ = desc.vcpu.value;
}
}
if (desc.os) {
domain.os = domainOsXml.serialize(desc.os);
}
if (desc.devices) {
domain.devices = {
emulator: [],
disk: [],
interface: [],
console: [],
graphics: [],
acpi: []
};
for (const deviceDesc of desc.devices) {
switch (deviceDesc.type) {
case 'emulator':
const emulatorDesc = deviceDesc.emulator;
if (emulatorDesc.value) {
domain.devices.emulator.push({
_: emulatorDesc.value
});
}
break;
case 'disk':
domain.devices.disk.push(domainDiskXml.serialize(deviceDesc.disk));
break;
case 'interface':
domain.devices.interface.push(domainInterfaceXml.serialize(deviceDesc.interface));
break;
case 'console':
const consoleDesc = deviceDesc.console;
domain.devices.console.push({
$: {
type: consoleDesc.type
}
});
break;
case 'graphics':
domain.devices.graphics.push(domainGraphicsXml.serialize(deviceDesc.graphics));
break;
case 'acpi':
domain.devices.acpi.push({});
break;
default:
}
}
}
const builder = new xml2js.Builder({ headless: true });
return builder.buildObject({ domain });
}
// eslint-disable-next-line complexity
export async function domainDescFromXml(xml) {
const domainDesc = {};
const parsed = await xml2js.parseStringPromise(xml);
if (!parsed.domain) {
throw new Error('Unable to parse domain xml');
}
if (parsed.domain.$.type) {
domainDesc.type = parsed.domain.$.type;
}
if (parsed.domain.$.id) {
domainDesc.id = parsed.domain.$.id;
}
if (parsed.domain.name?.[0]) {
domainDesc.name = parsed.domain.name[0];
}
if (parsed.domain.uuid?.[0]) {
domainDesc.uuid = parsed.domain.uuid[0];
}
if (parsed.domain.memory?.[0]) {
if (typeof parsed.domain.memory[0] === 'object') {
domainDesc.memory = {
value: Number(parsed.domain.memory[0]._),
unit: parsed.domain.memory[0].$.unit
};
}
else if (typeof parsed.domain.memory[0] === 'string') {
domainDesc.memory = {
value: Number(parsed.domain.memory[0])
};
}
}
if (parsed.domain.currentMemory?.[0]) {
if (typeof parsed.domain.currentMemory[0] === 'object') {
domainDesc.currentMemory = {
value: Number(parsed.domain.currentMemory[0]._),
unit: parsed.domain.currentMemory[0].$.unit
};
}
else if (typeof parsed.domain.currentMemory[0] === 'string') {
domainDesc.currentMemory = {
value: Number(parsed.domain.currentMemory[0])
};
}
}
if (parsed.domain.vcpu?.[0]) {
if (typeof parsed.domain.vcpu[0] === 'object') {
domainDesc.vcpu = {
value: Number(parsed.domain.vcpu[0]._),
placement: parsed.domain.vcpu[0].$.placement
};
}
else if (typeof parsed.domain.vcpu[0] === 'string') {
domainDesc.vcpu = {
value: Number(parsed.domain.vcpu[0])
};
}
}
if (parsed.domain.os?.[0]) {
domainDesc.os = domainOsXml.deserialize(parsed.domain.os[0]);
}
if (parsed.domain.devices?.[0]) {
domainDesc.devices = [];
if (parsed.domain.devices[0].emulator) {
domainDesc.devices.push({
type: 'emulator',
emulator: {
value: parsed.domain.devices[0].emulator[0]
}
});
}
if (parsed.domain.devices[0].disk) {
for (const disk of parsed.domain.devices[0].disk) {
domainDesc.devices.push({
type: 'disk',
disk: domainDiskXml.deserialize(disk)
});
}
}
if (parsed.domain.devices[0].interface) {
for (const iface of parsed.domain.devices[0].interface) {
domainDesc.devices.push({
type: 'interface',
interface: domainInterfaceXml.deserialize(iface)
});
}
}
if (parsed.domain.devices[0].console) {
for (const cnsole of parsed.domain.devices[0].console) {
domainDesc.devices.push({
type: 'console',
console: { type: cnsole.$.type }
});
}
}
if (parsed.domain.devices[0].graphics) {
for (const graphics of parsed.domain.devices[0].graphics) {
domainDesc.devices.push({
type: 'graphics',
graphics: domainGraphicsXml.deserialize(graphics)
});
}
}
}
return domainDesc;
}
//# sourceMappingURL=domain-xml.js.map