Blob Blame History Raw
diff -rupN cobbler-2.0.7-old/koan/app.py cobbler-2.0.7-new/koan/app.py
--- cobbler-2.0.7-old/koan/app.py	2013-11-21 14:02:54.303559201 -0500
+++ cobbler-2.0.7-new/koan/app.py	2013-11-22 17:54:23.691918000 -0500
@@ -28,6 +28,7 @@ import random
 import os
 import traceback
 import tempfile
+import shlex
 
 ANCIENT_PYTHON = 0
 try:
@@ -536,10 +537,13 @@ class Koan:
                 if not os.path.exists("/usr/bin/qemu-img"):
                     raise InfoException("qemu package needs to be installed")
                 # is libvirt new enough?
-                cmd = sub_process.Popen("rpm -q python-virtinst", stdout=sub_process.PIPE, shell=True)
-                version_str = cmd.communicate()[0]
-                if version_str.find("virtinst-0.1") != -1 or version_str.find("virtinst-0.0") != -1:
-                    raise InfoException("need python-virtinst >= 0.2 to do installs for qemu/kvm")
+                # Note: in some newer distros (like Fedora 19) the python-virtinst package has been
+                # subsumed into virt-install. If we don't have one check to see if we have the other.
+                rc, version_str = utils.subprocess_get_response(shlex.split('rpm -q virt-install'), True)
+                if rc != 0:
+                    rc, version_str = utils.subprocess_get_response(shlex.split('rpm -q python-virtinst'), True)
+                    if rc != 0 or version_str.find("virtinst-0.1") != -1 or version_str.find("virtinst-0.0") != -1:
+                        raise InfoException("need python-virtinst >= 0.2 or virt-install package to do installs for qemu/kvm (depending on your OS)")
 
             # for vmware
             if self.virt_type == "vmware" or self.virt_type == "vmwarew":
@@ -1106,7 +1110,10 @@ class Koan:
         Invoke virt guest-install (or tweaked copy thereof)
         """
         pd = profile_data
-        self.load_virt_modules()
+        # importing can't throw exceptions any more, don't put it in a sub-method
+        import xencreate
+        import qcreate
+        import imagecreate
 
         arch                          = self.safe_load(pd,'arch','x86')
         kextra                        = self.calc_kernel_args(pd)
@@ -1180,17 +1187,6 @@ class Koan:
 
     #---------------------------------------------------
 
-    def load_virt_modules(self):
-        try:
-            import xencreate
-            import qcreate
-            import imagecreate
-        except:
-            traceback.print_exc()
-            raise InfoException("no virtualization support available, install python-virtinst?")
-
-    #---------------------------------------------------
-
     def virt_choose(self, pd):
         fullvirt = False
         can_poll = None
@@ -1438,6 +1434,10 @@ class Koan:
                 return "%s/%s-disk%s" % (location, name, offset)
             elif not os.path.exists(location) and os.path.isdir(os.path.dirname(location)):
                 return location
+            elif not os.path.exists(os.path.dirname(location)):
+                print "- creating: %s" % os.path.dirname(location)
+                os.makedirs(os.path.dirname(location))
+                return location
             else:
                 raise InfoException, "invalid location: %s" % location                
         elif location.startswith("/dev/"):
diff -rupN cobbler-2.0.7-old/koan/imagecreate.py cobbler-2.0.7-new/koan/imagecreate.py
--- cobbler-2.0.7-old/koan/imagecreate.py	2013-11-21 14:02:54.303559201 -0500
+++ cobbler-2.0.7-new/koan/imagecreate.py	2013-11-21 14:08:24.214897902 -0500
@@ -1,7 +1,7 @@
 """
 Virtualization installation functions for image based deployment
 
-Copyright 2008 Red Hat, Inc.
+Copyright 2008 Red Hat, Inc and Others.
 Bryan Kearney <bkearney@redhat.com>
 
 Original version based on virt-image
