From 012d1cdc52d1443edfe1944c7e9c7dbec3bb0f00 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Wed, 17 Jul 2013 07:53:47 -0400 Subject: [PATCH] Installer: Drop all XML handling, just have it setup install info --- tests/image.py | 13 ++- tests/utils.py | 34 +++---- tests/xmlconfig.py | 55 ++++------ tests/xmlparse.py | 10 +- virt-image | 11 +- virt-install | 46 ++++----- virtManager/create.py | 41 ++++---- virtManager/domain.py | 40 ++++---- virtinst/CapabilitiesParser.py | 11 ++ virtinst/DistroInstaller.py | 49 ++++----- virtinst/Guest.py | 133 +++++++----------------- virtinst/ImageInstaller.py | 27 ++--- virtinst/Installer.py | 178 +++++++-------------------------- virtinst/OSDistro.py | 15 ++- virtinst/__init__.py | 1 + virtinst/cli.py | 11 +- virtinst/support.py | 6 ++ virtinst/util.py | 30 ++++++ 18 files changed, 272 insertions(+), 439 deletions(-) diff --git a/tests/image.py b/tests/image.py index f0dd8b321..27f5afe5c 100644 --- a/tests/image.py +++ b/tests/image.py @@ -79,14 +79,19 @@ class TestImageParser(unittest.TestCase): for idx in range(len(output_xmls)): fname = output_xmls[idx] inst = virtinst.ImageInstaller(conn, image, boot_index=idx) - - utils.set_conn(conn) - - if inst.is_hvm(): + capsguest, capsdomain = inst.get_caps_guest() + if capsguest.os_type == "hvm": g = utils.get_basic_fullyvirt_guest(typ=gtype) else: g = utils.get_basic_paravirt_guest() + g.os.os_type = capsguest.os_type + g.type = capsdomain.hypervisor_type + g.os.arch = capsguest.arch + + utils.set_conn(conn) + + g.installer = inst g._prepare_install(None) diff --git a/tests/utils.py b/tests/utils.py index 82dcf07cd..c2746ae69 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -35,7 +35,6 @@ os.environ["HOME"] = "/tmp" os.environ["DISPLAY"] = ":3.4" _cwd = os.getcwd() -scratch = os.path.join(_cwd, "tests", "testscratchdir") _testuri = "test:///%s/tests/testdriver.xml" % _cwd _fakeuri = "__virtinst_test__" + _testuri + ",predictable" _remoteuri = "__virtinst_test__" + _testuri + ",remote" @@ -44,6 +43,8 @@ _plainkvm = "%s,qemu" % _fakeuri _plainxen = "%s,xen" % _fakeuri _kvmuri = "%s,caps=%s" % (_plainkvm, _kvmcaps) +os.environ["VIRTINST_TEST_SCRATCHDIR"] = _cwd + def get_debug(): return ("DEBUG_TESTS" in os.environ and @@ -187,7 +188,6 @@ def get_basic_paravirt_guest(installer=None): g.installer._install_kernel = "/boot/vmlinuz" g.installer._install_initrd = "/boot/initrd" - g.installer._scratchdir = scratch g.add_default_input_device() g.add_default_console_device() @@ -201,7 +201,8 @@ def get_basic_fullyvirt_guest(typ="xen", installer=None): g.memory = int(200 * 1024) g.maxmemory = int(400 * 1024) g.uuid = "12345678-1234-1234-1234-123456789012" - g.cdrom = "/dev/loop0" + g.installer.location = "/dev/loop0" + g.installer.cdrom = True gdev = VirtualGraphics(_conn) gdev.type = "sdl" g.add_device(gdev) @@ -210,44 +211,33 @@ def get_basic_fullyvirt_guest(typ="xen", installer=None): if installer: g.installer = installer g.emulator = "/usr/lib/xen/bin/qemu-dm" - g.installer.arch = "i686" - g.installer.os_type = "hvm" + g.os.arch = "i686" + g.os.os_type = "hvm" - g.installer._scratchdir = scratch g.add_default_input_device() g.add_default_console_device() return g -def make_import_installer(os_type="hvm"): - inst = virtinst.ImportInstaller(_conn) - inst.type = "xen" - inst.os_type = os_type - return inst +def make_import_installer(): + return virtinst.ImportInstaller(_conn) -def make_distro_installer(location="/default-pool/default-vol", gtype="xen"): +def make_distro_installer(location="/default-pool/default-vol"): inst = virtinst.DistroInstaller(_conn) - inst.type = gtype - inst.os_type = "hvm" inst.location = location return inst -def make_live_installer(location="/dev/loop0", gtype="xen"): +def make_live_installer(location="/dev/loop0"): inst = virtinst.LiveCDInstaller(_conn) - inst.type = gtype - inst.os_type = "hvm" inst.location = location return inst -def make_pxe_installer(gtype="xen"): - inst = virtinst.PXEInstaller(_conn) - inst.type = gtype - inst.os_type = "hvm" - return inst +def make_pxe_installer(): + return virtinst.PXEInstaller(_conn) def build_win_kvm(path=None, fake=True): diff --git a/tests/xmlconfig.py b/tests/xmlconfig.py index f760c9629..db97d339b 100644 --- a/tests/xmlconfig.py +++ b/tests/xmlconfig.py @@ -63,10 +63,6 @@ class TestXMLConfig(unittest.TestCase): utils.reset_conn() logging.debug("Running %s", self.id()) - def tearDown(self): - if os.path.exists(utils.scratch): - os.rmdir(utils.scratch) - def _compare(self, guest, filebase, do_install, do_disk_boot=False, do_create=True): filename = filebase and build_xmlfile(filebase) or None @@ -278,9 +274,9 @@ class TestXMLConfig(unittest.TestCase): g = utils.get_basic_fullyvirt_guest(installer=i) g.add_device(utils.get_filedisk()) - g.installer.bootconfig.bootorder = [ - g.installer.bootconfig.BOOT_DEVICE_NETWORK] - g.installer.bootconfig.enable_bootmenu = True + g.os.bootorder = [ + g.os.BOOT_DEVICE_NETWORK] + g.os.enable_bootmenu = True self._compare(g, "boot-fullyvirt-pxe-always", False) @@ -314,7 +310,7 @@ class TestXMLConfig(unittest.TestCase): """ utils.set_conn(_plainkvm) - i = utils.make_distro_installer(gtype="kvm") + i = utils.make_distro_installer() g = utils.get_basic_fullyvirt_guest("kvm", installer=i) do_install = False @@ -351,9 +347,9 @@ class TestXMLConfig(unittest.TestCase): g = utils.get_basic_fullyvirt_guest(installer=i) g.add_device(utils.get_filedisk()) - g.installer.bootconfig.kernel = "kernel" - g.installer.bootconfig.initrd = "initrd" - g.installer.bootconfig.kernel_args = "my kernel args" + g.os.kernel = "kernel" + g.os.initrd = "initrd" + g.os.kernel_args = "my kernel args" self._compare(g, "install-fullyvirt-import-kernel", False) @@ -361,13 +357,13 @@ class TestXMLConfig(unittest.TestCase): i = utils.make_import_installer() g = utils.get_basic_fullyvirt_guest(installer=i) - g.installer.bootconfig.enable_bootmenu = False - g.installer.bootconfig.bootorder = ["hd", "fd", "cdrom", "network"] + g.os.enable_bootmenu = False + g.os.bootorder = ["hd", "fd", "cdrom", "network"] g.add_device(utils.get_filedisk()) self._compare(g, "install-fullyvirt-import-multiboot", False) def testInstallPVImport(self): - i = utils.make_import_installer("xen") + i = utils.make_import_installer() g = utils.get_basic_paravirt_guest(installer=i) g.add_device(utils.get_filedisk()) @@ -402,7 +398,7 @@ class TestXMLConfig(unittest.TestCase): # OS Type/Version configurations def testF10(self): utils.set_conn(_plainkvm) - i = utils.make_pxe_installer(gtype="kvm") + i = utils.make_pxe_installer() g = utils.get_basic_fullyvirt_guest("kvm", installer=i) g.os_type = "linux" @@ -414,8 +410,9 @@ class TestXMLConfig(unittest.TestCase): def testF11(self): utils.set_conn(_plainkvm) - i = utils.make_distro_installer(gtype="kvm") + i = utils.make_distro_installer() g = utils.get_basic_fullyvirt_guest("kvm", installer=i) + g.os.os_type = "hvm" g.os_type = "linux" g.os_variant = "fedora11" @@ -428,7 +425,7 @@ class TestXMLConfig(unittest.TestCase): def testF11AC97(self): def build_guest(): - i = utils.make_distro_installer(gtype="kvm") + i = utils.make_distro_installer() g = utils.get_basic_fullyvirt_guest("kvm", installer=i) g.os_type = "linux" @@ -467,7 +464,7 @@ class TestXMLConfig(unittest.TestCase): def testF11Qemu(self): utils.set_conn(_plainkvm) - i = utils.make_distro_installer(gtype="qemu") + i = utils.make_distro_installer() g = utils.get_basic_fullyvirt_guest("qemu", installer=i) g.os_type = "linux" @@ -481,7 +478,7 @@ class TestXMLConfig(unittest.TestCase): def testF11Xen(self): utils.set_conn(_plainxen) - i = utils.make_distro_installer(gtype="xen") + i = utils.make_distro_installer() g = utils.get_basic_fullyvirt_guest("xen", installer=i) g.os_type = "linux" @@ -929,8 +926,7 @@ class TestXMLConfig(unittest.TestCase): def testFullKVMRHEL6(self): utils.set_conn(_plainkvm) i = utils.make_distro_installer( - location="tests/cli-test-xml/fakerhel6tree", - gtype="kvm") + location="tests/cli-test-xml/fakerhel6tree") g = utils.get_basic_fullyvirt_guest("kvm", installer=i) g.add_device(utils.get_floppy()) g.add_device(utils.get_filedisk("/default-pool/rhel6.img", fake=False)) @@ -940,15 +936,7 @@ class TestXMLConfig(unittest.TestCase): g.add_device(VirtualVideoDevice(g.conn)) g.os_autodetect = True - # Do this ugly hack to make sure the test doesn't try and use vol - # upload - origscratch = getattr(i, "_get_system_scratchdir") - try: - setattr(i, "_get_system_scratchdir", - lambda: i.scratchdir) - self._testInstall(g, "rhel6-kvm-stage1", "rhel6-kvm-stage2") - finally: - setattr(i, "_get_system_scratchdir", origscratch) + self._testInstall(g, "rhel6-kvm-stage1", "rhel6-kvm-stage2") def testFullKVMWinxp(self): utils.set_conn(_plainkvm) @@ -1046,9 +1034,10 @@ class TestXMLConfig(unittest.TestCase): def testFedoraTreeinfo(self): i = utils.make_distro_installer( - location="tests/cli-test-xml/fakefedoratree", - gtype="kvm") - t, v = i.detect_distro() + location="tests/cli-test-xml/fakefedoratree") + g = utils.get_basic_fullyvirt_guest(installer=i) + g.type = "kvm" + t, v = i.detect_distro(g) self.assertEquals((t, v), ("linux", "fedora17")) if __name__ == "__main__": diff --git a/tests/xmlparse.py b/tests/xmlparse.py index 04b4c9bf8..c9a34758f 100644 --- a/tests/xmlparse.py +++ b/tests/xmlparse.py @@ -124,15 +124,13 @@ class XMLParseTest(unittest.TestCase): check("imagelabel", "imagelabel", "fooimage") check("relabel", None, True) - check = self._make_checker(guest.installer) + check = self._make_checker(guest.os) check("type", "kvm", "test") check("os_type", "hvm", "xen") check("arch", "i686", None) check("machine", "foobar", "pc-0.11") check("loader", None, "/foo/loader") check("init", None, "/sbin/init") - - check = self._make_checker(guest.installer.bootconfig) check("bootorder", ["hd"], ["fd"]) check("enable_bootmenu", None, False) check("kernel", None) @@ -203,14 +201,14 @@ class XMLParseTest(unittest.TestCase): guest.cpu.set_topology_defaults(guest.vcpus) self.assertTrue(guest.cpu.get_xml_config().startswith(", let's us fake hotplug @@ -1000,15 +1000,15 @@ class vmmDomain(vmmLibvirtObject): return self._get_guest().cpu def get_boot_device(self): - return self._get_guest().installer.bootconfig.bootorder + return self._get_guest().os.bootorder def get_boot_menu(self): guest = self._get_guest() - return bool(guest.installer.bootconfig.enable_bootmenu) + return bool(guest.os.enable_bootmenu) def get_boot_kernel_info(self): guest = self._get_guest() - kernel = guest.installer.bootconfig.kernel - initrd = guest.installer.bootconfig.initrd - args = guest.installer.bootconfig.kernel_args + kernel = guest.os.kernel + initrd = guest.os.initrd + args = guest.os.kernel_args return (kernel, initrd, args) diff --git a/virtinst/CapabilitiesParser.py b/virtinst/CapabilitiesParser.py index 724ddcfe2..2886ff93a 100644 --- a/virtinst/CapabilitiesParser.py +++ b/virtinst/CapabilitiesParser.py @@ -752,3 +752,14 @@ class Capabilities(object): 'arch': guest.arch, 'machine': machinestr}) return (guest, domain) + + def build_virtinst_guest(self, conn, guest, domain): + import virtinst + gobj = virtinst.Guest(conn) + gobj.type = domain.hypervisor_type + gobj.os.os_type = guest.os_type + gobj.os.arch = guest.arch + gobj.os.loader = domain.loader + gobj.emulator = domain.emulator + + return gobj diff --git a/virtinst/DistroInstaller.py b/virtinst/DistroInstaller.py index cb9d2b0ef..fcbffda3b 100644 --- a/virtinst/DistroInstaller.py +++ b/virtinst/DistroInstaller.py @@ -25,6 +25,7 @@ import tempfile import urlgrabber +from virtinst import support from virtinst import Storage from virtinst import util from virtinst import Installer @@ -198,11 +199,6 @@ def _perform_initrd_injections(initrd, injections, scratchdir): logging.debug("gzip stderr=%s", gziperr) -def _support_remote_url_install(conn): - if hasattr(conn, "_virtinst__fake_conn"): - return False - return conn.check_stream_support(conn.SUPPORT_STREAM_UPLOAD) - def _upload_media(conn, scratchdir, system_scratchdir, meter, kernel, initrd): @@ -218,7 +214,7 @@ def _upload_media(conn, scratchdir, system_scratchdir, " nothing to upload") return kernel, initrd, tmpvols - if not _support_remote_url_install(conn): + if not support.support_remote_url_install(conn): logging.debug("Media upload not supported") return kernel, initrd, tmpvols @@ -250,15 +246,14 @@ class DistroInstaller(Installer.Installer): # Install prepartions # ####################### - def _prepare_cdrom(self, guest, meter): + def _prepare_cdrom(self, guest, meter, scratchdir): transient = not self.livecd if not self._location_is_path: - # Xen needs a boot.iso if its a http://, ftp://, or nfs: url (store_ignore, os_type_ignore, os_variant_ignore, media) = OSDistro.getBootDisk(guest, self.location, meter, - self.scratchdir) + scratchdir) cdrom = media self._tmpfiles.append(cdrom) @@ -270,7 +265,7 @@ class DistroInstaller(Installer.Installer): disk.transient = transient self.install_devices.append(disk) - def _prepare_kernel_and_initrd(self, guest, meter): + def _prepare_kernel_and_initrd(self, guest, meter, scratchdir): disk = None # If installing off a local path, map it through to a virtual CD @@ -281,16 +276,14 @@ class DistroInstaller(Installer.Installer): disk = self._make_cdrom_dev(self.location) disk.transient = True - # Make sure we always fetch kernel here if required + # Don't fetch kernel if test suite manually injected a boot kernel if self._install_kernel and not self.scratchdir_required(): return disk - # Need to fetch the kernel & initrd from a remote site, or - # out of a loopback mounted disk image/device ignore, os_type, os_variant, media = OSDistro.getKernel(guest, self.location, meter, - self.scratchdir, - self.os_type) + scratchdir, + guest.os.os_type) (kernelfn, initrdfn, args) = media if guest.get_os_autodetect(): @@ -308,10 +301,11 @@ class DistroInstaller(Installer.Installer): _perform_initrd_injections(initrdfn, self.initrd_injections, - self.scratchdir) + scratchdir) kernelfn, initrdfn, tmpvols = _upload_media( - guest.conn, self.scratchdir, self._get_system_scratchdir(), + guest.conn, scratchdir, + util.get_system_scratchdir(guest.type), meter, kernelfn, initrdfn) self._tmpvols += tmpvols @@ -332,9 +326,9 @@ class DistroInstaller(Installer.Installer): self.livecd) if isinstall or persistent_cd: - bootdev = self.bootconfig.BOOT_DEVICE_CDROM + bootdev = "cdrom" else: - bootdev = self.bootconfig.BOOT_DEVICE_HARDDISK + bootdev = "hd" return bootdev def _validate_location(self, val): @@ -378,33 +372,34 @@ class DistroInstaller(Installer.Installer): return bool(is_url or mount_dvd) - def _prepare(self, guest, meter): + def _prepare(self, guest, meter, scratchdir): + logging.debug("Using scratchdir=%s", scratchdir) + dev = None if self.cdrom: if self.location: - dev = self._prepare_cdrom(guest, meter) + dev = self._prepare_cdrom(guest, meter, scratchdir) else: # Booting from a cdrom directly allocated to the guest pass else: - dev = self._prepare_kernel_and_initrd(guest, meter) + dev = self._prepare_kernel_and_initrd(guest, meter, scratchdir) if dev: self.install_devices.append(dev) - def check_location(self): + def check_location(self, arch): if self._location_is_path: # We already mostly validated this return True # This will throw an error for us - OSDistro.detectMediaDistro(location=self.location, arch=self.arch) + OSDistro.detectMediaDistro(self.location, arch) return True - def detect_distro(self): + def detect_distro(self, arch): try: - dist_info = OSDistro.detectMediaDistro(location=self.location, - arch=self.arch) + dist_info = OSDistro.detectMediaDistro(self.location, arch) except: logging.exception("Error attempting to detect distro.") return (None, None) diff --git a/virtinst/Guest.py b/virtinst/Guest.py index f6b0fdf9e..3d7ec3dc3 100644 --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -28,9 +28,10 @@ import urlgrabber.progress as progress import libvirt import libxml2 +import virtinst from virtinst import util from virtinst import support -import virtinst +from virtinst.osxml import OSXML from virtinst.xmlbuilder import XMLBuilder, XMLProperty from virtinst.VirtualDevice import VirtualDevice from virtinst.VirtualDisk import VirtualDisk @@ -206,34 +207,18 @@ class Guest(XMLBuilder): self._type = "xen" # Need to do this after all parameter init - self._features = DomainFeatures(self.conn) - self._clock = Clock(self.conn) - self._seclabel = Seclabel(self.conn) - self._cpu = CPU(self.conn) - self._numatune = DomainNumatune(self.conn) + self.os = OSXML(self.conn, parsexml, parsexmlnode) + self.features = DomainFeatures(self.conn) + self.clock = Clock(self.conn) + self.seclabel = Seclabel(self.conn) + self.cpu = CPU(self.conn) + self.numatune = DomainNumatune(self.conn) ###################### # Property accessors # ###################### - def get_clock(self): - return self._clock - clock = property(get_clock) - def get_seclabel(self): - return self._seclabel - seclabel = property(get_seclabel) - def get_cpu(self): - return self._cpu - cpu = property(get_cpu) - def get_numatune(self): - return self._numatune - numatune = property(get_numatune) - - def _get_features(self): - return self._features - features = property(_get_features) - # Domain name of the guest def get_name(self): return self._name @@ -432,52 +417,12 @@ class Guest(XMLBuilder): doc=_("Whether we should overwrite an existing guest " "with the same name.")) - ######################### - # DEPRECATED PROPERTIES # - ######################### - - # Hypervisor name (qemu, xen, kvm, etc.) - # Deprecated: should be pulled directly from the installer def get_type(self): - return self.installer.type + return self.os.type def set_type(self, val): - self.installer.type = val + self.os.type = val type = property(get_type, set_type) - # Deprecated: should be pulled directly from the installer - def get_arch(self): - return self.installer.arch - def set_arch(self, val): - self.installer.arch = val - arch = property(get_arch, set_arch) - - # Deprecated: Should be called from the installer directly - def get_location(self): - return self.installer.location - def set_location(self, val): - self.installer.location = val - location = property(get_location, set_location) - - # Deprecated: Should be called from the installer directly - def get_scratchdir(self): - return self.installer.scratchdir - scratchdir = property(get_scratchdir) - - # Deprecated: Should be called from the installer directly - def get_extraargs(self): - return self.installer.extraargs - def set_extraargs(self, val): - self.installer.extraargs = val - extraargs = property(get_extraargs, set_extraargs) - - # Deprecated: Should set the installer values directly - def get_cdrom(self): - return self.installer.location - def set_cdrom(self, val): - self.installer.location = val - self.installer.cdrom = True - cdrom = property(get_cdrom, set_cdrom) - ######################################## # Device Add/Remove Public API methods # @@ -612,23 +557,22 @@ class Guest(XMLBuilder): self._track_device(dev) self._xml_node.virtinst_root_doc = self._xml_root_doc - self.installer = virtinst.Installer.Installer(self.conn, - parsexmlnode=self._xml_node) - self._features = DomainFeatures(self.conn, - parsexmlnode=self._xml_node) - self._clock = Clock(self.conn, parsexmlnode=self._xml_node) - self._seclabel = Seclabel(self.conn, parsexmlnode=self._xml_node) - self._cpu = CPU(self.conn, parsexmlnode=self._xml_node) - self._numatune = DomainNumatune(self.conn, - parsexmlnode=self._xml_node) + self.os = OSXML(self.conn, parsexmlnode=self._xml_node) + self.features = DomainFeatures(self.conn, + parsexmlnode=self._xml_node) + self.clock = Clock(self.conn, parsexmlnode=self._xml_node) + self.seclabel = Seclabel(self.conn, parsexmlnode=self._xml_node) + self.cpu = CPU(self.conn, parsexmlnode=self._xml_node) + self.numatune = DomainNumatune(self.conn, + parsexmlnode=self._xml_node) def add_default_input_device(self): - if self.installer.is_container(): + if self.os.is_container(): return self.add_device(VirtualInputDevice(self.conn)) def add_default_console_device(self): - if self.installer.is_xenpv(): + if self.os.is_xenpv(): return dev = virtinst.VirtualConsoleDevice(self.conn) dev.type = dev.TYPE_PTY @@ -685,11 +629,11 @@ class Guest(XMLBuilder): def _get_emulator_xml(self): emulator = self.emulator - if self.installer.is_xenpv(): + if self.os.is_xenpv(): return "" if (not self.emulator and - self.installer.is_hvm() and + self.os.is_hvm() and self.type == "xen"): if self.conn.caps.host.arch in ("x86_64"): emulator = "/usr/lib64/xen/bin/qemu-dm" @@ -706,7 +650,7 @@ class Guest(XMLBuilder): """ Return features (pae, acpi, apic) xml """ - if self.installer and self.installer.is_container(): + if self.os.is_container(): return "" return features.get_xml_config() @@ -737,15 +681,12 @@ class Guest(XMLBuilder): """ Return os, features, and clock xml (Implemented in subclass) """ - xml = "" - - osxml = self.installer.get_xml_config(self, install) + oscopy = self.os.copy() + self.installer.alter_bootconfig(self, install, oscopy) + osxml = oscopy._get_osblob_helper(self, install, oscopy, self.os) if not osxml: return None - - xml = util.xml_append(xml, - self.installer.get_xml_config(self, install)) - return xml + return osxml def _get_vcpu_xml(self): curvcpus_supported = self.conn.check_conn_support( @@ -774,8 +715,8 @@ class Guest(XMLBuilder): ignore = dry # Fetch install media, prepare installer devices - self.installer.prepare(guest=self, - meter=meter) + self.installer.prepare(self, meter, + util.make_scratchdir(self.conn, self.type)) # Initialize install device list for dev in self.installer.install_devices: @@ -1212,9 +1153,9 @@ class Guest(XMLBuilder): if features["pae"] is None: features["pae"] = self.conn.caps.support_pae() - if (self.installer.machine is None and + if (self.os.machine is None and self.conn.caps.host.arch == "ppc64"): - self.installer.machine = "pseries" + self.os.machine = "pseries" def _set_pv_defaults(self, devlist_func): # Default file backed PV guests to tap driver @@ -1258,9 +1199,9 @@ class Guest(XMLBuilder): for dev in devlist_func("all"): dev.set_defaults() - if self.installer.is_hvm(): + if self.os.is_hvm(): self._set_hvm_defaults(devlist_func, features) - if self.installer.is_xenpv(): + if self.os.is_xenpv(): self._set_pv_defaults(devlist_func) soundtype = VirtualDevice.VIRTUAL_DEV_AUDIO @@ -1285,13 +1226,13 @@ class Guest(XMLBuilder): if disk.device == disk.DEVICE_FLOPPY: disk.bus = "fdc" else: - if self.installer.is_hvm(): - if (self.installer.type == "kvm" and - self.installer.machine == "pseries"): + if self.os.is_hvm(): + if (self.os.type == "kvm" and + self.os.machine == "pseries"): disk.bus = "scsi" else: disk.bus = "ide" - elif self.installer.is_xenpv(): + elif self.os.is_xenpv(): disk.bus = "xen" if disk.target: used_targets.append(disk.target) diff --git a/virtinst/ImageInstaller.py b/virtinst/ImageInstaller.py index eab8313c6..40847e426 100644 --- a/virtinst/ImageInstaller.py +++ b/virtinst/ImageInstaller.py @@ -35,7 +35,6 @@ class ImageInstaller(Installer.Installer): def __init__(self, conn, image, boot_index=None): Installer.Installer.__init__(self, conn) - self._arch = None self._image = image # Set boot _boot_caps/_boot_parameters @@ -53,23 +52,17 @@ class ImageInstaller(Installer.Installer): # Set up internal caps.guest object self._guest = self.conn.caps.guestForOSType(self.boot_caps.type, - self.boot_caps.arch) + self.boot_caps.arch) if self._guest is None: raise RuntimeError(_("Unsupported virtualization type: %s %s" % (self.boot_caps.type, self.boot_caps.arch))) - - self.os_type = self.boot_caps.type self._domain = self._guest.bestDomainType() - self.type = self._domain.hypervisor_type - self.arch = self._guest.arch + # Custom ImageInstaller methods - - def is_hvm(self): - if self._boot_caps.type == "hvm": - return True - return False + def get_caps_guest(self): + return self._guest, self._domain def get_image(self): return self._image @@ -81,9 +74,9 @@ class ImageInstaller(Installer.Installer): # General Installer methods - - def prepare(self, guest, meter): - self.cleanup() + def _prepare(self, guest, meter, scratchdir): + ignore = scratchdir + ignore = meter self._make_disks() @@ -93,9 +86,9 @@ class ImageInstaller(Installer.Installer): elif self.boot_caps.features[f] & CapabilitiesParser.FEATURE_OFF: guest.features[f] = False - self.bootconfig.kernel = self.boot_caps.kernel - self.bootconfig.initrd = self.boot_caps.initrd - self.bootconfig.kernel_args = self.boot_caps.cmdline + guest.os.kernel = self.boot_caps.kernel + guest.os.initrd = self.boot_caps.initrd + guest.os.kernel_args = self.boot_caps.cmdline # Private methods def _get_bootdev(self, isinstall, guest): diff --git a/virtinst/Installer.py b/virtinst/Installer.py index 3a3b369de..39562e649 100644 --- a/virtinst/Installer.py +++ b/virtinst/Installer.py @@ -20,20 +20,13 @@ # MA 02110-1301 USA. import os -import platform import logging -import copy import virtinst -from virtinst import osxml -from virtinst import util -from virtinst.xmlbuilder import XMLBuilder, XMLProperty - -XEN_SCRATCH = "/var/lib/xen" -LIBVIRT_SCRATCH = "/var/lib/libvirt/boot" +from virtinst import OSXML -class Installer(XMLBuilder): +class Installer(object): """ Installer classes attempt to encapsulate all the parameters needed to 'install' a guest: essentially, booting the guest with the correct @@ -58,18 +51,14 @@ class Installer(XMLBuilder): - Hypervisor name (parameter 'type') ('qemu', 'kvm', 'xen', etc.) - Guest architecture ('i686', 'x86_64') """ - _dumpxml_xpath = "/domain/os" _has_install_phase = True - def __init__(self, conn, parsexml=None, parsexmlnode=None): - XMLBuilder.__init__(self, conn, parsexml, parsexmlnode) - + def __init__(self, conn): + self.conn = conn self._location = None self._cdrom = False - self._scratchdir = None self.initrd_injections = [] - self.bootconfig = osxml.OSXML(self.conn, parsexml, parsexmlnode) self._install_kernel = None self._install_initrd = None @@ -82,43 +71,9 @@ class Installer(XMLBuilder): self._tmpvols = [] - ##################### - # XML related props # - ##################### - - def _set_type(self, val): - self.bootconfig.type = val - type = property(lambda s: s.bootconfig.type, _set_type) - def _set_os_type(self, val): - self.bootconfig.os_type = val - os_type = property(lambda s: s.bootconfig.os_type, _set_os_type) - def _set_machine(self, val): - self.bootconfig.machine = val - machine = property(lambda s: s.bootconfig.machine, _set_machine) - def _set_arch(self, val): - self.bootconfig.arch = val - arch = property(lambda s: s.bootconfig.arch, _set_arch) - def _set_loader(self, val): - self.bootconfig.loader = val - loader = property(lambda s: s.bootconfig.loader, _set_loader) - def _set_init(self, val): - self.bootconfig.init = val - init = property(lambda s: s.bootconfig.init, _set_init) - - - ###################### - # Non-XML properties # - ###################### - - def get_scratchdir(self): - if not self.scratchdir_required(): - return None - - if not self._scratchdir: - self._scratchdir = self._get_scratchdir() - logging.debug("scratchdir=%s", self._scratchdir) - return self._scratchdir - scratchdir = property(get_scratchdir) + ######################### + # Properties properties # + ######################### def get_cdrom(self): return self._cdrom @@ -145,49 +100,18 @@ class Installer(XMLBuilder): # Private helpers # ################### - def _get_system_scratchdir(self): - if platform.system() == "SunOS": - return "/var/tmp" - - if self.type == "test": - return "/tmp" - elif self.type == "xen": - return XEN_SCRATCH - else: - return LIBVIRT_SCRATCH - - def _get_scratchdir(self): - scratch = None - if not self.conn.is_session_uri(): - scratch = self._get_system_scratchdir() - - if (not scratch or - not os.path.exists(scratch) or - not os.access(scratch, os.W_OK)): - scratch = os.path.expanduser("~/.virtinst/boot") - if not os.path.exists(scratch): - os.makedirs(scratch, 0751) - - return scratch - def _build_boot_order(self, isinstall, guest): - bootdev = self._get_bootdev(isinstall, guest) - if bootdev is None: - # None here means 'kernel boot' - return [] - - bootorder = [bootdev] + bootorder = [self._get_bootdev(isinstall, guest)] # If guest has an attached disk, always have 'hd' in the boot # list, so disks are marked as bootable/installable (needed for # windows virtio installs, and booting local disk from PXE) for disk in guest.get_devices("disk"): if disk.device == disk.DEVICE_DISK: - bootdev = self.bootconfig.BOOT_DEVICE_HARDDISK + bootdev = "hd" if bootdev not in bootorder: bootorder.append(bootdev) break - return bootorder def _make_cdrom_dev(self, path): @@ -198,7 +122,7 @@ class Installer(XMLBuilder): dev.validate() return dev - def _get_xml_config(self, guest, isinstall): + def alter_bootconfig(self, guest, isinstall, bootconfig): """ Generate the portion of the guest xml that determines boot devices and parameters. (typically the block) @@ -209,28 +133,23 @@ class Installer(XMLBuilder): 'post-install' phase. @type isinstall: C{bool} """ - # pylint: disable=W0221 - # Argument number differs from overridden method if isinstall and not self.has_install_phase(): return - bootconfig = self.bootconfig.copy() bootorder = self._build_boot_order(isinstall, guest) if not bootconfig.bootorder: bootconfig.bootorder = bootorder - if isinstall: - bootconfig = bootconfig.copy() - if self._install_kernel: - bootconfig.kernel = self._install_kernel - if self._install_initrd: - bootconfig.initrd = self._install_initrd - if self._install_args: - bootconfig.kernel_args = self._install_args + if not isinstall: + return - return self.bootconfig._get_osblob_helper(guest, isinstall, - bootconfig, self.bootconfig) + if self._install_kernel: + bootconfig.kernel = self._install_kernel + if self._install_initrd: + bootconfig.initrd = self._install_initrd + if self._install_args: + bootconfig.kernel_args = self._install_args ########################## @@ -243,9 +162,10 @@ class Installer(XMLBuilder): def _validate_location(self, val): return val - def _prepare(self, guest, meter): + def _prepare(self, guest, meter, scratchdir): ignore = guest ignore = meter + ignore = scratchdir ############## @@ -260,10 +180,6 @@ class Installer(XMLBuilder): """ return False - is_hvm = lambda s: s.bootconfig.is_hvm() - is_xenpv = lambda s: s.bootconfig.is_xenpv() - is_container = lambda s: s.bootconfig.is_container() - def has_install_phase(self): """ Return True if the requested setup is actually installing an OS @@ -288,18 +204,19 @@ class Installer(XMLBuilder): self._tmpfiles = [] self.install_devices = [] - def prepare(self, guest, meter): + def prepare(self, guest, meter, scratchdir): self.cleanup() - self._prepare(guest, meter) + self._prepare(guest, meter, scratchdir) - def check_location(self): + def check_location(self, arch): """ Validate self.location seems to work. This will might hit the network so we don't want to do it on demand. """ + ignore = arch return True - def detect_distro(self): + def detect_distro(self, arch): """ Attempt to detect the distro for the Installer's 'location'. If an error is encountered in the detection process (or if detection @@ -307,49 +224,27 @@ class Installer(XMLBuilder): @returns: (distro type, distro variant) tuple """ + ignore = arch return (None, None) - def guest_from_installer(self): - """ - Return a L{Guest} instance wrapping the current installer. - - If all the appropriate values are present in the installer - (conn, type, os_type, arch, machine), we have everything we need - to determine what L{Guest} class is expected and what default values - to pass it. This is a convenience method to save the API user from - having to enter all these known details twice. - """ - guest, domain = self.conn.caps.guest_lookup(os_type=self.os_type, - typ=self.type, - arch=self.arch, - machine=self.machine) - - gobj = virtinst.Guest(self.conn) - gobj.installer = self - gobj.arch = guest.arch - gobj.emulator = domain.emulator - self.loader = domain.loader - - return gobj - class ContainerInstaller(Installer): _has_install_phase = False def _get_bootdev(self, isinstall, guest): ignore = isinstall ignore = guest - return self.bootconfig.BOOT_DEVICE_HARDDISK + return OSXML.BOOT_DEVICE_HARDDISK class PXEInstaller(Installer): def _get_bootdev(self, isinstall, guest): - bootdev = self.bootconfig.BOOT_DEVICE_NETWORK + bootdev = OSXML.BOOT_DEVICE_NETWORK if (not isinstall and [d for d in guest.get_devices("disk") if d.device == d.DEVICE_DISK]): # If doing post-install boot and guest has an HD attached - bootdev = self.bootconfig.BOOT_DEVICE_HARDDISK + bootdev = OSXML.BOOT_DEVICE_HARDDISK return bootdev @@ -360,12 +255,13 @@ class LiveCDInstaller(Installer): def _validate_location(self, val): return self._make_cdrom_dev(val).path - def _prepare(self, guest, meter): + def _prepare(self, guest, meter, scratchdir): ignore = guest ignore = meter + ignore = scratchdir self.install_devices.append(self._make_cdrom_dev(self.location)) def _get_bootdev(self, isinstall, guest): - return self.bootconfig.BOOT_DEVICE_CDROM + return OSXML.BOOT_DEVICE_CDROM class ImportInstaller(Installer): @@ -375,15 +271,15 @@ class ImportInstaller(Installer): def _get_bootdev(self, isinstall, guest): disks = guest.get_devices("disk") if not disks: - return self.bootconfig.BOOT_DEVICE_HARDDISK + return OSXML.BOOT_DEVICE_HARDDISK return self._disk_to_bootdev(disks[0]) def _disk_to_bootdev(self, disk): if disk.device == virtinst.VirtualDisk.DEVICE_DISK: - return self.bootconfig.BOOT_DEVICE_HARDDISK + return OSXML.BOOT_DEVICE_HARDDISK elif disk.device == virtinst.VirtualDisk.DEVICE_CDROM: - return self.bootconfig.BOOT_DEVICE_CDROM + return OSXML.BOOT_DEVICE_CDROM elif disk.device == virtinst.VirtualDisk.DEVICE_FLOPPY: - return self.bootconfig.BOOT_DEVICE_FLOPPY + return OSXML.BOOT_DEVICE_FLOPPY else: - return self.bootconfig.BOOT_DEVICE_HARDDISK + return OSXML.BOOT_DEVICE_HARDDISK diff --git a/virtinst/OSDistro.py b/virtinst/OSDistro.py index da750f54e..f7fe7b908 100644 --- a/virtinst/OSDistro.py +++ b/virtinst/OSDistro.py @@ -119,7 +119,7 @@ def _locationCheckWrapper(guest, baseuri, progresscb, scratchdir, _type, arch, callback): fetcher = _fetcherForURI(baseuri, scratchdir) if guest: - arch = guest.arch + arch = guest.os.arch try: fetcher.prepareLocation() @@ -154,17 +154,15 @@ def _acquireMedia(iskernel, guest, baseuri, progresscb, return _locationCheckWrapper(guest, baseuri, progresscb, scratchdir, _type, None, media_cb) + # Helper method to lookup install media distro and fetch an install kernel - - def getKernel(guest, baseuri, progresscb, scratchdir, typ): iskernel = True return _acquireMedia(iskernel, guest, baseuri, progresscb, scratchdir, typ) + # Helper method to lookup install media distro and fetch a boot iso - - def getBootDisk(guest, baseuri, progresscb, scratchdir): iskernel = False return _acquireMedia(iskernel, guest, baseuri, progresscb, @@ -179,9 +177,8 @@ def _check_osvariant_valid(os_type, os_variant): return bool(_check_ostype_valid(os_type) and os_variant in osdict.sort_helper(osdict.OS_TYPES[os_type]["variants"])) + # Attempt to detect the os type + variant for the passed location - - def detectMediaDistro(location, arch): import urlgrabber progresscb = urlgrabber.progress.BaseMeter() @@ -393,8 +390,8 @@ class Distro: if not fetcher.location.startswith("/"): args += "%s=%s" % (self.method_arg, fetcher.location) - if guest.extraargs: - args += " " + guest.extraargs + if guest.installer.extraargs: + args += " " + guest.installer.extraargs try: initrd = fetcher.acquireFile(initrdpath, progresscb) diff --git a/virtinst/__init__.py b/virtinst/__init__.py index be45cc2f6..42c9b5b28 100644 --- a/virtinst/__init__.py +++ b/virtinst/__init__.py @@ -22,6 +22,7 @@ cliutils.setup_i18n() # Public imports from virtinst.Guest import Guest +from virtinst.osxml import OSXML from virtinst.VirtualNetworkInterface import VirtualNetworkInterface from virtinst.VirtualGraphics import VirtualGraphics from virtinst.VirtualAudio import VirtualAudio diff --git a/virtinst/cli.py b/virtinst/cli.py index 426593cfb..7e96085c2 100644 --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -792,7 +792,7 @@ def digest_graphics(guest, options, default_override=None): elif default_override is False: nographics = True else: - if guest.installer.is_container(): + if guest.os.is_container(): logging.debug("Container guest, defaulting to nographics") nographics = True elif "DISPLAY" in os.environ.keys(): @@ -1277,10 +1277,7 @@ def parse_boot(guest, optstring): if val is None: return - if paramname == "loader": - guest.installer.loader = val - else: - setattr(guest.installer.bootconfig, paramname, val) + setattr(guest.os, paramname, val) # Convert menu= value if "menu" in opts: @@ -1307,14 +1304,14 @@ def parse_boot(guest, optstring): if opts: boot_order = [] for boot_dev in optlist: - if not boot_dev in guest.installer.bootconfig.boot_devices: + if not boot_dev in guest.os.boot_devices: continue del(opts[boot_dev]) if boot_dev not in boot_order: boot_order.append(boot_dev) - guest.installer.bootconfig.bootorder = boot_order + guest.os.bootorder = boot_order if opts: raise ValueError(_("Unknown options %s") % opts.keys()) diff --git a/virtinst/support.py b/virtinst/support.py index 27f27344c..6a00925b8 100644 --- a/virtinst/support.py +++ b/virtinst/support.py @@ -375,6 +375,12 @@ def get_rhel6(): return _rhel6 +def support_remote_url_install(conn): + if hasattr(conn, "_virtinst__fake_conn"): + return False + return conn.check_stream_support(conn.SUPPORT_STREAM_UPLOAD) + + # Check that command is present in the python bindings, and return the # the requested function def _get_command(funcname, objname=None, obj=None): diff --git a/virtinst/util.py b/virtinst/util.py index 38c08c1e4..ca3d69f7f 100644 --- a/virtinst/util.py +++ b/virtinst/util.py @@ -537,3 +537,33 @@ def uuidstr(rawuuid): if i == 3 or i == 5 or i == 7 or i == 9: uuid.append('-') return "".join(uuid) + + + + +def get_system_scratchdir(hvtype): + scratchdir = os.environ.get("VIRTINST_TEST_SCRATCHDIR", None) + if scratchdir: + return scratchdir + + if hvtype == "test": + return "/tmp" + elif hvtype == "xen": + return "/var/lib/xen" + else: + return "/var/lib/libvirt/boot" + + +def make_scratchdir(conn, hvtype): + scratch = None + if not conn.is_session_uri(): + scratch = get_system_scratchdir(hvtype) + + if (not scratch or + not os.path.exists(scratch) or + not os.access(scratch, os.W_OK)): + scratch = os.path.expanduser("~/.virtinst/boot") + if not os.path.exists(scratch): + os.makedirs(scratch, 0751) + + return scratch