[et-mgmt-tools] [PATCH] Add vdisk support

Cole Robinson crobinso at redhat.com
Tue Dec 9 03:09:16 UTC 2008


john.levon at sun.com wrote:
> # HG changeset patch
> # User john.levon at sun.com
> # Date 1228365031 28800
> # Node ID 152e0bfb277efb24679d7c7f440df0b0f6b21529
> # Parent  35baacfe79834400949ebdba69f952ed873ae442
> Add vdisk support
>
> Add support for the vdisk format used in Solaris.
>
> Signed-off-by: John Levon <john.levon at sun.com>
>
> diff --git a/virt-install b/virt-install
> --- a/virt-install
> +++ b/virt-install
> @@ -189,9 +189,13 @@ def get_disk(disk, size, sparse, guest, 
>                                   readOnly=readOnly, device=device, bus=bus,
>                                   conn=guest.conn)
>          # Default file backed PV guests to tap driver
> -        if d.type == virtinst.VirtualDisk.TYPE_FILE \
> -           and not(hvm) and virtinst.util.is_blktap_capable():
> -            d.driver_name = virtinst.VirtualDisk.DRIVER_TAP
> +        if d.type == virtinst.VirtualDisk.TYPE_FILE and not(hvm):
> +            if virtinst.util.is_blktap_capable():
> +                d.driver_name = virtinst.VirtualDisk.DRIVER_TAP
> +            elif virtinst.util.is_vdisk(path):
> +                d.driver_name = Guest.VirtualDisk.DRIVER_TAP
> +                d.driver_type = Guest.VirtualDisk.DRIVER_TAP_VDISK
> +
>   

Hmm, this whole block should probably be moved into the VirtualDisk
class, and used to set the default driver if the user doesn't
specify one. But it's not a blocker.

>      except ValueError, e:
>          fail(_("Error with storage parameters: %s" % str(e)))
>  
> diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py
> --- a/virtinst/CloneManager.py
> +++ b/virtinst/CloneManager.py
> @@ -19,7 +19,6 @@
>  # MA 02110-1301 USA.
>  
>  import os
> -import stat
>  import libxml2
>  import logging
>  import urlgrabber.progress as progress
> @@ -394,13 +393,9 @@ class CloneDesign(object):
>          logging.debug("original device list: %s" % (lst))
>  
>          for i in lst:
> -            mode = os.stat(i)[stat.ST_MODE]
> -            if stat.S_ISBLK(mode):
> -                size.append(util.blkdev_size(i))
> -                typ.append(False)
> -            elif stat.S_ISREG(mode):
> -                size.append(os.path.getsize(i))
> -                typ.append(True)
> +            (t, sz) = util.stat_disk(i)
> +            typ.append(t)
> +            size.append(sz)
>   

This, and all the other stat_disk code, seems like a separate cleanup.
Could we get this in a separate patch?