@@ -23,169 +23,9 @@ Foundation, Inc., 51 Franklin Street, Fi
 02110-1301  USA
 """
 
-import os, sys, time, stat
-import shutil
-import random
-import exceptions
-import errno
-import virtinst
-try:
-   from virtinst import ImageParser, Guest, CapabilitiesParser, VirtualNetworkInterface
-except:
-   # if this fails, this is ok, the user just won't be able to use image objects...
-   # keeping this dynamic allows this to work on older EL.
-   pass
-import libvirt
-
-import app as koan
-
-#FIXME this was copied
-def random_mac():
-    """
-    from xend/server/netif.py
-    Generate a random MAC address.
-    Uses OUI 00-16-3E, allocated to
-    Xensource, Inc.  Last 3 fields are random.
-    return: MAC address string
-    """
-    mac = [ 0x00, 0x16, 0x3e,
-        random.randint(0x00, 0x7f),
-        random.randint(0x00, 0xff),
-        random.randint(0x00, 0xff) ]
-    return ':'.join(map(lambda x: "%02x" % x, mac))
-
-
-def transform_arch(arch):
-    if arch == "i386":
-        return "i686"
-    else:
-        return arch
-        
-def copy_image(original_file, new_location):
-    shutil.copyfile(original_file, new_location)
-    return new_location
-    
-    
-def process_disk(image, boot, file, location, target):
-    image_location = copy_image(file, location)
-    # Create the disk
-    disk = ImageParser.Disk()
-    disk.format = "raw"
-    disk.file = image_location
-    disk.use = "user"
-    disk.id = image_location
-    image.storage[disk.id] = disk
-    
-    #Create the drive
-    drive = ImageParser.Drive()
-    drive.id = image_location
-    drive.target = target 
-    drive.disk = disk
-    boot.disks.append(drive)
-    #dev api
-    #boot.drives.append(drive)  
-    
-    
-def process_networks(domain, guest, profile_data, bridge):
-    # Create a bridge or default network for every requested nic. If there are more
-    # bridges then nics discard the last one.
-    domain.interface = int(profile_data["network_count"])
-    bridges = []
-    #use the provided bridge first
-    guest_bridge = bridge
-    if guest_bridge is None:
-        guest_bridge = profile_data["virt_bridge"]
-        
-    # Look for commas
-    if (guest_bridge is not None) and (len(guest_bridge.strip()) > 0):
-        if guest_bridge.find(",") == -1:
-            bridges.append(guest_bridge)
-        else:
-            bridges == guest_bridge.split(",")
-    
-    for cnt in range(0,domain.interface):
-        if cnt < len(bridges):
-            nic = VirtualNetworkInterface(random_mac(), type="bridge", bridge = bridges[cnt])
-            #dev api
-            #nic = VirtualNetworkInterface(random_mac(), type="bridge", bridge = bridge, conn=guest.conn)                
-        else: 
-            default_network = virtinst.util.default_network()
-            #dev api
-            #default_network = virtinst.util.default_network(guest.conn)
-            nic = VirtualNetworkInterface(random_mac(), type=default_network[0], network=default_network[1])
-        guest.nics.append(nic)
-
-def start_install(name=None, 
-                  ram=None, 
-                  disks=None,
-                  uuid=None,  
-                  extra=None, 
-                  vcpus=None,  
-                  profile_data=None, 
-                  arch=None, 
-                  no_gfx=False, 
-                  fullvirt=False, 
-                  bridge=None, 
-                  virt_type=None,
-                  virt_auto_boot=None):                 
-                           
-    #FIXME how to do a non-default connection
-    #Can we drive off of virt-type?
-    connection = None
-    
-    if (virt_type is None ) or (virt_type == "auto"):
-        connection = virtinst.util.default_connection()
-    elif virt_type.lower()[0:3] == "xen":
-        connection = "xen"
-    else:
-        connection = "qemu:///system"
-        
-    connection = libvirt.open(connection)
-    capabilities = virtinst.CapabilitiesParser.parse(connection.getCapabilities())   
-    image_arch = transform_arch(arch)       
-
-    image = ImageParser.Image() 
-    #dev api
-    #image = ImageParser.Image(filename="") #FIXME, ImageParser should take in None
-    image.name = name
-
-    domain = ImageParser.Domain()
-    domain.vcpu = vcpus
-    domain.memory = ram
-    image.domain = domain
-    
-    boot = ImageParser.Boot()
-    boot.type = "hvm" #FIXME HARDCODED
-    boot.loader = "hd" #FIXME HARDCODED
-    boot.arch = image_arch
-    domain.boots.append(boot)
-    
-    #FIXME Several issues. Single Disk, type is hardcoded
-    #And there is no way to provision with access to "file"
-    process_disk(image, boot, profile_data["file"], disks[0][0], "hda")
-    
-    #FIXME boot_index??
-    installer = virtinst.ImageInstaller(boot_index = 0, image=image, capabilities=capabilities)                               
-    guest = virtinst.FullVirtGuest(connection = connection, installer=installer, arch=image_arch)
-
-    extra = extra.replace("&","&amp;")
-
-    guest.extraargs = extra
-    guest.set_name(name)
-    guest.set_memory(ram)
-    guest.set_vcpus(vcpus)
-
-    if not no_gfx:
-        guest.set_graphics("vnc")
-    else:
-        guest.set_graphics(False)
-
-    if uuid is not None:
-        guest.set_uuid(uuid)
-                   
-    process_networks(domain, guest, profile_data, bridge)                   
-    
-    guest.start_install()
-    
-    return "use virt-manager or reconnect with virsh console %s" % name 
-     
+import utils
+import virtinstall
+
+def start_install(*args, **kwargs):
+    cmd = virtinstall.build_commandline("import", *args, **kwargs)
+    utils.subprocess_call(cmd)
diff -rupN cobbler-2.0.7-old/koan/qcreate.py cobbler-2.0.7-new/koan/qcreate.py
--- cobbler-2.0.7-old/koan/qcreate.py	2013-11-21 14:02:54.304559209 -0500
+++ cobbler-2.0.7-new/koan/qcreate.py	2013-12-05 18:49:06.355883703 -0500
@@ -1,8 +1,8 @@
 """
-Virtualization installation functions.  
+Virtualization installation functions.
 
