/*
* This file is part of DRBD Management Console by LINBIT HA-Solutions GmbH
* written by Rasto Levrinc.
*
* Copyright (C) 2009, Rastislav Levrinc
* Copyright (C) 2009, LINBIT HA-Solutions GmbH.
*
* DRBD Management Console is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* DRBD Management Console is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with drbd; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package lcmc.vm.domain;
import java.io.StringWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.inject.Named;
import javax.inject.Provider;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import lcmc.host.domain.Host;
import lcmc.common.domain.StringValue;
import lcmc.common.domain.Value;
import lcmc.common.domain.XMLTools;
import lcmc.common.domain.ConvertCmdCallback;
import lcmc.logger.Logger;
import lcmc.logger.LoggerFactory;
import lcmc.common.domain.util.Tools;
import lcmc.common.domain.Unit;
import lcmc.vm.domain.data.DiskData;
import lcmc.vm.domain.data.FilesystemData;
import lcmc.vm.domain.data.GraphicsData;
import lcmc.vm.domain.data.InputDevData;
import lcmc.vm.domain.data.InterfaceData;
import lcmc.vm.domain.data.ParallelData;
import lcmc.vm.domain.data.SerialData;
import lcmc.vm.domain.data.SoundData;
import lcmc.vm.domain.data.VideoData;
import lcmc.vm.service.VIRSH;
import lcmc.cluster.service.ssh.ExecCommandConfig;
import lcmc.cluster.service.ssh.SshOutput;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@Named
public class VmsXml {
private static final Logger LOG = LoggerFactory.getLogger(VmsXml.class);
@Autowired
private NetworkParser networkParser;
@Autowired
private VMParser vmParser;
@Autowired
private Provider<VMCreator> vmCreatorProvider;
private final Map<String, String> namesToConfigs = new HashMap<String, String>();
/** Returns string representation of the port; it can be autoport. */
static String portString(final String port) {
if ("-1".equals(port)) {
return "auto";
}
return port;
}
/** Returns string representation graphic display SDL/VNC. */
public static String graphicsDisplayName(final String type, final String port, final String display) {
if ("vnc".equals(type)) {
return type + " : " + portString(port);
} else if ("sdl".equals(type)) {
return type + " (" + display + ')';
}
return "unknown";
}
public static Unit getUnitKiBytes() {
return new Unit("K", "K", "KiByte", "KiBytes");
}
public static Unit getUnitMiBytes() {
return new Unit("M", "M", "MiByte", "MiBytes");
}
public static Unit getUnitGiBytes() {
return new Unit("G", "G", "GiByte", "GiBytes");
}
public static Unit getUnitTiBytes() {
return new Unit("T", "T", "TiByte", "TiBytes");
}
public static Unit getUnitPiBytes() {
return new Unit("P", "P", "PiByte", "PiBytes");
}
public static Unit[] getUnits() {
return new Unit[]{getUnitKiBytes(), getUnitMiBytes(), getUnitGiBytes(), getUnitTiBytes(), getUnitPiBytes()
};
}
//TODO: move somewhere else
public static Value convertKilobytes(final String kb) {
if (!Tools.isNumber(kb)) {
return new StringValue(kb, getUnitKiBytes());
}
final double k = Long.parseLong(kb);
if (k == 0) {
return new StringValue("0", getUnitKiBytes());
}
if (k / 1024 != (long) (k / 1024)) {
return new StringValue(kb, getUnitKiBytes());
}
final double m = k / 1024;
if (m / 1024 != (long) (m / 1024)) {
return new StringValue(Long.toString((long) m), getUnitMiBytes());
}
final double g = m / 1024;
if (g / 1024 != (long) (g / 1024)) {
return new StringValue(Long.toString((long) g), getUnitGiBytes());
}
final double t = g / 1024;
if (t / 1024 != (long) (t / 1024)) {
return new StringValue(Long.toString((long) t), getUnitTiBytes());
}
final double p = t / 1024;
return new StringValue(Long.toString((long) p), getUnitPiBytes());
}
/** Converts value with unit to kilobites. */
//TODO: move somewhere else
public static long convertToKilobytes(final Value value) {
if (value == null) {
return -1;
}
final String numS = value.getValueForConfig();
if (Tools.isNumber(numS)) {
long num = Long.parseLong(numS);
final Unit unitObject = value.getUnit();
if (unitObject == null) {
return -1;
}
final String unit = unitObject.getShortName();
if ("P".equalsIgnoreCase(unit)) {
num = num * 1024 * 1024 * 1024 * 1024;
} else if ("T".equalsIgnoreCase(unit)) {
num = num * 1024 * 1024 * 1024;
} else if ("G".equalsIgnoreCase(unit)) {
num = num * 1024 * 1024;
} else if ("M".equalsIgnoreCase(unit)) {
num *= 1024;
} else if ("K".equalsIgnoreCase(unit)) {
} else {
return -1;
}
return num;
}
return -1;
}
/** Map from domain name and network name to the network data. */
private Host definedOnHost;
private final ReadWriteLock mXMLDocumentLock = new ReentrantReadWriteLock();
private final Lock mXMLDocumentReadLock = mXMLDocumentLock.readLock();
private final Lock mXMLDocumentWriteLock = mXMLDocumentLock.writeLock();
private Document xmlDocument = null;
private String oldConfig = null;
public void init(final Host definedOnHost) {
this.definedOnHost = definedOnHost;
}
public Node getDomainNode(final String domainName) {
mXMLDocumentReadLock.lock();
final Document document;
try {
document = xmlDocument;
} finally {
mXMLDocumentReadLock.unlock();
}
final XPath xpath = XPathFactory.newInstance().newXPath();
final Node domainNode;
try {
final String path = "//vms/vm[@name='" + domainName + "']/config/domain";
final NodeList domainNodes = (NodeList) xpath.evaluate(path, document, XPathConstants.NODESET);
if (domainNodes.getLength() == 1) {
domainNode = domainNodes.item(0);
} else if (domainNodes.getLength() >= 1) {
LOG.appError("getDomainNode: " + domainNodes.getLength() + " supposedly unique " + domainName + " configs.");
return null;
} else {
LOG.appWarning("getDomainNode: could not find xml for " + domainName);
return null;
}
} catch (final XPathExpressionException e) {
LOG.appError("getDomainNode: could not evaluate: ", e);
return null;
}
return domainNode;
}
private void saveDomainXML(final String configName, final Node node, final String defineCommand) {
final String xml;
try {
final Transformer transformer = TransformerFactory.newInstance().newTransformer();
final StreamResult res = new StreamResult(new StringWriter());
final Source src = new DOMSource(node);
transformer.transform(src, res);
xml = res.getWriter().toString();
} catch (final TransformerException e) {
LOG.appError("saveDomainXML: " + e.getMessageAndLocation(), e);
return;
}
if (xml != null) {
definedOnHost.getSSH().scp(xml, configName, "0600", true, defineCommand, null, null);
}
}
private Node getDevicesNode(final XPath xpath, final Node domainNode) {
try {
final String devicesPath = "devices";
final NodeList devicesNodes = (NodeList) xpath.evaluate(devicesPath, domainNode, XPathConstants.NODESET);
if (devicesNodes.getLength() != 1) {
LOG.appWarning("getDevicesNode: nodes: " + devicesNodes.getLength());
return null;
}
return devicesNodes.item(0);
} catch (final XPathExpressionException e) {
LOG.appError("getDevicesNode: could not evaluate: ", e);
return null;
}
}
public static String getConfigName(final String type, final String domainName) { //TODO: move out
if ("xen".equals(type)) {
return "/etc/xen/vm/" + domainName + ".xml";
} else if ("lxc".equals(type)) {
return "/etc/libvirt/lxc/" + domainName + ".xml";
} else {
return "/etc/libvirt/qemu/" + domainName + ".xml";
}
}
public Node createDomainXML(final String uuid,
final String domainName,
final Map<String, String> parametersMap,
final boolean needConsole) {
/* domain type: kvm/xen */
final String type = parametersMap.get(VMParams.VM_PARAM_DOMAIN_TYPE);
final String configName = getConfigName(type, domainName);
namesToConfigs.put(domainName, configName);
/* build xml */
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
final DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
} catch (final ParserConfigurationException pce) {
throw new RuntimeException("cannot configure parser", pce);
}
final Document doc = db.newDocument();
val vmCreator = vmCreatorProvider.get();
vmCreator.init(doc, parametersMap);
return vmCreator.createDomain(uuid, domainName, needConsole, type);
}
public Node modifyDomainXML(final String domainName, final Map<String, String> parametersMap) {
final String configName = namesToConfigs.get(domainName);
if (configName == null) {
return null;
}
final Node domainNode = getDomainNode(domainName);
if (domainNode == null) {
return null;
}
final Document doc = domainNode.getOwnerDocument();
val vmCreator = vmCreatorProvider.get();
vmCreator.init(doc, parametersMap);
vmCreator.modifyDomain(domainNode);
return domainNode;
}
private void modifyXMLOption(final Node domainNode,
final Element hwNode,
final String value,
final int pos,
final String tag0,
final String attribute,
final Map<String, Element> parentNodes) {
if (tag0 == null && attribute != null) {
/* attribute */
final Node attributeNode = hwNode.getAttributes().getNamedItem(attribute);
if (attributeNode == null) {
if (value != null && !"".equals(value)) {
hwNode.setAttribute(attribute, value);
}
} else if (value == null || "".equals(value)) {
hwNode.removeAttribute(attribute);
} else {
attributeNode.setNodeValue(value);
}
return;
}
if (tag0 == null) {
return;
}
final String tag;
final int i = tag0.indexOf(':');
final Element pNode;
if (i > 0) {
if (value == null) {
/* don't make empty parent */
return;
}
/* with parent */
final String parent = tag0.substring(0, i);
tag = tag0.substring(i + 1);
pNode = parentNodes.get(parent);
} else {
tag = tag0;
pNode = hwNode;
}
Element node = (Element) XMLTools.getChildNode(pNode, tag, pos);
if ((attribute != null || "True".equals(value))
&& node == null) {
node = (Element) pNode.appendChild(domainNode.getOwnerDocument().createElement(tag));
} else if (node != null && attribute == null && (value == null || "".equals(value))) {
pNode.removeChild(node);
}
parentNodes.put(tag, node);
if (attribute != null) {
final Node attributeNode = node.getAttributes().getNamedItem(attribute);
if (attributeNode == null) {
if (value != null && !"".equals(value)) {
node.setAttribute(attribute, value);
}
} else {
if (value == null || "".equals(value)) {
node.removeAttribute(attribute);
} else {
attributeNode.setNodeValue(value);
}
}
}
}
private void removeXMLOption(final Element hwNode,
int pos,
final String tag0,
final Map<String, Element> parentNodes) {
if (tag0 == null) {
return;
}
final String tag;
final int i = tag0.indexOf(':');
final Element pNode;
if (i > 0) {
/* with parent */
final String parent = tag0.substring(0, i);
tag = tag0.substring(i + 1);
pNode = parentNodes.get(parent);
} else {
tag = tag0;
pNode = hwNode;
}
Element node;
do {
node = (Element) XMLTools.getChildNode(pNode, tag, pos);
if (node != null) {
pNode.removeChild(node);
pos++;
}
} while (node != null);
}
/** Modify xml of some device element. */
private void modifyXML(final Node domainNode,
final String domainName,
final Map<String, String> tagMap,
final Map<String, String> attributeMap,
final Map<String, String> parametersMap,
final String path,
final String elementName,
final VirtualHardwareComparator vhc) {
final String configName = namesToConfigs.get(domainName);
if (configName == null) {
return;
}
if (domainNode == null) {
return;
}
final XPath xpath = XPathFactory.newInstance().newXPath();
final Node devicesNode = getDevicesNode(xpath, domainNode);
if (devicesNode == null) {
return;
}
try {
final NodeList nodes = (NodeList) xpath.evaluate(path, domainNode, XPathConstants.NODESET);
Element hwNode = vhc.getElement(nodes, parametersMap);
if (hwNode == null) {
hwNode = (Element) devicesNode.appendChild(domainNode.getOwnerDocument().createElement(elementName));
}
final Map<String, Element> parentNodes = new HashMap<String, Element>();
for (final String param : parametersMap.keySet()) {
final String value = parametersMap.get(param);
final String tag = tagMap.get(param);
final String attribute = attributeMap.get(param);
if (value == null) {
modifyXMLOption(domainNode, hwNode, value, 0, tag, attribute, parentNodes);
} else {
final String[] values = value.split("\\s*,\\s*");
int pos = 0;
for (final String v : values) {
modifyXMLOption(domainNode, hwNode, v, pos, tag, attribute, parentNodes);
pos++;
}
removeXMLOption(hwNode, pos, tag, parentNodes);
}
}
final Node hwAddressNode = XMLTools.getChildNode(hwNode, VMParams.HW_ADDRESS);
if (hwAddressNode != null) {
hwNode.removeChild(hwAddressNode);
}
} catch (final XPathExpressionException e) {
LOG.appError("modifyXML: could not evaluate: ", e);
}
}
private void removeXML(final String domainName,
final Map<String, String> parametersMap,
final String path,
final VirtualHardwareComparator vhc,
final String virshOptions) {
final String configName = namesToConfigs.get(domainName);
if (configName == null) {
return;
}
final Node domainNode = getDomainNode(domainName);
if (domainNode == null) {
return;
}
final XPath xpath = XPathFactory.newInstance().newXPath();
try {
final NodeList nodes = (NodeList) xpath.evaluate(path, domainNode, XPathConstants.NODESET);
final Element hwNode = vhc.getElement(nodes, parametersMap);
if (hwNode != null) {
hwNode.getParentNode().removeChild(hwNode);
}
} catch (final XPathExpressionException e) {
LOG.appError("removeXML: could not evaluate: ", e);
return;
}
saveAndDefine(domainNode, domainName, virshOptions);
}
public void modifyDiskXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode, domainName,
VMParams.PARAM_DISK_TAG,
VMParams.PARAM_DISK_ATTRIBUTE,
parametersMap,
"devices/disk",
"disk",
getDiskDataComparator());
}
public void modifyFilesystemXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_FILESYSTEM_TAG,
VMParams.PARAM_FILESYSTEM_ATTRIBUTE,
parametersMap,
"devices/filesystem",
"filesystem",
getFilesystemDataComparator());
}
public void saveAndDefine(final Node domainNode, final String domainName, final String virshOptions) {
final String configName = namesToConfigs.get(domainName);
final String defineCommand = VIRSH.getDefineCommand(definedOnHost,
configName + ".new" + " && rm " + configName + ".new",
virshOptions);
saveDomainXML(configName, domainNode, defineCommand);
definedOnHost.setVMInfoMD5(null);
}
public void modifyInterfaceXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_INTERFACE_TAG,
VMParams.PARAM_INTERFACE_ATTRIBUTE,
parametersMap,
"devices/interface",
"interface",
getInterfaceDataComparator());
}
public void modifyInputDevXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode, domainName,
VMParams.PARAM_INPUTDEV_TAG,
VMParams.PARAM_INPUTDEV_ATTRIBUTE,
parametersMap,
"devices/input",
"input",
getInputDevDataComparator());
}
public void modifyGraphicsXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_GRAPHICS_TAG,
VMParams.PARAM_GRAPHICS_ATTRIBUTE,
parametersMap,
"devices/graphics",
"graphics",
getGraphicsDataComparator());
}
public void modifySoundXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_SOUND_TAG,
VMParams.PARAM_SOUND_ATTRIBUTE,
parametersMap,
"devices/sound",
"sound",
getSoundDataComparator());
}
public void modifySerialXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_SERIAL_TAG,
VMParams.PARAM_SERIAL_ATTRIBUTE,
parametersMap,
"devices/serial",
"serial",
getSerialDataComparator());
}
public void modifyParallelXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_PARALLEL_TAG,
VMParams.PARAM_PARALLEL_ATTRIBUTE,
parametersMap,
"devices/parallel",
"parallel",
getParallelDataComparator());
}
/** Modify video device XML. */
public void modifyVideoXML(final Node domainNode,
final String domainName,
final Map<String, String> parametersMap) {
modifyXML(domainNode,
domainName,
VMParams.PARAM_VIDEO_TAG,
VMParams.PARAM_VIDEO_ATTRIBUTE,
parametersMap,
"devices/video",
"video",
getVideoDataComparator());
}
public void removeDiskXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/disk", getDiskDataComparator(), virshOptions);
}
public void removeFilesystemXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/filesystem", getFilesystemDataComparator(), virshOptions);
}
public void removeInterfaceXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/interface", getInterfaceDataComparator(), virshOptions);
}
public void removeInputDevXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/input", getInputDevDataComparator(), virshOptions);
}
public void removeGraphicsXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/graphics", getGraphicsDataComparator(), virshOptions);
}
public void removeSoundXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/sound", getSoundDataComparator(), virshOptions);
}
public void removeSerialXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/serial", getSerialDataComparator(), virshOptions);
}
public void removeParallelXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/parallel", getParallelDataComparator(), virshOptions);
}
public void removeVideoXML(final String domainName,
final Map<String, String> parametersMap,
final String virshOptions) {
removeXML(domainName, parametersMap, "devices/video", getVideoDataComparator(), virshOptions);
}
public boolean parseXml() {
final String command = definedOnHost.getHostParser().getDistCommand("VMSXML.GetData", (ConvertCmdCallback) null);
final SshOutput ret = definedOnHost.captureCommand(new ExecCommandConfig().command(command)
.silentCommand()
.silentOutput());
if (ret.getExitCode() != 0) {
return false;
}
final String output = ret.getOutput();
if (output == null) {
return false;
}
return parseXml(output);
}
public boolean parseXml(final String xml) {
oldConfig = xml;
final Document document = XMLTools.getXMLDocument(xml);
mXMLDocumentWriteLock.lock();
try {
xmlDocument = document;
} finally {
mXMLDocumentWriteLock.unlock();
}
if (document == null) {
return false;
}
final Node vmsNode = XMLTools.getChildNode(document, "vms");
final String md5 = XMLTools.getAttribute(vmsNode, "md5");
if (md5 == null || md5.equals(definedOnHost.getVMInfoMD5())) {
return false;
}
definedOnHost.setVMInfoMD5(md5);
final NodeList vms = vmsNode.getChildNodes();
for (int i = 0; i < vms.getLength(); i++) {
final Node node = vms.item(i);
if ("net".equals(node.getNodeName())) {
networkParser.parseNetwork(node);
} else if ("vm".equals(node.getNodeName())) {
vmParser.parseVM(node, definedOnHost, namesToConfigs);
} else if ("version".equals(node.getNodeName())) {
definedOnHost.getHostParser().setLibvirtVersion(XMLTools.getText(node));
}
}
return true;
}
public Collection<String> getDomainNames() {
return vmParser.getDomainNames();
}
public boolean isRunning(final String domainName) {
return vmParser.isRunning(domainName);
}
public boolean isSuspended(final String domainName) {
return vmParser.isSuspended(domainName);
}
public int getRemotePort(final String domainName) {
return vmParser.getRemotePort(domainName);
}
public Host getDefinedOnHost() {
return definedOnHost;
}
public Collection<Value> getConfigs() {
return vmParser.getConfigs();
}
public String getNameFromConfig(final String config) {
return vmParser.getNameFromConfig(config);
}
public String getValue(final String name, final String param) {
return vmParser.getValue(name, param);
}
public List<Value> getNetworks() {
return networkParser.getNetworks();
}
public Map<String, DiskData> getDisks(final String name) {
return vmParser.getDisks(name);
}
public Map<String, FilesystemData> getFilesystems(final String name) {
return vmParser.getFilesystems(name);
}
public Map<String, InterfaceData> getInterfaces(final String name) {
return vmParser.getInterfaces(name);
}
public Map<String, InputDevData> getInputDevs(final String name) {
return vmParser.getInputDevs(name);
}
public Map<String, GraphicsData> getGraphicDisplays(final String name) {
return vmParser.getGraphicDisplays(name);
}
public Map<String, SoundData> getSounds(final String name) {
return vmParser.getSounds(name);
}
public Map<String, SerialData> getSerials(final String name) {
return vmParser.getSerials(name);
}
public Map<String, ParallelData> getParallels(final String name) {
return vmParser.getParallels(name);
}
public Map<String, VideoData> getVideos(final String name) {
return vmParser.getVideos(name);
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getDiskDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
Element el = null;
final String targetDev = parameters.get(DiskData.SAVED_TARGET_DEVICE);
if (targetDev != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = XMLTools.getChildNode(nodes.item(i), "target");
if (targetDev.equals(XMLTools.getAttribute(mn, "dev"))) {
el = (Element) nodes.item(i);
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getFilesystemDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
Element el = null;
final String targetDev = parameters.get(FilesystemData.SAVED_TARGET_DIR);
if (targetDev != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = XMLTools.getChildNode(nodes.item(i), "target");
if (targetDev.equals(XMLTools.getAttribute(mn, "dir"))) {
el = (Element) nodes.item(i);
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getInterfaceDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
final String macAddress = parameters.get(InterfaceData.SAVED_MAC_ADDRESS);
Element el = null;
if (macAddress != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = XMLTools.getChildNode(nodes.item(i), "mac");
if (macAddress.equals(XMLTools.getAttribute(mn, "address"))) {
el = (Element) nodes.item(i);
break;
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getInputDevDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
final String type = parameters.get(InputDevData.SAVED_TYPE);
final String bus = parameters.get(InputDevData.SAVED_BUS);
Element el = null;
if (type != null && bus != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = nodes.item(i);
if (type.equals(XMLTools.getAttribute(mn, "type")) && bus.equals(XMLTools.getAttribute(mn, "bus"))) {
el = (Element) nodes.item(i);
break;
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getGraphicsDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
final String type = parameters.get(GraphicsData.SAVED_TYPE);
Element el = null;
if (type != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = nodes.item(i);
if (type.equals(XMLTools.getAttribute(mn, "type"))) {
el = (Element) nodes.item(i);
break;
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getSoundDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
final String model = parameters.get(SoundData.SAVED_MODEL);
Element el = null;
if (model != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = nodes.item(i);
if (model.equals(XMLTools.getAttribute(mn, "model"))) {
el = (Element) nodes.item(i);
break;
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getSerialDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
final String type = parameters.get(SerialData.SAVED_TYPE);
Element el = null;
if (type != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = nodes.item(i);
if (type.equals(XMLTools.getAttribute(mn, "type"))) {
el = (Element) nodes.item(i);
break;
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getParallelDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
final String type = parameters.get(ParallelData.SAVED_TYPE);
Element el = null;
if (type != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = nodes.item(i);
if (type.equals(XMLTools.getAttribute(mn, "type"))) {
el = (Element) nodes.item(i);
break;
}
}
}
return el;
}
};
}
/** Returns function that gets the node that belongs to the paremeters. */
protected VirtualHardwareComparator getVideoDataComparator() {
return new VirtualHardwareComparator() {
@Override
public Element getElement(final NodeList nodes, final Map<String, String> parameters) {
Element el = null;
final String modelType = parameters.get(VideoData.SAVED_MODEL_TYPE);
if (modelType != null) {
for (int i = 0; i < nodes.getLength(); i++) {
final Node mn = XMLTools.getChildNode(nodes.item(i), "model");
if (modelType.equals(XMLTools.getAttribute(mn, "type"))) {
el = (Element) nodes.item(i);
}
}
}
return el;
}
};
}
public Iterable<String> getSourceFileDirs() {
return vmParser.getSourceFileDirs();
}
/** Return set of mac addresses. */
public Collection<String> getUsedMacAddresses() {
return vmParser.getUsedMacAddresses();
}
public String getConfig() {
return oldConfig;
}
}