summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/util/vm/VboxConfig.java
blob: d64348b65c68f5bec14b5a4da0a5d79c5ae4a08a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12



                            

                            





                                                      




                                               

                                      
                                       



                                                
                                                

                                                    
                           

                                

                                                   


                       

                                                                                  

                                    

                                                                           
        








                                                                                        












                                                                                                                 





                                                                                                                

         
                                      


                                        













































































































































































                                                                                                                                                   
 
package org.openslx.util.vm;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
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.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.log4j.Logger;
import org.apache.log4j.varia.StringMatchFilter;
import org.openslx.util.vm.VmwareConfig.ConfigEntry;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.openslx.util.vm.VmMetaData.DriveBusType;
import org.openslx.util.vm.VmMetaData.HardDisk;

public class VboxConfig
{
	private static final Logger LOGGER = Logger.getLogger( VboxConfig.class );
	XPath xPath = XPathFactory.newInstance().newXPath();
	
	private Document doc = null;
	private String displayNameExpression = "/VirtualBox/Machine/@name";
	private String displayName;
	
	private String osTypeExpression = "/VirtualBox/Machine/@OSType";
	private String osName = new String();;
	
	private String hddsExpression = "/VirtualBox/Machine/MediaRegistry/HardDisks/*";
	private ArrayList<HardDisk> hddsArray;

	// a black list of sorts of tags that need to be removed from the .vbox file
	private static String[] blackList = {"ExtraData"};
		
	public VboxConfig ( File file ) throws IOException, UnsupportedVirtualizerFormatException {
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			
			doc = dBuilder.parse( file );
			
			// TODO - does this test suffice??
			if ( !doc.getDocumentElement().getNodeName().equals( "VirtualBox" ) ) {
				throw new UnsupportedVirtualizerFormatException( "not VirtualBox image format" );
			}
			
		} catch ( ParserConfigurationException | SAXException | IOException e ) {
			LOGGER.debug( "Could not parse .Vbox", e );
			throw new UnsupportedVirtualizerFormatException( "Konnte VBoxConfig nicht erstellen!" );
		}
		displayName = new String();
		hddsArray = new ArrayList<HardDisk>();
		
	}
	
	// returns definition document
	public Document getConfigDoc() {
		return doc;
	}
	
	// initialization function
	public void init(){
		try {
			setMachineName();
			setOsType();
			setHdds();
			removeBlackListedTags();
		} catch ( XPathExpressionException e ) {
			LOGGER.debug( "Konnte VBoxConfig nicht initializieren", e );
			return;
		}
	}
	
	public void setMachineName() throws XPathExpressionException 
	{
		String name = xPath.compile( displayNameExpression ).evaluate( this.doc );
		if ( !name.isEmpty() ) {
			displayName = name;
		}
	}
	
	public void setOsType() throws XPathExpressionException 
	{
		String os = xPath.compile( osTypeExpression ).evaluate( this.doc );
		if ( !os.isEmpty() ) {
			LOGGER.debug( os);
			osName = os;
		}
	}
	
	public void setHdds() throws XPathExpressionException 
	{
		XPathExpression hddsExpr = xPath.compile( hddsExpression );
		Object result = hddsExpr.evaluate( this.doc , XPathConstants.NODESET );
		// take all the hdd nodes
		NodeList nodes = (NodeList) result;
		
	   // TODO find all HardDisk under HardDisks, give them to the hdds
		// foreach hdd in the hddnodes do:
		for ( int i = 0; i < nodes.getLength(); i++) {
			// have the node
			// take the uuid
			// look under <AttachedDevice if found and do stuff with it
			Element hddElement = (Element) nodes.item(i);
			// read the filePath
			String fileName = hddElement.getAttribute( "location" );
			// take the uuid
			String uuid = hddElement.getAttribute( "uuid" );				
			
			// do the loop  the loop
			// search in the xml thingy and give back the parent of the parent of the node that is called Image and hast the given uuid
			String pathToParent = givePathToStorageController( uuid );
			XPathExpression attachedDevicesExpr = xPath.compile( pathToParent );
			Object devicesResult = attachedDevicesExpr.evaluate( this.doc , XPathConstants.NODESET );
			NodeList devicesNodes = (NodeList) devicesResult;
			
			// TODO -- ehm...should only have 1 element...what do when there are more?
			if ( devicesNodes.getLength() > 1 ) return;
			
			Element deviceElement = (Element) devicesNodes.item( 0 );
			String controllerDevice = deviceElement.getAttribute( "type" );
			String bus = deviceElement.getAttribute( "name" );
			
			DriveBusType busType = null;
			if ( bus.equals( "IDE" ) ) {
				busType = DriveBusType.IDE;
			} else if ( bus.equals( "SCSI" ) ) {
				busType = DriveBusType.SCSI;
			} else if ( bus.equals( "SATA" ) ) {
				busType = DriveBusType.SATA;
			}
			// add them together
			hddsArray.add( new HardDisk( controllerDevice, busType, fileName ) );
		}
	}
	
	
	public void changeAttribute(String targetTag, String attribute, String newValue) 
	{
		changeAttribute(targetTag, attribute, newValue, null, null);
	}
	 
	public void changeAttribute(String targetTag, String targetAttr, String newValue, String refAttr, String refVal) 
	{
		String path = ".//"+targetTag;
		XPathExpression expr;
		NodeList nodes = null;
		try {
			expr = xPath.compile( path );
			Object nodesObject = expr.evaluate( this.doc , XPathConstants.NODESET );
			nodes = (NodeList) nodesObject;
		} catch ( XPathExpressionException e ) {
			e.printStackTrace();
		}
		
		for ( int i = 0; i < nodes.getLength(); i++) 
		{
			Element element = (Element) nodes.item(i);
			if (refAttr != null && refVal != null) 
			{
				if (element.getAttribute( refAttr ).equals( refVal )) 
				{
					element.setAttribute( targetAttr, newValue );
					break;
				}
			}
			else 
			{
				if ( nodes.getLength() > 1)
				{
					LOGGER.warn( "Aktion würde an mehreren Knotten die Value ändern; unterbrochen!" );
					return;
				}
				LOGGER.debug( element.toString() );
				element.setAttribute( targetAttr, newValue );
			}
		}
	}
	
	// cleanup part here
	private void removeBlackListedTags() throws XPathExpressionException 
	{
		// iterate over the blackList
		for ( String blackedTag : blackList ) {
			String blackedExpression = ".//"+blackedTag;
			XPathExpression blackedExpr = xPath.compile( blackedExpression );
			Object blackedResult = blackedExpr.evaluate( this.doc , XPathConstants.NODESET );
			NodeList blackedNodes = (NodeList) blackedResult;
			for ( int i = 0; i < blackedNodes.getLength(); i++) {
				Element blackedListedElement = (Element) blackedNodes.item(i);
				blackedListedElement.getParentNode().removeChild( blackedListedElement );
			}
		}
	}
	
	private String givePathToStorageController( String uuid ) 
	{
		// StorageController is the parent of the parent of node with given uuid
		return "//Image[contains(@uuid, \'"+uuid+"\')]/../..";
	}
	
	public String getDisplayName()
	{
		return displayName;
	}

	public String getOsName()
	{
		return osName;
	}
	
	public ArrayList<HardDisk> getHdds()
	{
		return hddsArray;
	}
	
	public String toString()
	{
		try {
	        StringWriter sw = new StringWriter();
	        TransformerFactory tf = TransformerFactory.newInstance();
	        Transformer transformer = tf.newTransformer();
	        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
	        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
	        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
	        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

	        transformer.transform(new DOMSource(doc), new StreamResult(sw));
	        return sw.toString();
	    } catch (Exception ex) {
	        throw new RuntimeException("Error converting to String", ex);
	    }
	}
}