-Copyright 2007-2008 Red Hat, Inc.
-Michael DeHaan <mdehaan@redhat.com>
+Copyright 2007-2008 Red Hat, Inc and Others.
+Michael DeHaan <michael.dehaan AT gmail>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -20,192 +20,32 @@ Foundation, Inc., 51 Franklin Street, Fi
 02110-1301  USA
 
 module for creating fullvirt guests via KVM/kqemu/qemu
-requires python-virtinst-0.200.
+requires python-virtinst-0.200 (or virt-install in later distros).
 """
 
-import os, sys, time, stat
-import tempfile
-import random
-from optparse import OptionParser
-import exceptions
-import errno
-import re
-import tempfile
-import shutil
-import virtinst
-import app as koan
-try:
-    import subprocess
-except:
-    import sub_process as subprocess
 import utils
+import virtinstall
+from xml.dom.minidom import parseString
 
-def random_mac():
-    """
-    from xend/server/netif.py
-    Generate a random MAC address.
-    Uses OUI 00-16-3E, allocated to
-    Xensource, Inc.  Last 3 fields are random.
-    return: MAC address string
-    """
-    mac = [ 0x00, 0x16, 0x3e,
-        random.randint(0x00, 0x7f),
-        random.randint(0x00, 0xff),
-        random.randint(0x00, 0xff) ]
-    return ':'.join(map(lambda x: "%02x" % x, mac))
-
-
-def start_install(name=None, 
-                  ram=None, 
-                  disks=None, 
-                  mac=None,
-                  uuid=None,  
-                  extra=None,
-                  vcpus=None, 
-                  profile_data=None, 
-                  arch=None, 
-                  no_gfx=False, 
-                  fullvirt=True, 
-                  bridge=None, 
-                  virt_type=None,
-                  virt_auto_boot=False):
-
-    vtype = "qemu"
-    if virtinst.util.is_kvm_capable():
-       vtype = "kvm"
-       arch = None # let virtinst.FullVirtGuest() default to the host arch
-    elif virtinst.util.is_kqemu_capable():
-       vtype = "kqemu"
-    print "- using qemu hypervisor, type=%s" % vtype
-
-    if arch is not None and arch.lower() in ["x86","i386"]:
-        arch = "i686"
-
-    guest = virtinst.FullVirtGuest(hypervisorURI="qemu:///system",type=vtype, arch=arch)
-
-    if not profile_data.has_key("file"):
-        # images don't need to source this 
-        if not profile_data.has_key("install_tree"):
-            raise koan.InfoException("Cannot find install source in kickstart file, aborting.")
-   
- 
-        if not profile_data["install_tree"].endswith("/"):
-            profile_data["install_tree"] = profile_data["install_tree"] + "/"
-
-        # virt manager doesn't like nfs:// and just wants nfs:
-        # (which cobbler should fix anyway)
-        profile_data["install_tree"] = profile_data["install_tree"].replace("nfs://","nfs:")
-
-    if profile_data.has_key("file"):
-        # this is an image based installation
-        input_path = profile_data["file"]
-        print "- using image location %s" % input_path
-        if input_path.find(":") == -1:
-            # this is not an NFS path
-            guest.cdrom = input_path
-        else:
-            (tempdir, filename) = utils.nfsmount(input_path)
-            guest.cdrom = os.path.join(tempdir, filename)     
-
-        kickstart = profile_data.get("kickstart","")
-        if kickstart != "":
-            # we have a (windows?) answer file we have to provide
-            # to the ISO.
-            print "I want to make a floppy for %s" % kickstart
-            floppy_path = utils.make_floppy(kickstart)
-            guest.disks.append(virtinst.VirtualDisk(device=virtinst.VirtualDisk.DEVICE_FLOPPY, path=floppy_path))
-        
-
-    else:
-        guest.location = profile_data["install_tree"]
-   
-    extra = extra.replace("&","&amp;") 
-    guest.extraargs = extra
-
-    if profile_data.has_key("breed"):
-        breed = profile_data["breed"]
-        if breed != "other" and breed != "":
-            if breed in [ "debian", "suse", "redhat" ]:
-                guest.set_os_type("linux")
-            elif breed in [ "windows" ]:
-                guest.set_os_type("windows")
-            else:
-                guest.set_os_type("unix")
-            if profile_data.has_key("os_version"):
-                # FIXME: when os_version is not defined and it's linux, do we use generic24/generic26 ?
-                version = profile_data["os_version"]
-                if version != "other" and version != "":
-                    try:
-                        guest.set_os_variant(version)
-                    except:
-                        print "- virtinst library does not understand variant %s, treating as generic" % version
-                        pass
-
-    guest.set_name(name)
-    guest.set_memory(ram)
-    guest.set_vcpus(vcpus)
-    # for KVM, we actually can't disable this, since it's the only
-    # console it has other than SDL
-    guest.set_graphics("vnc")
-
-    if uuid is not None:
-        guest.set_uuid(uuid)
-
-    for d in disks:
-        print "- adding disk: %s of size %s" % (d[0], d[1])
-        if d[1] != 0 or d[0].startswith("/dev"):
-            guest.disks.append(virtinst.VirtualDisk(d[0], size=d[1]))
-        else:
-            raise koan.InfoException("this virtualization type does not work without a disk image, set virt-size in Cobbler to non-zero")
-
-    if profile_data.has_key("interfaces"):
-
-        counter = 0
-        interfaces = profile_data["interfaces"].keys()
-        interfaces.sort()
-        vlanpattern = re.compile("[a-zA-Z0-9]+\.[0-9]+")
-        for iname in interfaces:
-            intf = profile_data["interfaces"][iname]
-
-            if intf["bonding"] == "master" or vlanpattern.match(iname) or iname.find(":") != -1:
-                continue
-
-            mac = intf["mac_address"]
-            if mac == "":
-                mac = random_mac()
-
-            if bridge is None:
-                profile_bridge = profile_data["virt_bridge"]
-
-                intf_bridge = intf["virt_bridge"]
-                if intf_bridge == "":
-                    if profile_bridge == "":
-                        raise koan.InfoException("virt-bridge setting is not defined in cobbler")
-                    intf_bridge = profile_bridge
-            else:
-                if bridge.find(",") == -1:
-                    intf_bridge = bridge
-                else:
-                    bridges = bridge.split(",")  
-                    intf_bridge = bridges[counter]
-            nic_obj = virtinst.VirtualNetworkInterface(macaddr=mac, bridge=intf_bridge)
-            guest.nics.append(nic_obj)
-            counter = counter + 1
-
-    else:
-
-            if bridge is not None:
-                profile_bridge = bridge
-            else:
-                profile_bridge = profile_data["virt_bridge"]
-
-            if profile_bridge == "":
-                raise koan.InfoException("virt-bridge setting is not defined in cobbler")
-
-            nic_obj = virtinst.VirtualNetworkInterface(macaddr=random_mac(), bridge=profile_bridge)
-            guest.nics.append(nic_obj)
-
-    guest.start_install()
-
-    return "use virt-manager and connect to qemu to manage guest: %s" % name
-
+def start_install(*args, **kwargs):
+    # See http://post-office.corp.redhat.com/archives/satellite-dept-list/2013-December/msg00039.html for discussion on this hack.
+    if 'arch' in kwargs.keys():
+        kwargs['arch'] = None # use host arch for kvm acceleration
+
+    # Use kvm acceleration if available
+    try:
+        import libvirt
+    except:
+        raise koan.InfoException("package libvirt is required for installing virtual guests")
+    conn = libvirt.openReadOnly(None)
+    # See http://libvirt.org/formatcaps.html
+    capabilities = parseString(conn.getCapabilities())
+    for domain in capabilities.getElementsByTagName("domain"):
+        attributes = dict(domain.attributes.items())
+        if 'type' in attributes.keys() and attributes['type'] == 'kvm':
+            kwargs['virt_type'] = 'kvm'
+            break
+
+    virtinstall.create_image_file(*args, **kwargs)
+    cmd = virtinstall.build_commandline("qemu:///system", *args, **kwargs)
+    utils.subprocess_call(cmd)
diff -rupN cobbler-2.0.7-old/koan/utils.py cobbler-2.0.7-new/koan/utils.py
--- cobbler-2.0.7-old/koan/utils.py	2013-11-21 14:02:54.303559201 -0500
+++ cobbler-2.0.7-new/koan/utils.py	2013-12-03 16:14:43.732007939 -0500
@@ -178,6 +178,27 @@ def subprocess_call(cmd,ignore_rc=0):
         raise InfoException, "command failed (%s)" % rc
     return rc
 
+def subprocess_get_response(cmd, ignore_rc=False):
+    """
+    Wrapper around subprocess.check_output(...)
+    """
+    print "- %s" % cmd
+    rc = 0
+    result = ""
+    if not ANCIENT_PYTHON:
+        try:
+            result = sub_process.check_output(cmd).strip()
+        except sub_process.CalledProcessError, e:
+            rc = e.returncode
+            result = e.output
+    else:
+        cmd = string.join(cmd, " ")
+        print "cmdstr=(%s)" % cmd
+        rc = os.system(cmd)
+    if not ignore_rc and rc != 0:
+        raise InfoException, "command failed (%s)" % rc
+    return rc, result
+
 def input_string_or_hash(options,delim=None,allow_multiples=True):
     """
     Older cobbler files stored configurations in a flat way, such that all values for strings.
