diff --git a/src/database.py b/src/database.py
index 4758c9c7fac8b31a337c4de965c667557aede0fc..148482750ae9f18024fbd2254651e8e8172cd28e 100644
--- a/src/database.py
+++ b/src/database.py
@@ -20,7 +20,8 @@ class DataBase:
                 vms = util.get_vms(db)
                 pass
             vm_dict = dict(map(lambda vm_elem: (vm_elem.name, vm_elem), vms))
-            return collections.OrderedDict([ (n,vm_dict[n]) for n in sorted(vm_dict)])
+            return collections.OrderedDict([ (n,vm_dict[n]) for n in
+                                             sorted(vm_dict)])
         self.vms = util.FutureCache(vms, self)
         self.hypervisors = vm.get_hypervisors(self)
         self.mount = util.FutureCache(mount.get_active_mounts)
diff --git a/src/images.py b/src/images.py
index cee4a4b236b96edf06ad2026f2ef23a5c0a4a1b4..be1985e225ff2e3d1d43f14cc0fbcf24cfa76ebd 100644
--- a/src/images.py
+++ b/src/images.py
@@ -31,4 +31,3 @@ def mount_all(db):
             vm.mount(db)
         pass
     pass
-    
diff --git a/src/mount.py b/src/mount.py
index fb3702fc3829f4b8d949f321fcb07706e0561426..214e9477436450ace104e7933283f1412ffa57c3 100644
--- a/src/mount.py
+++ b/src/mount.py
@@ -1,6 +1,6 @@
 class Mount:
 