>          logging.debug("original device size: %s" % (size))
>          logging.debug("original device type: %s" % (typ))
>  
> @@ -443,18 +438,9 @@ class CloneDesign(object):
>          typ  = []
>  
>          for i in cln_dev_lst:
> -            if os.path.exists(i) ==  False:
> -                size.append(0)
> -                # if not exists, create file necessary
> -                typ.append(True)
> -                continue
> -            mode = os.stat(i)[stat.ST_MODE]
> -            if stat.S_ISBLK(mode):
> -                size.append(util.blkdev_size(i))
> -                typ.append(False)
> -            elif stat.S_ISREG(mode):
> -                size.append(os.path.getsize(i))
> -                typ.append(True)
> +            (t, sz) = util.stat_disk(i)
> +            typ.append(t)
> +            size.append(sz)
>  
>          logging.debug("clone device list: %s" % (cln_dev_lst))
>          logging.debug("clone device size: %s" % (size))
> @@ -535,6 +521,14 @@ def _do_duplicate(design):
>              if src_dev == "/dev/null" or src_dev == dst_dev:
>                  meter.end(size)
>                  continue
> +
> +            if util.is_vdisk(src_dev) or (os.path.exists(dst_dev) and util.is_vdisk(dst_dev)):
> +                if not util.is_vdisk(src_dev) or os.path.exists(dst_dev):
> +                    raise RuntimeError, _("copying to an existing vdisk is not supported")
> +                if not util.vdisk_clone(src_dev, dst_dev):
> +                    raise RuntimeError, _("failed to clone disk")
> +                continue
> +
>              #
>              # create sparse file
>              # if a destination file exists and sparse flg is True,
> diff --git a/virtinst/Guest.py b/virtinst/Guest.py
> --- a/virtinst/Guest.py
> +++ b/virtinst/Guest.py
> @@ -474,6 +474,9 @@ class Installer(object):
>             or guest.disks[0].device != VirtualDisk.DEVICE_DISK:
>              return True
>  
> +        if util.is_vdisk(guest.disks[0].path):
> +            return True
> +
>          # Check for the 0xaa55 signature at the end of the MBR
>          try:
>              fd = os.open(guest.disks[0].path, os.O_RDONLY)
> diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py
> --- a/virtinst/ImageManager.py
> +++ b/virtinst/ImageManager.py
> @@ -101,8 +101,13 @@ class ImageInstaller(Guest.Installer):
>              d = VirtualDisk(p, s,
>                              device = device,
>                              type = VirtualDisk.TYPE_FILE)
> -            if self.boot_caps.type == "xen" and util.is_blktap_capable():
> -                d.driver_name = VirtualDisk.DRIVER_TAP
> +            if util.is_vdisk(p):
> +                d.driver_name = Guest.VirtualDisk.DRIVER_TAP
> +                d.driver_type = Guest.VirtualDisk.DRIVER_TAP_VDISK
> +            else:
> +                if self.boot_caps.type == "xen" and util.is_blktap_capable():
> +                    d.driver_name = Guest.VirtualDisk.DRIVER_TAP
> +
>              d.target = m.target
>  
>              guest._install_disks.append(d)
> diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py
> --- a/virtinst/VirtualDisk.py
> +++ b/virtinst/VirtualDisk.py
> @@ -68,7 +68,9 @@ class VirtualDisk(VirtualDevice):
>      DRIVER_TAP_RAW = "aio"
>      DRIVER_TAP_QCOW = "qcow"
>      DRIVER_TAP_VMDK = "vmdk"
> -    driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, DRIVER_TAP_VMDK]
> +    DRIVER_TAP_VDISK = "vdisk"
> +    driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW,
> +        DRIVER_TAP_VMDK, DRIVER_TAP_VDISK]
>  
>      DEVICE_DISK = "disk"
>      DEVICE_CDROM = "cdrom"
> @@ -424,7 +426,8 @@ class VirtualDisk(VirtualDevice):
>                          or self.vol_object):
>              logging.debug("VirtualDisk storage exists.")
>  
> -            if using_path and os.path.isdir(self.path):
> +            if (using_path and os.path.isdir(self.path) and
> +                not util.is_vdisk(self.path)):
>                  raise ValueError, _("The path must be a file or a device,"
>                                      " not a directory")
>              self.__set_dev_type()
> @@ -476,9 +479,24 @@ class VirtualDisk(VirtualDevice):
>              self._set_vol_object(self.vol_install.install(meter=progresscb),
>                                   validate=False)
>              return
> -        elif self.type == VirtualDisk.TYPE_FILE and self.path is not None \
> -             and not os.path.exists(self.path):
> +        elif (self.type == VirtualDisk.TYPE_FILE and self.path is not None
> +            and os.path.exists(self.path) and util.is_vdisk(self.path)):
> +            self._driverName = self.DRIVER_TAP
> +            self._driverType = self.DRIVER_TAP_VDISK
>   

This could use a debug statement stating we are forcing the vdisk
driver.

