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 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("&","&") - - 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 +Copyright 2007-2008 Red Hat, Inc and Others. +Michael DeHaan 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("&","&") - 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 + +Original version based on virtguest-install +Jeremy Katz +Option handling added by Andrew Puch +Simplified for use as library by koan, Michael DeHaan + +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 +Copyright 2006-2008 Red Hat, Inc and Others. +Michael DeHaan Original version based on virtguest-install Jeremy Katz Option handling added by Andrew Puch -Simplified for use as library by koan, Michael DeHaan +Simplified for use as library by koan, Michael DeHaan 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("&","&") - - 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)