-    def __init__(self, parent, root, mount, mount_opt, tags, fstype, 
+    def __init__(self, parent, root, mount, mount_opt, tags, fstype,
                  super_opt, active):
         self.parent = parent
         self.root  = root
@@ -16,7 +16,7 @@ class Mount:
             pass
         pass
         self.is_mounted = True
-    
+
     def add_child(self, child):
         self.child.append(child)
         pass
@@ -25,14 +25,6 @@ class Mount:
         self.active = False
         for c in self.child:
             c.set_inactive()
-
-    def unmount(self):
-        if self.is_mounted:
-            for c in self.child:
-                c.unmount()
-                pass
-            self.is_mounted = False
-            subprocess.check_call(['umount', self.mount])  
             pass
         pass
 
diff --git a/src/parser.py b/src/parser.py
index daeb5dbd89f5341d9dcdfe63fe79c479dc5cda4b..b9e5ea54d8f01b9fe0a195a2a6fea4e57c0c67ef 100755
--- a/src/parser.py
+++ b/src/parser.py
@@ -64,14 +64,14 @@ SPECIAL ATTRIBUTES
     _tag                    the XML tag
 
   the top level node of %(module)s.parse also contains
-    
+
     _mtime                  modification time of XML source (0 if not file)
     _url                    the URL that was parsed
 
   [ see also %(module)s.Node ]
 
-EXAMPLE  
-  
+EXAMPLE
+
   Assume an XML document with the following content:
 
   <doc attr='doc_attr'>
@@ -133,19 +133,19 @@ def xml_escape(s):
             result += '&amp;'
         else:
             result += c
-        
+
     return result
 
 class ChildAccessor:
     """Helper class for iterating over xml trees
-    
+
     [see Node._child(...)]
     """
     def __init__(self, root, path):
         self._root = root
         self._path = path
         self._elem = None
-        
+
     def __getattr__(self, attr):
         if attr.startswith("__") and attr != "__":
             raise AttributeError(attr)
@@ -172,7 +172,7 @@ class ChildAccessor:
         if self._elem == None:
             self._elem = self._root._child_path(self._path)
         return self._elem.__len__()
-    
+
     def __getitem__(self, index):
         if self._elem == None:
             self._elem = self._root._child_path(self._path)
@@ -209,7 +209,7 @@ class AttributeAccessor:
             node = node._parent
             i += 1
         return None
-        
+
     def __getitem__(self, index):
         """declared value of attr
 
@@ -226,7 +226,7 @@ class AttributeAccessor:
                 return node._attribute[self._name]
             except:
                 return None
-            
+
         elif index.__class__ == slice:
             if index.step == None:
                 # Return first declaration within range
@@ -261,7 +261,7 @@ class AttributeAccessor:
                 return result
         else:
             raise TypeError("Illegal index kind %s" % index.__class__)
-        
+
 
 class Iterator:
     """Fix for python 2.2"""
@@ -277,7 +277,7 @@ class Iterator:
             raise StopIteration()
         self.current += 1
         return self.elem[self.current - 1]
-        
+
 class Node:
     def __init__(self, tag, line=None, attr={}):
         self._tag = tag
@@ -298,15 +298,15 @@ class Node:
         """Copy node, but not children"""
         result = Node(self._tag, self._line, self._attribute)
         return result
-    
+
     def __deepcopy__(self, memo):
         """Copy node and all children"""
         result = self.__copy__()
         for c in self._children:
             result._add(c.__deepcopy__(memo))
         return result
-    
-    def __getattr__(self, attr):            
+
+    def __getattr__(self, attr):
         if attr.startswith("__") and attr != "__":
             raise AttributeError(attr)
         elif attr.startswith("_") and attr.endswith("_"):
@@ -321,7 +321,7 @@ class Node:
                 raise AttributeError(attr)
         else:
             return AttributeAccessor(self, attr)
-    
+
     def _xml(self, indent=0, attr_key=None, node_key=None, width=80):
         """Generate a prettyprinted xml of the tree rooted in this node"""
         result = ""
@@ -352,20 +352,20 @@ class Node:
     def _child(self, name=''):
         """Return all children matching 'name', '' matches all children"""
         return ChildAccessor(self, [ name ])
-       
+
     def _attr(self, name):
         """Return a accessor for attribute matching 'name'
 
         [ see AttributeAccessor ]
         """
         return AttributeAccessor(self, name)
-       
+
     def _child_path(self, path=None):
         if path == None or len(path) == 0:
             # Return all immediate children
             return self._children
         else:
-            # Return children matching the path given 
+            # Return children matching the path given
             result = []
             for c in self._children:
                 if c._tag == path[0] or path[0] == '':
@@ -404,11 +404,11 @@ class Comment:
         """Copy self"""
         result = Comment(self._content, self._line)
         return result
-    
+
     def __deepcopy__(self, memo):
         """Copy node and all children"""
         return self.__copy__()
-    
+
     def _xml(self, indent=0, attr_key=None, node_key=None, width=80):
         """Generate a prettyprinted xml of the tree rooted in this node"""
         result = "%s<!--" % ("  " * indent)
@@ -424,13 +424,13 @@ class Parser:
         """Parse the given url into .tree
 
         augment the tree with
-          ._mtime == url modification time if url is a file, 
+          ._mtime == url modification time if url is a file,
                      current time otherwise
           ._url   == the url that was parsed
         """
         self.include_comments = include_comments
         self.tree = None
-        
+
         # Create a xml parser
         self.parser = xml.parsers.expat.ParserCreate()
         self.parser.StartElementHandler = self.startElement
@@ -451,8 +451,8 @@ class Parser:
             pass
         self.tree._mtime = mtime
         self.tree._url = url
-            
-            
+
+
     #
     # This will be called by the  parser for the top hostinfo node
     #
@@ -467,12 +467,12 @@ class Parser:
         for (name, value) in attrs.items():
             child._set(name, value)
         self.current.append(child)
-        
+
     def endElement(self, tag):
         child = self.current.pop()
         parent = self.current[-1]
         parent._add(child)
- 
+
     def characters(self, char):
         if not char.isspace():
             self.current[-1]._append(char)
@@ -487,7 +487,7 @@ def parse(source, include_comments=False, url=None):
     (scheme, host, path, param, query, frag) = urlparse(source)
     if not scheme:
         data = open(source).read()
-        mtime = os.stat(source)[stat.ST_MTIME]                
+        mtime = os.stat(source)[stat.ST_MTIME]
         pass
     else:
         u = urllib2.urlopen(source)
@@ -501,9 +501,9 @@ def parse(source, include_comments=False, url=None):
             pass
         pass
     pass
-    return Parser(data, url=url or source, mtime=mtime, 
+    return Parser(data, url=url or source, mtime=mtime,
                   include_comments=include_comments).tree
 
 def parse_string(source, include_comments=False):
-    return Parser(source, url=None, mtime=None, 
+    return Parser(source, url=None, mtime=None,
                   include_comments=include_comments).tree
diff --git a/src/util.py b/src/util.py
index 5d19c66cef5be1f684dd7647c698235a19139b60..584251cdf681c2472c28385aace1c0c7a34a2133 100644
--- a/src/util.py
+++ b/src/util.py
@@ -1,5 +1,4 @@
 import os
-import calendar
 import ipaddress
 import subprocess
 import re
@@ -47,26 +46,25 @@ def qemu_img_info(img):
     result = AttributeDict()
     for l in run('qemu-img', 'info', '--force-share', img):
         m = re.match('^file format:\\s*(\\S+)\\s*$', l)
-        if m: 
+        if m:
             result.format = m.group(1)
             continue
         m = re.match('^virtual size:.*[(]([0-9]+) bytes[)]', l)
-        if m: 
+        if m:
             result.size = int(m.group(1))
             continue
         pass
     return result
 
 def is_mounted(path):
-    return (os.path.exists(path) and 
+    return (os.path.exists(path) and
             os.stat(path).st_dev != os.stat(os.path.dirname(path)).st_dev)
 
-class AttributeDict(dict): 
+class AttributeDict(dict):
     __getattr__ = dict.__getitem__
     __setattr__ = dict.__setitem__
 
 class FutureCache:
-    
     def __init__(self, func, *args):
         self._func = func
         self._args = args
@@ -106,7 +104,7 @@ class FutureCache:
     def clear_cache(self):
         self._cache = None
         pass
-        
+
 class InvalidHostException(Exception):
 
     def __init__(self, allowed=[]):
@@ -114,11 +112,14 @@ class InvalidHostException(Exception):
         super(Exception, self).__init__('Invalid host (allowed=%s)' % allowed)
     pass
 
+class MountException(Exception):
+    pass
+
 class NeedCommandException(Exception):
 
     def __init__(self, command):
         self.command = command
-        super(Exception, self).__init__("Run '%s'" % 
+        super(Exception, self).__init__("Run '%s'" %
                                         (' '.join(map(str, command))))
         pass
 
@@ -129,18 +130,18 @@ class NeedOptionException(Exception):
     def __init__(self, option):
         self.option = option
         super(Exception, self).__init__("You need to specify '%s'" % option)
-    
+
 class Interface:
 
     def __init__(self, db):
-        self.db = db 
+        self.db = db
         def host(db):
             net = db.prefix[1][0]
             result = {}
-            for h,i,b in [ (i.name[2], IPAddress(i.address[0]), 
+            for h,i,b in [ (i.name[2], IPAddress(i.address[0]),
                             i.bridge[1])
                            for i in db.tree._host_._interface_._ipv6_
-                           if (i.address[0] and 
+                           if (i.address[0] and
                                IPAddress(i.address[0]) in net)]:
                 result[h] = (i, b)
                 pass
@@ -155,9 +156,9 @@ class Interface:
         except KeyError:
             raise Exception('%s is not reachable from this machine' % host)
         pass
-            
+
     def bridge(self, host):
-        try: 
+        try:
             return self.host[host][1]
         except KeyError:
             raise Exception('%s is not reachable from this machine' % host)
@@ -172,16 +173,18 @@ class VirtualMachine:
         self.qemu = qemu
         self.netgroups = netgroups
         self.correct = True
+        self.physical = False
         if db.option.virtualize_physical:
             self.name = qemu.name[0]
             self.physical = True
             encoded_name = self.name.encode('utf-8')
             name_hash = sha512(encoded_name).digest()
-            hypervisor_index = (int.from_bytes(name_hash) %
-                                len(db.option.check_hypervisor))
-            self.host = list(sorted(db.option.check_hypervisor))[hypervisor_index]
+            if not db.option.vm_xml:
+                hypervisor_index = (int.from_bytes(name_hash) %
+                                    len(db.option.check_hypervisor))
+                self.host = list(sorted(db.option.check_hypervisor))[hypervisor_index]
 
-            if not db.option.create:
+            if not db.option.create and not db.option.vm_xml:
                 if (self.host not in db.hypervisors or
                     self.name not in db.hypervisors[self.host].domain):
                     self.correct = False
@@ -192,19 +195,21 @@ class VirtualMachine:
                 pass
             pass
 
-        if db.option.virtualize_physical and db.option.create:
+        if db.option.virtualize_physical and (db.option.create or
+                                              db.option.vm_xml):
             self.memory = db.option.physical_ram
             self.arch = db.option.physical_arch
             self.machine_type = db.option.physical_machine_type
             self.cpu_model = db.option.physical_model
             self.cpus = db.option.physical_cores
+            h = "" if db.option.vm_xml else self.host
             uuid_seed=(int.from_bytes(encoded_name)
                        + int.from_bytes(self.memory.encode('utf-8'))
                        + int.from_bytes(self.arch.encode('utf-8'))
                        + int.from_bytes(self.machine_type.encode('utf-8'))
                        + int.from_bytes(self.cpu_model.encode('utf-8'))
                        + int.from_bytes(self.cpus.encode('utf-8'))
-                       + int.from_bytes(str(self.host).encode('utf-8')))
+                       + int.from_bytes(str(h).encode('utf-8')))
             while uuid_seed < (1<<100):
                 uuid_seed=uuid_seed*uuid_seed
                 pass
@@ -231,7 +236,6 @@ class VirtualMachine:
             self.machine_type = qemu_tag.machine[0]
             self.cpu_model = qemu_tag.cpu_model[0]
             self.cpus = qemu_tag.cpus[0]
-            self.physical = False
             self.uuid = qemu_tag.uuid[0]
             pass
         def regular_disks(disk_tree):
@@ -253,18 +257,19 @@ class VirtualMachine:
         def physical_disks():
             disk = []
             pd = qemu._qemu_[0]
-            if db.option.create:
+            if db.option.create or db.option.vm_xml:
                 for d_name in db.option.physical_disks:
                     size = db.option.physical_disks[d_name]
                     path = db.option.physical_disk_paths[d_name] or '/tw/general'
+                    h = "" if db.option.vm_xml else self.host
                     disk.append(Disk(db=db,
                                      vm=self,
-                                     host=self.host,
+                                     host=h,
                                      root=path,
                                      id=d_name, raid=False, format='qcow2',
                                      size=size))
                     attr = {"root": path,
-                            "host": self.host,
+                            "host": h,
                             "id": d_name,
                             "size": size,
                             "format": 'qcow2'
@@ -276,7 +281,8 @@ class VirtualMachine:
             return disk
         def disk():
             disk = []
-            if db.option.virtualize_physical and db.option.create:
+            if db.option.virtualize_physical and (db.option.create or
+                                                  db.option.vm_xml):
                 disk = physical_disks()
                 pass
             else:
@@ -317,7 +323,7 @@ class VirtualMachine:
                 if not db.option.virtualize_physical:
                     b = i.qemu_bridge[0] or 'main'
                     pass
-                elif db.option.create:
+                elif db.option.create or db.option.vm_xml:
                     bridge_len = len(db.option.physical_interface_bridge)
                     if index < bridge_len:
                         b = db.option.physical_interface_bridge[index]
@@ -336,7 +342,7 @@ class VirtualMachine:
         if not self.db.option.virtualize_physical:
             l = self.qemu._parent._interface_
             pass
-        elif self.db.option.create:
+        elif self.db.option.create or self.db.option.vm_xml:
             l = self.qemu._interface_
             pass
         else:
@@ -511,29 +517,29 @@ class Disk:
 
     def check_mounted_image(self, db):
         if not os.path.exists(self.mount_at):
-            raise Exception('%s does not exists' % self.mount_at)
+            raise MountException('%s does not exists' % self.mount_at)
         if not is_mounted(self.mount_at):
-            raise Exception('%s is not mounted' % self.mount_at)
+            raise MountException('%s is not mounted' % self.mount_at)
         if not os.path.exists(self.link_target):
-            raise Exception('%s does not exist' % self.link_target)
+            raise MountException('%s does not exist' % self.link_target)
         if not is_mounted(self.link_target):
-            raise Exception('%s is not mounted' % self.link_target)
+            raise MountException('%s is not mounted' % self.link_target)
         current = qemu_img_info(self.link_target)
         if current.size < self.size:
-            raise Exception('%s invalid size, fix on %s' % 
+            raise MountException('%s invalid size, fix on %s' %
                             (self.mount_at, self.host))
         if current.format != self.format:
-            raise Exception('%s invalid format, fix on %s' % 
+            raise MountException('%s invalid format, fix on %s' %
                             (self.mount_at, self.host))
 
     def check_local_image(self, db):
         result = True
         if not os.path.exists(self.image_path):
             cmd = [ str(a) for a in [ 'qemu-img', 'create',
-                                      '-f', self.format, 
+                                      '-f', self.format,
                                       self.image_path, self.size ] ]
             if db.option.create:
-                print("Running '%s'" % ' '.join(cmd), file=sys.stderr) 
+                print("Running '%s'" % ' '.join(cmd), file=sys.stderr)
                 run(*cmd)
                 pass
             else:
@@ -541,7 +547,7 @@ class Disk:
             pass
         current = qemu_img_info(self.image_path)
         if current.size < self.size:
-            print('qemu-img resize %s %s' % (self.image_path, 
+            print('qemu-img resize %s %s' % (self.image_path,
                                              self.size), file=sys.stderr)
             result = False
         if current.format != self.format:
@@ -549,7 +555,7 @@ class Disk:
             print('qemu-img convert -O %s %s' % (self.format, self.image_path),
                   file=sys.stderr)
             result = False
-        return result       
+        return result
 
     def check(self, db):
         #self.vm.check(options)
@@ -563,8 +569,8 @@ class Disk:
 
     def __repr__(self):
         return os.path.normpath('%s:/%s/%s (%s, %s)' % (
-            self.host, self.root, 
-            self.file, self.format, 
+            self.host, self.root,
+            self.file, self.format,
             self.size))
     pass
 
@@ -652,15 +658,20 @@ def get_vms(db):
     return get_from_netgroup(db, lambda h: not h._qemu_)
 
 def get_physical(db):
-    filter_hosts = lambda h: h._qemu_ or h.name[0] in db.option.check_hypervisor
+    filter_hosts = lambda h: h._qemu_ or (db.option.check_hypervisor and
+                                          h.name[0] in db.option.check_hypervisor)
     return get_from_netgroup(db, filter_hosts)
 
 def get_from_netgroup(db, filter_host):
     result = set()
+    done = set()
     ngs = netgroups(db.tree, filter_host=filter_host)
     for g in ngs:
         if (not db.option.check_netgroup or ngs[g].name in db.option.check_netgroup):
             for m in ngs[g].hosts():
+                if m in done:
+                    continue
+                done.add(m)
                 groups = [gr for gr in ngs if m in ngs[g].hosts()]
                 result.add(VirtualMachine(db, m, groups))
                 pass
@@ -682,7 +693,7 @@ def get_dev_with_prefix(prefix):
         addr[dev] += l
         pass
     for dev,s in addr.items():
-        match = [ IPNetwork(n) for n,a in 
+        match = [ IPNetwork(n) for n,a in
                   re.findall('\\s(([0-9a-f.:]+)/[0-9]+)\\s', s) if
                   IPAddress(a) in net ]
         if match:
diff --git a/src/vm.py b/src/vm.py
index 496621585fbc45d4aeea0906c7ea472a495c19b5..65c01aa12d9165d50e6ba3051e4fc7fd4342855b 100644
--- a/src/vm.py
+++ b/src/vm.py
@@ -1,5 +1,4 @@
 import util
-import subprocess
 import parser
 import libvirt
 import sys
@@ -120,7 +119,7 @@ class Hypervisor:
         def get_storage_pool(name):
             return self.libvirt.storagePoolLookupByName(name)
             pass
-        def get_storage_pool_list(): 
+        def get_storage_pool_list():
             return dict([ (p.name(), p)
                           for p in self.libvirt.listAllStoragePools() ])
         self.storage = util.FutureCache(get_storage_pool_list)
@@ -148,12 +147,14 @@ class Hypervisor:
         if not attr.startswith('__'):
             return getattr(self.libvirt, attr)
         raise AttributeError()
-                
-    
+
+
 def get_hypervisors(db):
     hosts = set()
     if db.option.virtualize_physical:
         if not db.option.check_hypervisor:
+            if db.option.vm_xml:
+                return hosts
             raise util.NeedOptionException("--check-hypervisor")
         for h in db.option.check_hypervisor:
             hosts.add(h)
@@ -261,7 +262,7 @@ def check_interfaces(virtual_machine, hypervisor):
         present.add((i._mac_[0].address[0], i._source_[0].bridge[0]))
         pass
     return wanted == present
- 
+
 def check_RNG(host, hypervisor, attach):
     def has_rng(tree):
         for rng in tree._devices_._rng_:
@@ -441,11 +442,10 @@ def print_xml(db):
         print('\n'.join([
             'Wrong hypervisor host (%s not in %s),' % (db.option.host,
                                                        e.allowed),
-            'XML might not reflect reality']), file=sys.stderr) 
+            'XML might not reflect reality']), file=sys.stderr)
         pass
     for c in command:
         print(' '.join(map(str, c)), file=sys.stderr)
         pass
     print(domain_xml(vm))
     pass
-