This patch is a simple move to prepare for the fun stuff. VirtualDisk is removed out of Guest.py and put into its own file VirtualDisk.py. All files that were relatively importing VirtualDisk needed to be fixed up as well. Thanks, Cole
# HG changeset patch # User "Cole Robinson <crobinso@xxxxxxxxxx>" # Date 1217985457 14400 # Node ID 7e161f48ad67ccdd023105a5489777adad5fe482 # Parent 6a207373b908ab521d33cd675c7c8d3854bdc1f1 Move VirtualDisk to its own file. diff -r 6a207373b908 -r 7e161f48ad67 virtinst/CloneManager.py --- a/virtinst/CloneManager.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/CloneManager.py Tue Aug 05 21:17:37 2008 -0400 @@ -29,6 +29,7 @@ import commands import libvirt import Guest +from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ # @@ -332,7 +333,7 @@ # ret : Use File Path # def _check_file(self, conn, disk, size): - d = Guest.VirtualDisk(disk, size) + d = VirtualDisk(disk, size) return d.path # diff -r 6a207373b908 -r 7e161f48ad67 virtinst/DistroManager.py --- a/virtinst/DistroManager.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/DistroManager.py Tue Aug 05 21:17:37 2008 -0400 @@ -29,6 +29,7 @@ import tempfile import util import Guest +from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ from ImageFetcher import MountedImageFetcher @@ -176,10 +177,10 @@ arch = arch) self._tmpfiles.append(cdrom) - self._install_disk = Guest.VirtualDisk(cdrom, - device=Guest.VirtualDisk.DEVICE_CDROM, - readOnly=True, - transient=True) + self._install_disk = VirtualDisk(cdrom, + device=VirtualDisk.DEVICE_CDROM, + readOnly=True, + transient=True) def _prepare_kernel_and_initrd(self, guest, distro, meter): if self.boot is not None: @@ -213,9 +214,9 @@ # If they're installing off a local file/device, we map it # through to a virtual harddisk if self.location is not None and self.location.startswith("/") and not os.path.isdir(self.location): - self._install_disk = Guest.VirtualDisk(self.location, - readOnly=True, - transient=True) + self._install_disk = VirtualDisk(self.location, + readOnly=True, + transient=True) def prepare(self, guest, meter, distro = None): self.cleanup() diff -r 6a207373b908 -r 7e161f48ad67 virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/FullVirtGuest.py Tue Aug 05 21:17:37 2008 -0400 @@ -26,6 +26,7 @@ import DistroManager import logging import time +from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ @@ -285,7 +286,7 @@ # First assign CDROM device nodes, since they're scarce resource cdnode = self.disknode + "c" for d in self._install_disks: - if d.device != Guest.VirtualDisk.DEVICE_CDROM: + if d.device != VirtualDisk.DEVICE_CDROM: continue if d.target: @@ -300,7 +301,7 @@ # Now assign regular disk node with remainder for d in self._install_disks: - if d.device == Guest.VirtualDisk.DEVICE_CDROM: + if d.device == VirtualDisk.DEVICE_CDROM: continue if d.target is None: # Auto-assign disk @@ -316,7 +317,7 @@ for d in self._install_disks: saved_path = None - if d.device == Guest.VirtualDisk.DEVICE_CDROM \ + if d.device == VirtualDisk.DEVICE_CDROM \ and d.transient and not install: # Keep cdrom around, but with no media attached # But only if we are a distro that doesn't have a multi diff -r 6a207373b908 -r 7e161f48ad67 virtinst/Guest.py --- a/virtinst/Guest.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/Guest.py Tue Aug 05 21:17:37 2008 -0400 @@ -31,249 +31,6 @@ from virtinst import _virtinst as _ import logging - -class VirtualDisk: - DRIVER_FILE = "file" - DRIVER_PHY = "phy" - DRIVER_TAP = "tap" - - DRIVER_TAP_RAW = "aio" - DRIVER_TAP_QCOW = "qcow" - DRIVER_TAP_VMDK = "vmdk" - - DEVICE_DISK = "disk" - DEVICE_CDROM = "cdrom" - DEVICE_FLOPPY = "floppy" - - TYPE_FILE = "file" - TYPE_BLOCK = "block" - - def __init__(self, path = None, size = None, transient=False, type=None, device=DEVICE_DISK, driverName=None, driverType=None, readOnly=False, sparse=True): - """@path is the path to the disk image. - @size is the size of the disk image in gigabytes.""" - self.size = size - self.sparse = sparse - self.transient = transient - self.path = path - self._type = type - self._readOnly = readOnly - self._device = device - self._driverName = driverName - self._driverType = driverType - self.target = None - - # Reset type variable as the builtin function - type = __builtin__.type - - if self._device == self.DEVICE_CDROM: - self._readOnly = True - - # Only floppy or cdrom can be created w/o media - if self.path is None: - if device != self.DEVICE_FLOPPY and device != self.DEVICE_CDROM: - raise ValueError, _("Disk type '%s' requires a path") % device - return - - # Basic path validation - if type(self.path) is not str: - raise ValueError, _("The %s path must be a string or None.") % \ - self._device - self.path = os.path.abspath(self.path) - if os.path.isdir(self.path): - raise ValueError, _("The %s path must be a file or a device, not a directory") % self._device - - # Main distinction: does path exist or not? - if os.path.exists(self.path): - logging.debug("VirtualDisk path exists.") - - # Determine disk type - if stat.S_ISBLK(os.stat(self.path)[stat.ST_MODE]): - logging.debug("Path is block file: Assuming Block disk type.") - newtype = VirtualDisk.TYPE_BLOCK - else: - newtype = VirtualDisk.TYPE_FILE - - if self._type is not None and self._type != newtype: - raise ValueError, _("Path is not specified type '%s'." % \ - self._type) - self._type = newtype - - - else: - logging.debug("VirtualDisk path does not exist.") - if self._device == self.DEVICE_FLOPPY or \ - self._device == self.DEVICE_CDROM: - raise ValueError, _("The %s path must exist.") % self._device - - if self._type is self.TYPE_BLOCK: - raise ValueError, _("Block device path must exist.") - self._type = self.TYPE_FILE - - # Path doesn't exist: make sure we have write access to dir - if not os.access(os.path.dirname(self.path), os.W_OK): - raise ValueError, _("No write access to directory '%s'") % \ - os.path.dirname(self.path) - - # Ensure size was specified - if size is None or type(size) not in [int, float] or size < 0: - raise ValueError, \ - _("A size must be provided for non-existent disks") - - ret = self.size_conflict() - if ret[0]: - raise ValueError, ret[1] - elif ret[1]: - logging.warn(ret[1]) - - - def get_type(self): - return self._type - type = property(get_type) - - def get_device(self): - return self._device - device = property(get_device) - - def get_driver_name(self): - return self._driverName - driver_name = property(get_driver_name) - - def get_driver_type(self): - return self._driverType - driver_type = property(get_driver_type) - - def get_read_only(self): - return self._readOnly - read_only = property(get_read_only) - - def setup(self, progresscb): - if self._type == VirtualDisk.TYPE_FILE and self.path is not None \ - and not os.path.exists(self.path): - size_bytes = long(self.size * 1024L * 1024L * 1024L) - progresscb.start(filename=self.path,size=long(size_bytes), \ - text=_("Creating storage file...")) - fd = None - try: - try: - fd = os.open(self.path, os.O_WRONLY | os.O_CREAT) - if self.sparse: - os.lseek(fd, size_bytes, 0) - os.write(fd, '\x00') - progresscb.update(self.size) - else: - buf = '\x00' * 1024 * 1024 # 1 meg of nulls - for i in range(0, long(self.size * 1024L)): - os.write(fd, buf) - progresscb.update(long(i * 1024L * 1024L)) - except OSError, detail: - raise RuntimeError, "Error creating diskimage " + self.path + ": " + detail.strerror - finally: - if fd is not None: - os.close(fd) - progresscb.end(size_bytes) - # FIXME: set selinux context? - - def get_xml_config(self, disknode): - typeattr = 'file' - if self.type == VirtualDisk.TYPE_BLOCK: - typeattr = 'dev' - - ret = " <disk type='%(type)s' device='%(device)s'>\n" % { "type": self.type, "device": self.device } - if not(self.driver_name is None): - if self.driver_type is None: - ret += " <driver name='%(name)s'/>\n" % { "name": self.driver_name } - else: - ret += " <driver name='%(name)s' type='%(type)s'/>\n" % { "name": self.driver_name, "type": self.driver_type } - if self.path is not None: - path = util.xml_escape(self.path) - ret += " <source %(typeattr)s='%(disk)s'/>\n" % { "typeattr": typeattr, "disk": path } - if self.target is not None: - disknode = self.target - ret += " <target dev='%(disknode)s'/>\n" % { "disknode": disknode } - if self.read_only: - ret += " <readonly/>\n" - ret += " </disk>" - return ret - - def size_conflict(self): - """size_conflict: reports if disk size conflicts with available space - - returns a two element tuple: - first element is True if fatal conflict occurs - second element is a string description of the conflict or None - Non fatal conflicts (sparse disk exceeds available space) will - return (False, "description of collision")""" - - if not self.size or not self.path or os.path.exists(self.path) or \ - self.type != self.TYPE_FILE: - return (False, None) - - ret = False - msg = None - vfs = os.statvfs(os.path.dirname(self.path)) - avail = vfs[statvfs.F_FRSIZE] * vfs[statvfs.F_BAVAIL] - need = self.size * 1024 * 1024 * 1024 - if need > avail: - if self.sparse: - msg = _("The filesystem will not have enough free space" - " to fully allocate the sparse file when the guest" - " is running.") - else: - ret = True - msg = _("There is not enough free space to create the disk.") - return (ret, msg) - - def is_conflict_disk(self, conn): - vms = [] - # get working domain's name - ids = conn.listDomainsID(); - for id in ids: - try: - vm = conn.lookupByID(id) - vms.append(vm) - except libvirt.libvirtError: - # guest probably in process of dieing - logging.warn("Failed to lookup domain id %d" % id) - # get defined domain - names = conn.listDefinedDomains() - for name in names: - try: - vm = conn.lookupByName(name) - vms.append(vm) - except libvirt.libvirtError: - # guest probably in process of dieing - logging.warn("Failed to lookup domain name %s" % name) - - count = 0 - for vm in vms: - doc = None - try: - doc = libxml2.parseDoc(vm.XMLDesc(0)) - except: - continue - ctx = doc.xpathNewContext() - try: - try: - count += ctx.xpathEval("count(/domain/devices/disk/source[@dev='%s'])" % self.path) - count += ctx.xpathEval("count(/domain/devices/disk/source[@file='%s'])" % self.path) - except: - continue - finally: - if ctx is not None: - ctx.xpathFreeContext() - if doc is not None: - doc.freeDoc() - if count > 0: - return True - else: - return False - - def __repr__(self): - return "%s:%s" %(self.type, self.path) - -# Back compat class to avoid ABI break -class XenDisk(VirtualDisk): - pass class VirtualNetworkInterface: def __init__(self, macaddr = None, type="bridge", bridge = None, network=None): diff -r 6a207373b908 -r 7e161f48ad67 virtinst/ImageManager.py --- a/virtinst/ImageManager.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/ImageManager.py Tue Aug 05 21:17:37 2008 -0400 @@ -21,6 +21,7 @@ import Guest import ImageParser import CapabilitiesParser as Cap +from VirtualDisk import VirtualDisk import os import util from virtinst import _virtinst as _ @@ -94,14 +95,14 @@ if m.disk.use == ImageParser.Disk.USE_SYSTEM and not os.path.exists(p): raise ImageInstallerException(_("System disk %s does not exist") % p) - device = Guest.VirtualDisk.DEVICE_DISK + device = VirtualDisk.DEVICE_DISK if m.disk.format == ImageParser.Disk.FORMAT_ISO: - device = Guest.VirtualDisk.DEVICE_CDROM - d = Guest.VirtualDisk(p, s, - device = device, - type = Guest.VirtualDisk.TYPE_FILE) + device = VirtualDisk.DEVICE_CDROM + d = VirtualDisk(p, s, + device = device, + type = VirtualDisk.TYPE_FILE) if self.boot_caps.type == "xen" and util.is_blktap_capable(): - d.driver_name = Guest.VirtualDisk.DRIVER_TAP + d.driver_name = VirtualDisk.DRIVER_TAP d.target = m.target guest._install_disks.append(d) diff -r 6a207373b908 -r 7e161f48ad67 virtinst/LiveCDInstaller.py --- a/virtinst/LiveCDInstaller.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/LiveCDInstaller.py Tue Aug 05 21:17:37 2008 -0400 @@ -21,6 +21,7 @@ import os import Guest +from VirtualDisk import VirtualDisk import CapabilitiesParser from virtinst import _virtinst as _ @@ -50,9 +51,9 @@ if not found: raise LiveCDInstallerException(_("HVM virtualisation not supported; cannot boot LiveCD")) - disk = Guest.VirtualDisk(self.location, - device = Guest.VirtualDisk.DEVICE_CDROM, - readOnly = True) + disk = VirtualDisk(self.location, + device = VirtualDisk.DEVICE_CDROM, + readOnly = True) guest._install_disks.insert(0, disk) def _get_osblob(self, install, hvm, arch = None, loader = None, conn = None): diff -r 6a207373b908 -r 7e161f48ad67 virtinst/VirtualDisk.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/virtinst/VirtualDisk.py Tue Aug 05 21:17:37 2008 -0400 @@ -0,0 +1,274 @@ +# +# Copyright 2006-2007 Red Hat, Inc. +# Jeremy Katz <katzj@xxxxxxxxxx> +# +# 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, os.path +import statvfs +import stat, sys, time +import re +import libxml2 +import urlgrabber.progress as progress +import util +import libvirt +import __builtin__ +from virtinst import _virtinst as _ + +import logging + +class VirtualDisk: + DRIVER_FILE = "file" + DRIVER_PHY = "phy" + DRIVER_TAP = "tap" + + DRIVER_TAP_RAW = "aio" + DRIVER_TAP_QCOW = "qcow" + DRIVER_TAP_VMDK = "vmdk" + + DEVICE_DISK = "disk" + DEVICE_CDROM = "cdrom" + DEVICE_FLOPPY = "floppy" + + TYPE_FILE = "file" + TYPE_BLOCK = "block" + + def __init__(self, path = None, size = None, transient=False, type=None, device=DEVICE_DISK, driverName=None, driverType=None, readOnly=False, sparse=True): + """@path is the path to the disk image. + @size is the size of the disk image in gigabytes.""" + self.size = size + self.sparse = sparse + self.transient = transient + self.path = path + self._type = type + self._readOnly = readOnly + self._device = device + self._driverName = driverName + self._driverType = driverType + self.target = None + + # Reset type variable as the builtin function + type = __builtin__.type + + if self._device == self.DEVICE_CDROM: + self._readOnly = True + + # Only floppy or cdrom can be created w/o media + if self.path is None: + if device != self.DEVICE_FLOPPY and device != self.DEVICE_CDROM: + raise ValueError, _("Disk type '%s' requires a path") % device + return + + # Basic path validation + if type(self.path) is not str: + raise ValueError, _("The %s path must be a string or None.") % \ + self._device + self.path = os.path.abspath(self.path) + if os.path.isdir(self.path): + raise ValueError, _("The %s path must be a file or a device, not a directory") % self._device + + # Main distinction: does path exist or not? + if os.path.exists(self.path): + logging.debug("VirtualDisk path exists.") + + # Determine disk type + if stat.S_ISBLK(os.stat(self.path)[stat.ST_MODE]): + logging.debug("Path is block file: Assuming Block disk type.") + newtype = VirtualDisk.TYPE_BLOCK + else: + newtype = VirtualDisk.TYPE_FILE + + if self._type is not None and self._type != newtype: + raise ValueError, _("Path is not specified type '%s'." % \ + self._type) + self._type = newtype + + + else: + logging.debug("VirtualDisk path does not exist.") + if self._device == self.DEVICE_FLOPPY or \ + self._device == self.DEVICE_CDROM: + raise ValueError, _("The %s path must exist.") % self._device + + if self._type is self.TYPE_BLOCK: + raise ValueError, _("Block device path must exist.") + self._type = self.TYPE_FILE + + # Path doesn't exist: make sure we have write access to dir + if not os.access(os.path.dirname(self.path), os.W_OK): + raise ValueError, _("No write access to directory '%s'") % \ + os.path.dirname(self.path) + + # Ensure size was specified + if size is None or type(size) not in [int, float] or size < 0: + raise ValueError, \ + _("A size must be provided for non-existent disks") + + ret = self.size_conflict() + if ret[0]: + raise ValueError, ret[1] + elif ret[1]: + logging.warn(ret[1]) + + + def get_type(self): + return self._type + type = property(get_type) + + def get_device(self): + return self._device + device = property(get_device) + + def get_driver_name(self): + return self._driverName + driver_name = property(get_driver_name) + + def get_driver_type(self): + return self._driverType + driver_type = property(get_driver_type) + + def get_read_only(self): + return self._readOnly + read_only = property(get_read_only) + + def setup(self, progresscb): + if self._type == VirtualDisk.TYPE_FILE and self.path is not None \ + and not os.path.exists(self.path): + size_bytes = long(self.size * 1024L * 1024L * 1024L) + progresscb.start(filename=self.path,size=long(size_bytes), \ + text=_("Creating storage file...")) + fd = None + try: + try: + fd = os.open(self.path, os.O_WRONLY | os.O_CREAT) + if self.sparse: + os.lseek(fd, size_bytes, 0) + os.write(fd, '\x00') + progresscb.update(self.size) + else: + buf = '\x00' * 1024 * 1024 # 1 meg of nulls + for i in range(0, long(self.size * 1024L)): + os.write(fd, buf) + progresscb.update(long(i * 1024L * 1024L)) + except OSError, detail: + raise RuntimeError, "Error creating diskimage " + self.path + ": " + detail.strerror + finally: + if fd is not None: + os.close(fd) + progresscb.end(size_bytes) + # FIXME: set selinux context? + + def get_xml_config(self, disknode): + typeattr = 'file' + if self.type == VirtualDisk.TYPE_BLOCK: + typeattr = 'dev' + + ret = " <disk type='%(type)s' device='%(device)s'>\n" % { "type": self.type, "device": self.device } + if not(self.driver_name is None): + if self.driver_type is None: + ret += " <driver name='%(name)s'/>\n" % { "name": self.driver_name } + else: + ret += " <driver name='%(name)s' type='%(type)s'/>\n" % { "name": self.driver_name, "type": self.driver_type } + if self.path is not None: + path = util.xml_escape(self.path) + ret += " <source %(typeattr)s='%(disk)s'/>\n" % { "typeattr": typeattr, "disk": path } + if self.target is not None: + disknode = self.target + ret += " <target dev='%(disknode)s'/>\n" % { "disknode": disknode } + if self.read_only: + ret += " <readonly/>\n" + ret += " </disk>" + return ret + + def size_conflict(self): + """size_conflict: reports if disk size conflicts with available space + + returns a two element tuple: + first element is True if fatal conflict occurs + second element is a string description of the conflict or None + Non fatal conflicts (sparse disk exceeds available space) will + return (False, "description of collision")""" + + if not self.size or not self.path or os.path.exists(self.path) or \ + self.type != self.TYPE_FILE: + return (False, None) + + ret = False + msg = None + vfs = os.statvfs(os.path.dirname(self.path)) + avail = vfs[statvfs.F_FRSIZE] * vfs[statvfs.F_BAVAIL] + need = self.size * 1024 * 1024 * 1024 + if need > avail: + if self.sparse: + msg = _("The filesystem will not have enough free space" + " to fully allocate the sparse file when the guest" + " is running.") + else: + ret = True + msg = _("There is not enough free space to create the disk.") + return (ret, msg) + + def is_conflict_disk(self, conn): + vms = [] + # get working domain's name + ids = conn.listDomainsID(); + for id in ids: + try: + vm = conn.lookupByID(id) + vms.append(vm) + except libvirt.libvirtError: + # guest probably in process of dieing + logging.warn("Failed to lookup domain id %d" % id) + # get defined domain + names = conn.listDefinedDomains() + for name in names: + try: + vm = conn.lookupByName(name) + vms.append(vm) + except libvirt.libvirtError: + # guest probably in process of dieing + logging.warn("Failed to lookup domain name %s" % name) + + count = 0 + for vm in vms: + doc = None + try: + doc = libxml2.parseDoc(vm.XMLDesc(0)) + except: + continue + ctx = doc.xpathNewContext() + try: + try: + count += ctx.xpathEval("count(/domain/devices/disk/source[@dev='%s'])" % self.path) + count += ctx.xpathEval("count(/domain/devices/disk/source[@file='%s'])" % self.path) + except: + continue + finally: + if ctx is not None: + ctx.xpathFreeContext() + if doc is not None: + doc.freeDoc() + if count > 0: + return True + else: + return False + + def __repr__(self): + return "%s:%s" %(self.type, self.path) + +# Back compat class to avoid ABI break +class XenDisk(VirtualDisk): + pass diff -r 6a207373b908 -r 7e161f48ad67 virtinst/__init__.py --- a/virtinst/__init__.py Tue Jul 29 11:21:07 2008 -0400 +++ b/virtinst/__init__.py Tue Aug 05 21:17:37 2008 -0400 @@ -25,7 +25,9 @@ return gettext.dgettext(gettext_app, msg) import util -from Guest import Guest, VirtualDisk, VirtualNetworkInterface, XenGuest, XenDisk, XenNetworkInterface, VirtualGraphics, VirtualAudio +from Guest import Guest, VirtualNetworkInterface, XenGuest, \ + XenNetworkInterface, VirtualGraphics, VirtualAudio +from VirtualDisk import VirtualDisk, XenDisk from FullVirtGuest import FullVirtGuest from ParaVirtGuest import ParaVirtGuest from DistroManager import DistroInstaller, PXEInstaller
_______________________________________________ et-mgmt-tools mailing list et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools