Exemplo n.º 1
0
    def _create(cls,
                dom,
                imgUUID,
                volUUID,
                size,
                volFormat,
                preallocate,
                volParent,
                srcImgUUID,
                srcVolUUID,
                volPath,
                initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """
        if initialSize:
            cls.log.error("initialSize is not supported for file-based "
                          "volumes")
            raise se.InvalidParameterException("initial size", initialSize)

        sizeBytes = size * BLOCK_SIZE
        truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(
                volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise

        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                                 sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        # Forcing the volume permissions in case one of the tools we use
        # (dd, qemu-img, etc.) will mistakenly change the file permissiosn.
        dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS)

        return (volPath, )
Exemplo n.º 2
0
    def create(cls, repoPath, sdUUID, imgUUID, size, volFormat, preallocate,
               diskType, volUUID, desc, srcImgUUID, srcVolUUID):
        """
        Create a new volume with given size or snapshot
            'size' - in sectors
            'volFormat' - volume format COW / RAW
            'preallocate' - Prealocate / Sparse
            'diskType' - string that describes disk type System|Data|Shared|Swap|Temp
            'srcImgUUID' - source image UUID
            'srcVolUUID' - source volume UUID
        """
        if not volUUID:
            volUUID = str(uuid.uuid4())
        if volUUID == volume.BLANK_UUID:
            raise se.InvalidParameterException("volUUID", volUUID)

        # Validate volume parameters should be checked here for all
        # internal flows using volume creation.
        cls.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)

        imageDir = image.Image(repoPath).create(sdUUID, imgUUID)
        vol_path = os.path.join(imageDir, volUUID)
        voltype = "LEAF"
        pvol = None
        # Check if volume already exists
        if oop.getProcessPool(sdUUID).fileUtils.pathExists(vol_path):
            raise se.VolumeAlreadyExists(vol_path)
        # Check if snapshot creation required
        if srcVolUUID != volume.BLANK_UUID:
            if srcImgUUID == volume.BLANK_UUID:
                srcImgUUID = imgUUID
            pvol = FileVolume(repoPath, sdUUID, srcImgUUID, srcVolUUID)
            # Cannot create snapshot for ILLEGAL volume
            if not pvol.isLegal():
                raise se.createIllegalVolumeSnapshotError(pvol.volUUID)

        # create volume rollback
        vars.task.pushRecovery(
            task.Recovery("halfbaked volume rollback", "fileVolume",
                          "FileVolume", "halfbakedVolumeRollback", [vol_path]))
        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting,
                                 (int(size) * 512))
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
Exemplo n.º 3
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, imgPath, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        sizeBytes = int(size) * BLOCK_SIZE

        if preallocate == volume.SPARSE_VOL:
            # Sparse = regular file
            oop.getProcessPool(dom.sdUUID).truncateFile(volPath, sizeBytes)
        else:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                                 sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)

            if volFormat == volume.COW_FORMAT:
                volume.createVolume(None, None, volPath, size, volFormat,
                                    preallocate)
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(imgPath, volUUID, volFormat, preallocate)

        # By definition the volume is a leaf
        cls.file_setrw(volPath, rw=True)

        return (volPath, )
Exemplo n.º 4
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True,
                         rw=True,
                         chainrw=force,
                         setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy(
                    "/dev/zero",
                    vol_path,
                    vars.task.aborting,
                    int(size),
                    recoveryCallback=volume.baseAsyncTasksRollback)
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
Exemplo n.º 5
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        # On block storage domains we store a volume's parent UUID in two
        # places: 1) in the domain's metadata LV, and 2) in a LV tag attached
        # to the volume LV itself.  The LV tag is more efficient to access
        # than the domain metadata but it may only be updated by the SPM.
        #
        # This means that after a live merge completes the domain metadata LV
        # will be updated but the LV tag will not.  We can detect this case
        # here and fix the LV tag since this is an SPM verb.
        #
        # File domains do not have this complexity because the metadata is
        # stored in only one place and that metadata is updated by the HSM
        # host when the live merge finishes.
        sync = False
        for childID in self.getChildren():
            child = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                childID)
            metaParent = child.getParentMeta()
            tagParent = child.getParentTag()
            if metaParent != tagParent:
                self.log.debug(
                    "Updating stale PUUID LV tag from %s to %s for "
                    "volume %s", tagParent, metaParent, child.volUUID)
                child.setParentTag(metaParent)
                sync = True
        if sync:
            self.recheckIfLeaf()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True,
                         rw=True,
                         chainrw=force,
                         setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting,
                                 int(size))
            except utils.ActionStopped:
                raise
            except Exception:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
            finally:
                self.teardown(self.sdUUID, self.volUUID, justme=True)

        # try to cleanup as much as possible
        eFound = se.CannotDeleteVolume(self.volUUID)
        puuid = None
        try:
            # We need to blank parent record in our metadata
            # for parent to become leaf successfully.
            puuid = self.getParent()
            self.setParent(volume.BLANK_UUID)
            if puuid and puuid != volume.BLANK_UUID:
                pvol = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                   puuid)
                pvol.recheckIfLeaf()
        except Exception as e:
            eFound = e
            self.log.warning("cannot finalize parent volume %s",
                             puuid,
                             exc_info=True)

        try:
            try:
                lvm.removeLVs(self.sdUUID, self.volUUID)
            except se.CannotRemoveLogicalVolume:
                # At this point LV is already marked as illegal, we will
                # try to cleanup whatever we can...
                pass

            self.removeMetadata([self.sdUUID, offs])
        except Exception as e:
            eFound = e
            self.log.error("cannot remove volume %s/%s",
                           self.sdUUID,
                           self.volUUID,
                           exc_info=True)

        try:
            self.log.debug("Unlinking %s", vol_path)
            os.unlink(vol_path)
            return True
        except Exception as e:
            eFound = e
            self.log.error("cannot delete volume's %s/%s link path: %s",
                           self.sdUUID,
                           self.volUUID,
                           vol_path,
                           exc_info=True)

        raise eFound
Exemplo n.º 6
0
    def create(cls, sdUUID, domainName, domClass, vgUUID, storageType,
               version):
        """ Create new storage domain
            'sdUUID' - Storage Domain UUID
            'domainName' - storage domain name
            'domClass' - Data/Iso
            'vgUUID' - volume group UUID
            'storageType' - NFS_DOMAIN, LOCALFS_DOMAIN, &etc.
            'version' - DOMAIN_VERSIONS
        """
        cls.log.info("sdUUID=%s domainName=%s domClass=%s vgUUID=%s "
                     "storageType=%s version=%s", sdUUID, domainName, domClass,
                     vgUUID, storageType, version)

        if not misc.isAscii(domainName) and not sd.supportsUnicode(version):
            raise se.UnicodeArgumentException()

        if len(domainName) > sd.MAX_DOMAIN_DESCRIPTION_SIZE:
            raise se.StorageDomainDescriptionTooLongError()

        sd.validateDomainVersion(version)

        vg = lvm.getVGbyUUID(vgUUID)
        vgName = vg.name

        if set((STORAGE_UNREADY_DOMAIN_TAG,)) != set(vg.tags):
            raise se.VolumeGroupHasDomainTag(vgUUID)
        try:
            lvm.getLV(vgName)
            raise se.StorageDomainNotEmpty(vgUUID)
        except se.LogicalVolumeDoesNotExistError:
            pass

        numOfPVs = len(lvm.listPVNames(vgName))
        if version in VERS_METADATA_LV and numOfPVs > MAX_PVS:
            cls.log.debug("%d > %d", numOfPVs, MAX_PVS)
            raise se.StorageDomainIsMadeFromTooManyPVs()

        # Create metadata service volume
        metasize = cls.metaSize(vgName)
        lvm.createLV(vgName, sd.METADATA, "%s" % (metasize))
        # Create the mapping right now so the index 0 is guaranteed
        # to belong to the metadata volume. Since the metadata is at
        # least SDMETADATA/METASIZE units, we know we can use the first
        # SDMETADATA bytes of the metadata volume for the SD metadata.
        # pass metadata's dev to ensure it is the first mapping
        mapping = cls.getMetaDataMapping(vgName)

        # Create the rest of the BlockSD internal volumes
        for metaFile, metaSizeMb in sd.SPECIAL_VOLUME_SIZES_MIB.iteritems():
            lvm.createLV(vgName, metaFile, metaSizeMb)

        lvm.createLV(vgName, MASTERLV, MASTERLV_SIZE)

        # Create VMS file system
        _createVMSfs(os.path.join("/dev", vgName, MASTERLV))

        lvm.deactivateLVs(vgName, MASTERLV)

        path = lvm.lvPath(vgName, sd.METADATA)

        # Zero out the metadata and special volumes before use
        try:
            misc.ddCopy("/dev/zero", path, RESERVED_METADATA_SIZE)
            path = lvm.lvPath(vgName, sd.INBOX)
            misc.ddCopy("/dev/zero", path, RESERVED_MAILBOX_SIZE)
            path = lvm.lvPath(vgName, sd.OUTBOX)
            misc.ddCopy("/dev/zero", path, RESERVED_MAILBOX_SIZE)
        except utils.ActionStopped:
            raise
        except se.StorageException:
            raise se.VolumesZeroingError(path)

        if version in VERS_METADATA_LV:
            md = LvBasedSDMetadata(vgName, sd.METADATA)
        elif version in VERS_METADATA_TAG:
            md = TagBasedSDMetadata(vgName)

        logBlkSize, phyBlkSize = lvm.getVGBlockSizes(vgName)

        # create domain metadata
        # FIXME : This is 99% like the metadata in file SD
        #         Do we really need to keep the VGUUID?
        #         no one reads it from here anyway
        initialMetadata = {
            sd.DMDK_VERSION: version,
            sd.DMDK_SDUUID: sdUUID,
            sd.DMDK_TYPE: storageType,
            sd.DMDK_CLASS: domClass,
            sd.DMDK_DESCRIPTION: domainName,
            sd.DMDK_ROLE: sd.REGULAR_DOMAIN,
            sd.DMDK_POOLS: [],
            sd.DMDK_LOCK_POLICY: '',
            sd.DMDK_LOCK_RENEWAL_INTERVAL_SEC: sd.DEFAULT_LEASE_PARAMS[
                sd.DMDK_LOCK_RENEWAL_INTERVAL_SEC],
            sd.DMDK_LEASE_TIME_SEC: sd.DEFAULT_LEASE_PARAMS[
                sd.DMDK_LEASE_TIME_SEC],
            sd.DMDK_IO_OP_TIMEOUT_SEC: sd.DEFAULT_LEASE_PARAMS[
                sd.DMDK_IO_OP_TIMEOUT_SEC],
            sd.DMDK_LEASE_RETRIES: sd.DEFAULT_LEASE_PARAMS[
                sd.DMDK_LEASE_RETRIES],
            DMDK_VGUUID: vgUUID,
            DMDK_LOGBLKSIZE: logBlkSize,
            DMDK_PHYBLKSIZE: phyBlkSize,
        }

        initialMetadata.update(mapping)

        md.update(initialMetadata)

        # Mark VG with Storage Domain Tag
        try:
            lvm.replaceVGTag(vgName, STORAGE_UNREADY_DOMAIN_TAG,
                             STORAGE_DOMAIN_TAG)
        except se.StorageException:
            raise se.VolumeGroupUninitialized(vgName)

        bsd = BlockStorageDomain(sdUUID)

        bsd.initSPMlease()

        return bsd
Exemplo n.º 7
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True,
                         rw=True,
                         chainrw=force,
                         setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting,
                                 int(size))
            except utils.ActionStopped:
                raise
            except Exception:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
            finally:
                self.teardown(self.sdUUID, self.volUUID, justme=True)

        # try to cleanup as much as possible
        eFound = se.CannotDeleteVolume(self.volUUID)
        puuid = None
        try:
            # We need to blank parent record in our metadata
            # for parent to become leaf successfully.
            puuid = self.getParent()
            self.setParent(volume.BLANK_UUID)
            if puuid and puuid != volume.BLANK_UUID:
                pvol = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                   puuid)
                pvol.recheckIfLeaf()
        except Exception as e:
            eFound = e
            self.log.warning("cannot finalize parent volume %s",
                             puuid,
                             exc_info=True)

        try:
            try:
                lvm.removeLVs(self.sdUUID, self.volUUID)
            except se.CannotRemoveLogicalVolume:
                # At this point LV is already marked as illegal, we will
                # try to cleanup whatever we can...
                pass

            self.removeMetadata([self.sdUUID, offs])
        except Exception as e:
            eFound = e
            self.log.error("cannot remove volume %s/%s",
                           self.sdUUID,
                           self.volUUID,
                           exc_info=True)

        try:
            self.log.debug("Unlinking %s", vol_path)
            os.unlink(vol_path)
            return True
        except Exception as e:
            eFound = e
            self.log.error("cannot delete volume's %s/%s link path: %s",
                           self.sdUUID,
                           self.volUUID,
                           vol_path,
                           exc_info=True)

        raise eFound
Exemplo n.º 8
0
    #See http://gerrit.usersys.redhat.com/771
    #Assert volumes are writable. (Don't do this at home.)
    lvNames = (vol.volUUID for vol in volumes)
    try:
        lvm.changelv(sdUUID, lvNames, "--permission", "rw")
    except se.StorageException, e:
        #Hope this only means that some volumes were already writable
        pass
    for lv in lvm.getLV(sdUUID):
        if lv.name in lvNames:
            # wipe out the whole volume
            try:
                misc.ddWatchCopy(
                    "/dev/zero",
                    lvm.lvPath(sdUUID, lv.name),
                    vars.task.aborting,
                    int(lv.size),
                    recoveryCallback=volume.baseAsyncTasksRollback)
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                raise se.VolumesZeroingError(lv.name)


def deleteMultipleVolumes(sdUUID, volumes, postZero):
    "Delete multiple volumes (LVs) in the same domain (VG)." ""
    if postZero:
        _postZero(sdUUID, volumes)
    lvNames = [vol.volUUID for vol in volumes]
    lvm.removeLVs(sdUUID, lvNames)
Exemplo n.º 9
0
class BlockStorageDomain(sd.StorageDomain):
    mountpoint = os.path.join(sd.StorageDomain.storage_repository,
                              sd.DOMAIN_MNT_POINT, sd.BLOCKSD_DIR)

    def __init__(self, sdUUID):
        domaindir = os.path.join(self.mountpoint, sdUUID)
        metadata = selectMetadata(sdUUID)
        sd.StorageDomain.__init__(self, sdUUID, domaindir, metadata)
        lvm.activateLVs(self.sdUUID, SPECIAL_LVS)
        self.metavol = lvm.lvPath(self.sdUUID, sd.METADATA)

        try:
            self.logBlkSize = self.getMetaParam(DMDK_LOGBLKSIZE)
            self.phyBlkSize = self.getMetaParam(DMDK_PHYBLKSIZE)
        except KeyError:
            # Initialize the block sizes metadata if not defined
            self.logBlkSize, self.phyBlkSize = lvm.getVGBlockSizes(sdUUID)
            self.setMetaParam(DMDK_LOGBLKSIZE, self.logBlkSize)
            self.setMetaParam(DMDK_PHYBLKSIZE, self.phyBlkSize)

        # Check that all devices in the VG have the same logical and physical
        # block sizes.
        lvm.checkVGBlockSizes(sdUUID, (self.logBlkSize, self.phyBlkSize))

        # _extendlock is used to prevent race between
        # VG extend and LV extend.
        self._extendlock = threading.Lock()
        self.imageGarbageCollector()
        self._registerResourceNamespaces()
        self._lastUncachedSelftest = 0

    def _registerResourceNamespaces(self):
        """
        Register resources namespaces and create
        factories for it.
        """
        sd.StorageDomain._registerResourceNamespaces(self)

        rmanager = rm.ResourceManager.getInstance()
        # Register lvm activation resource namespace for the underlying VG
        lvmActivationFactory = resourceFactories.LvmActivationFactory(
            self.sdUUID)
        lvmActivationNamespace = sd.getNamespace(self.sdUUID,
                                                 LVM_ACTIVATION_NAMESPACE)
        try:
            rmanager.registerNamespace(lvmActivationNamespace,
                                       lvmActivationFactory)
        except Exception:
            self.log.warn("Resource namespace %s already registered",
                          lvmActivationNamespace)

    @classmethod
    def metaSize(cls, vgroup):
        ''' Calc the minimal meta volume size in MB'''
        # In any case the metadata volume cannot be less than 512MB for the
        # case of 512 bytes per volume metadata, 2K for domain metadata and
        # extent size of 128MB. In any case we compute the right size on line.
        vg = lvm.getVG(vgroup)
        minmetasize = (SD_METADATA_SIZE / sd.METASIZE * int(vg.extent_size) +
                       (1024 * 1024 - 1)) / (1024 * 1024)
        metaratio = int(vg.extent_size) / sd.METASIZE
        metasize = (int(vg.extent_count) * sd.METASIZE +
                    (1024 * 1024 - 1)) / (1024 * 1024)
        metasize = max(minmetasize, metasize)
        if metasize > int(vg.free) / (1024 * 1024):
            raise se.VolumeGroupSizeError(
                "volume group has not enough extents %s (Minimum %s), VG may be too small"
                % (vg.extent_count, (1024 * 1024) / sd.METASIZE))
        cls.log.info("size %s MB (metaratio %s)" % (metasize, metaratio))
        return metasize

    @classmethod
    def create(cls, sdUUID, domainName, domClass, vgUUID, storageType,
               version):
        """ Create new storage domain
            'sdUUID' - Storage Domain UUID
            'domainName' - storage domain name
            'vgUUID' - volume group UUID
            'domClass' - Data/Iso
        """
        cls.log.info(
            "sdUUID=%s domainName=%s domClass=%s vgUUID=%s "
            "storageType=%s version=%s", sdUUID, domainName, domClass, vgUUID,
            storageType, version)

        if len(domainName) > sd.MAX_DOMAIN_DESCRIPTION_SIZE:
            raise se.StorageDomainDescriptionTooLongError()

        sd.validateDomainVersion(version)

        vg = lvm.getVGbyUUID(vgUUID)
        vgName = vg.name

        if set((STORAGE_UNREADY_DOMAIN_TAG, )) != set(vg.tags):
            raise se.VolumeGroupHasDomainTag(vgUUID)
        try:
            lvm.getLV(vgName)
            raise se.StorageDomainNotEmpty(vgUUID)
        except se.LogicalVolumeDoesNotExistError:
            pass

        numOfPVs = len(lvm.listPVNames(vgName))
        if version in VERS_METADATA_LV and numOfPVs > MAX_PVS:
            cls.log.debug("%d > %d", numOfPVs, MAX_PVS)
            raise se.StorageDomainIsMadeFromTooManyPVs()

        # Set the name of the VG to be the same as sdUUID
        if vgName != sdUUID:
            lvm.renameVG(vgName, sdUUID)
            vgName = sdUUID
        # Create metadata service volume
        metasize = cls.metaSize(vgName)
        lvm.createLV(vgName, sd.METADATA, "%s" % (metasize))
        # Create the mapping right now so the index 0 is guaranteed
        # to belong to the metadata volume. Since the metadata is at
        # least SDMETADATA/METASIZE units, we know we can use the first
        # SDMETADATA bytes of the metadata volume for the SD metadata.
        # pass metadata's dev to ensure it is the first mapping
        mapping = cls.getMetaDataMapping(vgName)

        # Create the rest of the BlockSD internal volumes
        lvm.createLV(vgName, sd.LEASES, sd.LEASES_SIZE)
        lvm.createLV(vgName, sd.IDS, sd.IDS_SIZE)
        lvm.createLV(vgName, sd.INBOX, sd.INBOX_SIZE)
        lvm.createLV(vgName, sd.OUTBOX, sd.OUTBOX_SIZE)
        lvm.createLV(vgName, MASTERLV, MASTERLV_SIZE)

        # Create VMS file system
        _createVMSfs(os.path.join("/dev", vgName, MASTERLV))

        lvm.deactivateLVs(vgName, MASTERLV)

        path = lvm.lvPath(vgName, sd.METADATA)

        # Zero out the metadata and special volumes before use
        try:
            misc.ddCopy("/dev/zero", path, RESERVED_METADATA_SIZE)
            path = lvm.lvPath(vgName, sd.INBOX)
            misc.ddCopy("/dev/zero", path, RESERVED_MAILBOX_SIZE)
            path = lvm.lvPath(vgName, sd.OUTBOX)
            misc.ddCopy("/dev/zero", path, RESERVED_MAILBOX_SIZE)
        except se.ActionStopped, e:
            raise e
        except se.StorageException:
            raise se.VolumesZeroingError(path)