@@ -267,7 +288,7 @@ def nfsmount(input_path):
         shutil.rmtree(tempdir, ignore_errors=True)
         raise koan.InfoException("nfs mount failed: %s" % dirpath)
     # NOTE: option for a blocking install might be nice, so we could do this
-    # automatically, if supported by python-virtinst
+    # automatically, if supported by virt-install
     print "after install completes, you may unmount and delete %s" % tempdir
     return (tempdir, filename)
 
@@ -516,7 +537,7 @@ def make_floppy(kickstart):
     if not rc == 0:
         raise InfoException("umount failed")
 
-    # return the path to the completed disk image to pass to virtinst
+    # return the path to the completed disk image to pass to virt-install
     return floppy_path
 
 
diff -rupN cobbler-2.0.7-old/koan/virtinstall.py cobbler-2.0.7-new/koan/virtinstall.py
--- cobbler-2.0.7-old/koan/virtinstall.py	1969-12-31 19:00:00.000000000 -0500
+++ cobbler-2.0.7-new/koan/virtinstall.py	2013-12-05 17:06:04.469953236 -0500
@@ -0,0 +1,413 @@
+"""
+Virtualization installation functions.
+Currently somewhat Xen/paravirt specific, will evolve later.
+
+Copyright 2006-2008 Red Hat, Inc.
+Michael DeHaan <mdehaan@redhat.com>
+
+Original version based on virtguest-install
+Jeremy Katz <katzj@redhat.com>
+Option handling added by Andrew Puch <apuch@redhat.com>
+Simplified for use as library by koan, Michael DeHaan <mdehaan@redhat.com>
+
+This program 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 of the License, or
+(at your option) any later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301  USA
+"""
+
+import os
+import re
+import shlex
+
+import app as koan
+import utils
+
+# The virtinst module will no longer be availabe to import in some
+# distros. We need to get all the info we need from the virt-install
+# command line tool. This should work on both old and new variants,
+# as the virt-install command line tool has always been provided by
+# python-virtinst (and now the new virt-install rpm).
+rc, response = utils.subprocess_get_response(
+        shlex.split('virt-install --version'), True)
+if rc == 0:
+    virtinst_version = response
+else:
+    virtinst_version = None
+
+# This one's trickier. We need a list of supported os varients, but
+# the man page explicitly says not to parse the result of this command.
+# But we need it, and there's no other way to get it. I spoke with the
+# virt-install maintainers and they said the point of that message
+# is that you can't absolutely depend on the output not changing, but
+# at the moment it's the only option for us. Long term plans are for
+# virt-install to switch to libosinfo for OS metadata tracking, which
+# provides a library and tools for querying valid OS values. Until
+# that's available and pervasive the best we can do is to use the
+# module if it's availabe and if not parse the command output.
+supported_variants = set()
+try:
+    from virtinst import osdict
+    for ostype in osdict.OS_TYPES.keys():
+        for variant in osdict.OS_TYPES[ostype]["variants"].keys():
+            supported_variants.add(variant)
+except:
+    try:
+        rc, response = utils.subprocess_get_response(
+                shlex.split('virt-install --os-variant list'))
+        variants = response.split('\n')
+        for variant in variants:
+            supported_variants.add(variant.split()[0])
+    except:
+        pass # No problem, we'll just use generic
+
+def _sanitize_disks(disks):
+    ret = []
+    for d in disks:
+        driver_type = None
+        if len(d) > 2:
+            driver_type = d[2]
+
+        if d[1] != 0 or d[0].startswith("/dev"):
+            ret.append((d[0], d[1], driver_type))
+        else:
+            raise koan.InfoException("this virtualization type does not work without a disk image, set virt-size in Cobbler to non-zero")
+
+    return ret
+
+def _sanitize_nics(nics, bridge, profile_bridge, network_count):
+    ret = []
+
+    if network_count is not None and not nics:
+        # Fill in some stub nics so we can take advantage of the loop logic
+        nics = {}
+        for i in range(int(network_count)):
+            nics["foo%s" % i] = {
+                "interface_type" : "na",
+                "mac_address": None,
+                "virt_bridge": None,
+            }
+
+    if not nics:
+        return ret
+
+    interfaces = nics.keys()
+    interfaces.sort()
+    counter = -1
+    vlanpattern = re.compile("[a-zA-Z0-9]+\.[0-9]+")
+
+    for iname in interfaces:
+        counter = counter + 1
+        intf = nics[iname]
+
+        if (intf["bonding"] == "master" or vlanpattern.match(iname) or iname.find(":") != -1):
+            continue
+
+        mac = intf["mac_address"]
+
+        if not bridge:
+            intf_bridge = intf["virt_bridge"]
+            if intf_bridge == "":
+                if profile_bridge == "":
+                    raise koan.InfoException("virt-bridge setting is not defined in cobbler")
+                intf_bridge = profile_bridge
+
+        else:
+            if bridge.find(",") == -1:
+                intf_bridge = bridge
+            else:
+                bridges = bridge.split(",")
+                intf_bridge = bridges[counter]
+
+        ret.append((intf_bridge, mac))
+
+    return ret
+
+def create_image_file(disks=None, **kwargs):
+    disks = _sanitize_disks(disks)
+    for path, size, driver_type in disks:
+        if driver_type is None:
+            continue
+        if os.path.isdir(path) or os.path.exists(path):
+            continue
+        if str(size) == "0":
+            continue
+        utils.create_qemu_image_file(path, size, driver_type)
+
+def build_commandline(uri,
+                      name=None,
+                      ram=None,
+                      disks=None,
+                      uuid=None,
+                      extra=None,
+                      vcpus=None,
+                      profile_data=None,
+                      arch=None,
+                      no_gfx=False,
+                      fullvirt=False,
+                      bridge=None,
+                      virt_type=None,
+                      virt_auto_boot=False,
+                      virt_pxe_boot=False,
+                      qemu_driver_type=None,
+                      qemu_net_type=None,
+                      qemu_machine_type=None,
+                      wait=0,
+                      noreboot=False,
+                      osimport=False):
+
+    # Set flags for CLI arguments based on the virtinst_version
+    # tuple above. Older versions of python-virtinst don't have
+    # a version easily accessible, so it will be None and we can
+    # easily disable features based on that (RHEL5 and older usually)
+
+    disable_autostart = False
+    disable_virt_type = False
+    disable_boot_opt = False
+    disable_driver_type = False
+    disable_net_model = False
+    disable_machine_type = False
+    oldstyle_macs = False
+    oldstyle_accelerate = False
+
+    if not virtinst_version:
+        print ("- warning: old virt-install detected, a lot of features will be disabled")
+        disable_autostart = True
+        disable_boot_opt = True
+        disable_virt_type = True
+        disable_driver_type = True
+        disable_net_model = True
+        disable_machine_type = True
+        oldstyle_macs = True
+        oldstyle_accelerate = True
+
+    import_exists = False # avoid duplicating --import parameter
+    disable_extra = False # disable --extra-args on --import
+    if osimport:
+        disable_extra = True
+
+    is_import = uri.startswith("import")
+    if is_import:
+        # We use the special value 'import' for imagecreate.py. Since
+        # it is connection agnostic, just let virt-install choose the
+        # best hypervisor.
+        uri = ""
+        fullvirt = None
+
+    is_xen = uri.startswith("xen")
+    is_qemu = uri.startswith("qemu")
+    if is_qemu:
+        if virt_type != "kvm":
+            fullvirt = True
+        else:
+            fullvirt = None
+
+    floppy = None
+    cdrom = None
+    location = None
+    importpath = None
+
+    if is_import:
+        importpath = profile_data.get("file")
+        if not importpath:
+            raise koan.InfoException("Profile 'file' required for image "
+                                     "install")
+
+    elif profile_data.has_key("file"):
+        if is_xen:
+            raise koan.InfoException("Xen does not work with --image yet")
+
+        # this is an image based installation
+        input_path = profile_data["file"]
+        print "- using image location %s" % input_path
+        if input_path.find(":") == -1:
+            # this is not an NFS path
+            cdrom = input_path
+        else:
+            (tempdir, filename) = utils.nfsmount(input_path)
+            cdrom = os.path.join(tempdir, filename)
+
+        kickstart = profile_data.get("kickstart","")
+        if kickstart != "":
+            # we have a (windows?) answer file we have to provide
+            # to the ISO.
+            print "I want to make a floppy for %s" % kickstart
+            floppy = utils.make_floppy(kickstart)
+    elif is_qemu or is_xen:
+        # images don't need to source this
+        if not profile_data.has_key("install_tree"):
+            raise koan.InfoException("Cannot find install source in kickstart file, aborting.")
+
+        if not profile_data["install_tree"].endswith("/"):
+            profile_data["install_tree"] = profile_data["install_tree"] + "/"
+
+        location = profile_data["install_tree"]
+
+
+    disks = _sanitize_disks(disks)
+    nics = _sanitize_nics(profile_data.get("interfaces"),
+                          bridge,
+                          profile_data.get("virt_bridge"),
+                          profile_data.get("network_count"))
+    if not nics:
+        # for --profile you get one NIC, go define a system if you want more.
+        # FIXME: can mac still be sent on command line in this case?
+
+        if bridge is None:
+            bridge = profile_data["virt_bridge"]
+
+        if bridge == "":
+            raise koan.InfoException("virt-bridge setting is not defined in cobbler")
+        nics = [(bridge, None)]
+
+
+    kernel = profile_data.get("kernel_local")
+    initrd = profile_data.get("initrd_local")
+    breed = profile_data.get("breed")
+    os_version = profile_data.get("os_version")
+    if os_version and breed == "ubuntu":
+        os_version = "ubuntu%s" % os_version
+    if os_version and breed == "debian":
+        os_version = "debian%s" % os_version
+
+    net_model = None
+    disk_bus = None
+    machine_type = None
+
+    if is_qemu:
+        net_model = qemu_net_type
+        disk_bus = qemu_driver_type
+        machine_type = qemu_machine_type
+
+    if machine_type is None:
+        machine_type = "pc"
+
+    cmd = "virt-install "
+    if uri:
+        cmd += "--connect %s " % uri
+
+    cmd += "--name %s " % name
+    cmd += "--ram %s " % ram
+    cmd += "--vcpus %s " % vcpus
+
+    if uuid:
+        cmd += "--uuid %s " % uuid
+
+    if virt_auto_boot and not disable_autostart:
+        cmd += "--autostart "
+
+    if no_gfx:
+        cmd += "--nographics "
+    else:
+        cmd += "--vnc "
+
+    if is_qemu and virt_type:
+        if not disable_virt_type:
+            cmd += "--virt-type %s " % virt_type
+
+    if is_qemu and machine_type and not disable_machine_type:
+        cmd += "--machine %s " % machine_type
+
+    if fullvirt or is_qemu or is_import:
+        if fullvirt is not None:
+            cmd += "--hvm "
+        elif oldstyle_accelerate:
+            cmd += "--accelerate "
+
+        if is_qemu and extra and not(virt_pxe_boot) and not(disable_extra):
+            cmd += ("--extra-args=\"%s\" " % (extra))
+
+        if virt_pxe_boot or is_xen:
+            cmd += "--pxe "
+        elif cdrom:
+            cmd += "--cdrom %s " % cdrom
+        elif location:
+            cmd += "--location %s " % location
+        elif importpath:
+            cmd += "--import "
+            import_exists = True
+
+        if arch:
+            cmd += "--arch %s " % arch
+    else:
+        cmd += "--paravirt "
+        if not disable_boot_opt:
+            cmd += ("--boot kernel=%s,initrd=%s,kernel_args=\"%s\" " %
+                    (kernel, initrd, extra))
+        else:
+            if location:
+                cmd += "--location %s " % location
+            if extra:
+                cmd += "--extra-args=\"%s\" " % extra
+
+    if breed and breed != "other":
+        if os_version and os_version != "other":
+            if breed == "suse":
+                suse_version_re = re.compile("^(opensuse[0-9]+)\.([0-9]+)$")
+                if suse_version_re.match(os_version):
+                    os_version = suse_version_re.match(os_version).groups()[0]
+            # make sure virt-install knows about our os_version,
+            # otherwise default it to generic26
+            found = False
+            if os_version in supported_variants:
+                cmd += "--os-variant %s " % os_version
+            else:
+                print ("- warning: virt-install doesn't know this os_version, defaulting to generic26")
+                cmd += "--os-variant generic26 "
+        else:
+            distro = "unix"
+            if breed in [ "debian", "suse", "redhat" ]:
+                distro = "linux"
+            elif breed in [ "windows" ]:
+                distro = "windows"
+
+            cmd += "--os-type %s " % distro
+
+    if importpath:
+        # This needs to be the first disk for import to work
+        cmd += "--disk path=%s " % importpath
+
+    for path, size, driver_type in disks:
+        print ("- adding disk: %s of size %s (driver type=%s)" %
+               (path, size, driver_type))
+        cmd += "--disk path=%s" % (path)
+        if str(size) != "0":
+            cmd += ",size=%s" % size
+        if disk_bus:
+            cmd += ",bus=%s" % disk_bus
+        if driver_type and not disable_driver_type:
+            cmd += ",format=%s" % driver_type
+        cmd += " "
+
+    if floppy:
+        cmd += "--disk path=%s,device=floppy " % floppy
+
+    for bridge, mac in nics:
+        cmd += "--network bridge=%s" % bridge
+        if net_model and not disable_net_model:
+            cmd += ",model=%s" % net_model
+        if mac:
+            if oldstyle_macs:
+                cmd += " --mac=%s" % mac
+            else:
+                cmd += ",mac=%s" % mac
+        cmd += " "
+
+    cmd += "--wait %d " % int(wait)
+    if noreboot:
+        cmd += "--noreboot "
+    if osimport and not(import_exists):
+        cmd += "--import "
+    cmd += "--noautoconsole "
+
+    return shlex.split(cmd.strip())
diff -rupN cobbler-2.0.7-old/koan/xencreate.py cobbler-2.0.7-new/koan/xencreate.py
--- cobbler-2.0.7-old/koan/xencreate.py	2013-11-21 14:02:54.304559209 -0500
+++ cobbler-2.0.7-new/koan/xencreate.py	2013-11-21 14:05:56.006847361 -0500
@@ -1,14 +1,14 @@
 """
-Virtualization installation functions.  
+Virtualization installation functions.
 Currently somewhat Xen/paravirt specific, will evolve later.
 
-Copyright 2006-2008 Red Hat, Inc.
-Michael DeHaan <mdehaan@redhat.com>
+Copyright 2006-2008 Red Hat, Inc and Others.
+Michael DeHaan <michael.dehaan AT gmail>
 
 Original version based on virtguest-install
 Jeremy Katz <katzj@redhat.com>
 Option handling added by Andrew Puch <apuch@redhat.com>
-Simplified for use as library by koan, Michael DeHaan <mdehaan@redhat.com>
+Simplified for use as library by koan, Michael DeHaan <michael.dehaan AT gmail>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -26,180 +26,9 @@ Foundation, Inc., 51 Franklin Street, Fi
 02110-1301  USA
 """
 