> +            return
> +        elif (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)
> +
> +            if util.is_vdisk(self.path):
> +                progresscb.update(1024)
> +                if (not util.vdisk_create(self.path, size_bytes, "vmdk",
> +                    self.sparse)):
> +                    raise RuntimeError, _("Error creating vdisk %s" % self.path)
> +                self._driverName = self.DRIVER_TAP
> +                self._driverType = self.DRIVER_TAP_VDISK
> +                progresscb.end(self.size)
> +                return
>  
>              if progresscb:
>                  progresscb.start(filename=self.path,size=long(size_bytes), \
> diff --git a/virtinst/util.py b/virtinst/util.py
> --- a/virtinst/util.py
> +++ b/virtinst/util.py
> @@ -29,6 +29,7 @@ import stat
>  import stat
>  import popen2
>  from sys import stderr
> +from subprocess import call
>  
>  import libvirt
>  from virtinst import _virtinst as _
> @@ -283,17 +284,71 @@ def xml_escape(str):
>      str = str.replace(">", ">")
>      return str
>   
> -def blkdev_size(path):
> -    if platform.system() == 'SunOS':
> -        return os.stat(path)[stat.ST_SIZE]
> -    else:
> -        dummy, msg = commands.getstatusoutput('fdisk -s %s' % path)
> -        # check
> -        if msg.isdigit() == False:
> -            lines = msg.splitlines()
> -            # retry eg. for the GPT disk
> -            msg = lines[len(lines)-1]
> -        return (int(msg) * 1024)
> +def is_vdisk(path):
> +    if not os.path.exists("/usr/sbin/vdiskadm"):
> +        return False
> +    if not os.path.exists(path):
> +        return True
> +    if os.path.isdir(path) and \
> +       os.path.exists(path + "/vdisk.xml"):
> +        return True
> +    return False
> +
> +def vdisk_create(path, size, kind, sparse = True):
> +    force_fixed = "raw"
> +    path = os.path.expanduser(path)
> +    if kind in force_fixed or not sparse:
> +        type = kind + ":fixed"
> +    else:
> +        type = kind + ":sparse"
> +    args = " create -t " + type + " -s " + str(size) + " " + path
> +    try:
> +        rc = call("/usr/sbin/vdiskadm" + args, shell=True)
> +        if rc != 0:
> +            return False
> +        return True
> +    except OSError, e:
> +        return False
> +
> +def vdisk_clone(path, clone):
> +    path = os.path.expanduser(path)
> +    clone = os.path.expanduser(clone)
> +    args = path + " " + clone
> +    try:
> +        rc = call("/usr/sbin/vdiskadm clone " + args, shell=True)
> +        if rc != 0:
> +            return False
> +        return True
> +    except OSError, e:
> +        return False
> +
>   

These two can be moved to VirtualDisk and CloneManager respectively
as non class functions. Please prefix them with an underscore to
mark them as private.

> +def stat_disk(path):
> +    """Returns the tuple (isreg, size)."""
> +    if not os.path.exists(path):
> +        return True, 0
> +
> +    if is_vdisk(path):
> +        size = int(commands.getoutput(
> +            "vdiskadm prop-get -p max-size " + path))
> +        return True, size
> +
> +    mode = os.stat(path)[stat.ST_MODE]
> +    if stat.S_ISBLK(mode):
> +        if platform.system() == 'SunOS':
> +            size = os.stat(path)[stat.ST_SIZE]
> +        else:
> +            dummy, msg = commands.getstatusoutput('fdisk -s %s' % path)
> +            # check
> +            if msg.isdigit() == False:
> +                lines = msg.splitlines()
> +                # retry eg. for the GPT disk
> +                msg = lines[len(lines)-1]
> +            size = int(msg) * 1024
> +        return False, size
> +    elif stat.S_ISREG(mode):
> +        return True, os.path.getsize(path)
> +
> +    return True, 0
>  
>  def compareMAC(p, q):
>      """Compare two MAC addresses""

Thanks,
Cole




More information about the et-mgmt-tools mailing list