-import os, sys, time, stat
-import tempfile
-import random
-import exceptions
-import errno
-import re
-import virtinst
-import app as koan
-
-try:
-    from virtinst.DistroManager import PXEInstaller
-    pxe_installer = PXEInstaller()
-except ImportError:
-    try:
-        from virtinst import PXEInstaller
-        pxe_installer = PXEInstaller(os_type='hvm')
-    except:
-        # older virtinst, this is probably ok
-        # but we know we can't do Xen fullvirt installs
-        pass
-import traceback
-
-def random_mac():
-    """
-    from xend/server/netif.py
-    Generate a random MAC address.
-    Uses OUI 00-16-3E, allocated to
-    Xensource, Inc.  Last 3 fields are random.
-    return: MAC address string
-    """
-    mac = [ 0x00, 0x16, 0x3e,
-        random.randint(0x00, 0x7f),
-        random.randint(0x00, 0xff),
-        random.randint(0x00, 0xff) ]
-    return ':'.join(map(lambda x: "%02x" % x, mac))
-
-
-def start_install(name=None, 
-                  ram=None, 
-                  disks=None,
-                  uuid=None,  
-                  extra=None, 
-                  vcpus=None,  
-                  profile_data=None, 
-                  arch=None, 
-                  no_gfx=False, 
-                  fullvirt=False, 
-                  bridge=None, 
-                  virt_type=None,
-                  virt_auto_boot=False):
-
-    if profile_data.has_key("file"):
-        raise koan.InfoException("Xen does not work with --image yet")
-
-    if fullvirt:
-        # FIXME: add error handling here to explain when it's not supported
-        guest = virtinst.FullVirtGuest(installer=pxe_installer)
-    else:
-        guest = virtinst.ParaVirtGuest()
-
-    extra = extra.replace("&","&amp;")
-
-    if not fullvirt:
-        guest.set_boot((profile_data["kernel_local"], profile_data["initrd_local"]))
-        # fullvirt OS's will get this from the PXE config (managed by Cobbler)
-        guest.extraargs = extra
-    else:
-        print "- fullvirt mode"
-        if profile_data.has_key("breed"):
-            breed = profile_data["breed"]
-            if breed != "other" and breed != "":
-                if breed in [ "debian", "suse", "redhat" ]:
-                    guest.set_os_type("linux")
-                elif breed in [ "windows" ]:
-                    guest.set_os_type("windows")
-                else:
-                    guest.set_os_type("unix")
-                if profile_data.has_key("os_version"):
-                    # FIXME: when os_version is not defined and it's linux, do we use generic24/generic26 ?
-                    version = profile_data["os_version"]
-                    if version != "other" and version != "":
-                        try:
-                            guest.set_os_variant(version)
-                        except:
-                            print "- virtinst library does not understand variant %s, treating as generic" % version
-                            pass
-
-
-    guest.set_name(name)
-    guest.set_memory(ram)
-    guest.set_vcpus(vcpus)
-
-    if not no_gfx:
-        guest.set_graphics("vnc")
-    else:
-        guest.set_graphics(False)
-
-    if uuid is not None:
-        guest.set_uuid(uuid)
-
-    for d in disks:
-        if d[1] != 0 or d[0].startswith("/dev"):
-            virtdisk = virtinst.XenDisk(d[0], size=d[1])
-
-            # Set driver_name to tap for Xen PV guests
-            if guest.installer and guest.installer.os_type in ('xen', 'linux'):
-                if virtdisk.type == virtinst.XenDisk.TYPE_FILE and \
-                   virtinst._util.is_blktap_capable():
-                    virtdisk.driver_name = virtinst.XenDisk.DRIVER_TAP
-
-            guest.disks.append(virtdisk)
-        else:
-            raise koan.InfoException("this virtualization type does not work without a disk image, set virt-size in Cobbler to non-zero")
-
-    counter = 0
-
-    if profile_data.has_key("interfaces"):
-
-        interfaces = profile_data["interfaces"].keys()
-        interfaces.sort()
-        counter = -1
-        vlanpattern = re.compile("[a-zA-Z0-9]+\.[0-9]+")
-
-        for iname in interfaces:
-            counter = counter + 1
-            intf = profile_data["interfaces"][iname]
-
-            if intf["bonding"] == "master" or vlanpattern.match(iname) or iname.find(":") != -1: 
-                continue
-
-            mac = intf["mac_address"]
-            if mac == "":
-                mac = random_mac()
-
-            if not bridge:
-                profile_bridge = profile_data["virt_bridge"]
-
-                intf_bridge = intf["virt_bridge"]
-                if intf_bridge == "":
-                    if profile_bridge == "":
-                        raise koan.InfoException("virt-bridge setting is not defined in cobbler")
-                    intf_bridge = profile_bridge
-
-            else:
-                if bridge.find(",") == -1:
-                    intf_bridge = bridge
-                else:
-                    bridges = bridge.split(",")
-                    intf_bridge = bridges[counter]
-
-
-            nic_obj = virtinst.XenNetworkInterface(macaddr=mac, bridge=intf_bridge)
-            guest.nics.append(nic_obj)
-            counter = counter + 1
-   
-    else:
-            # for --profile you just get one NIC, go define a system if you want more.
-            # FIXME: can mac still be sent on command line in this case?
-
-            if bridge is None:
-                profile_bridge = profile_data["virt_bridge"]
-            else:
-                profile_bridge = bridge
-
-            if profile_bridge == "":
-                raise koan.InfoException("virt-bridge setting is not defined in cobbler")
-
-            nic_obj = virtinst.XenNetworkInterface(macaddr=random_mac(), bridge=profile_bridge)
-            guest.nics.append(nic_obj)
-            
-        
-
-
-    guest.start_install()
-    
-    return "use virt-manager or reconnect with virsh console %s" % name 
-     
+import utils
+import virtinstall
+
+def start_install(*args, **kwargs):
+    cmd = virtinstall.build_commandline("xen:///", *args, **kwargs)
+    utils.subprocess_call(cmd)