Ejemplo n.º 1
0
    def __validateConnectionParams(self, domType, conList):
        """
        Validate connection parameters
        """
        conParamsList = []

        if domType in sd.FILE_DOMAIN_TYPES:
            paramInfos = PARAMS_FILE_DOMAIN
        elif domType in sd.BLOCK_DOMAIN_TYPES:
            paramInfos = PARAMS_BLOCK_DOMAIN
        else:
            raise se.InvalidParameterException("type", domType)

        for con in conList:
            conParams = {}
            for paramInfo in paramInfos:
                conParamName, paramName = paramInfo[:2]
                hasDefault = len(paramInfo) > 2
                try:
                    if hasDefault:
                        value = con.get(paramName, paramInfo[2])
                    else:
                        value = con[paramName]

                    conParams[conParamName] = value
                except KeyError:
                    raise se.InvalidParameterException(
                        'parameter "%s" is missing from connection info %s' %
                        (paramName, con.get('id', "")))

            conParamsList.append(conParams)

        return conParamsList
Ejemplo n.º 2
0
    def _calculate_volume_alloc_size(cls, preallocate, capacity, initial_size):
        """ Calculate the allocation size in mb of the volume
        'preallocate' - Sparse or Preallocated
        'capacity' - the volume size in sectors
        'initial_size' - optional, if provided the initial allocated
                         size in sectors for sparse volumes
         """
        if initial_size and initial_size > capacity:
            log.error(
                "The volume size %s is smaller "
                "than the requested initial size %s", capacity, initial_size)
            raise se.InvalidParameterException("initial size", initial_size)

        if initial_size and preallocate == volume.PREALLOCATED_VOL:
            log.error("Initial size is not supported for preallocated volumes")
            raise se.InvalidParameterException("initial size", initial_size)

        if preallocate == volume.SPARSE_VOL:
            if initial_size:
                initial_size = int(initial_size * QCOW_OVERHEAD_FACTOR)
                alloc_size = ((initial_size + SECTORS_TO_MB - 1) /
                              SECTORS_TO_MB)
            else:
                alloc_size = config.getint("irs",
                                           "volume_utilization_chunk_mb")
        else:
            alloc_size = (capacity + SECTORS_TO_MB - 1) / SECTORS_TO_MB

        return alloc_size
Ejemplo n.º 3
0
def validateiSCSIParams(ip, port, username=None, password=None):
    if not ip:
        raise se.InvalidParameterException("IP", ip)
    else:
        try:
            ip = socket.gethostbyname(ip)
        except socket.gaierror:
            raise se.InvalidIpAddress(ip)
    if not port:
        raise se.InvalidParameterException("Port", port)

    return (ip, port, username, password)
Ejemplo n.º 4
0
def ddWatchCopy(src, dst, stop, size, offset=0, recoveryCallback=None):
    """
    Copy src to dst using dd command with stop abilities
    """
    try:
        size = int(size)
    except ValueError:
        raise se.InvalidParameterException("size", "size = %s" % (size,))
    try:
        offset = int(offset)
    except ValueError:
        raise se.InvalidParameterException("offset", "offset = %s" % (offset,))

    left = size
    baseoffset = offset

    while left > 0:
        (iounit, count, iooffset) = _alignData(left, offset)
        oflag = None
        conv = "notrunc"
        if (iounit % 512) == 0:
            if fileUtils.pathRequiresFlagForDirectIO(dst):
                oflag = DIRECTFLAG
        else:
            conv += ",%s" % DATASYNCFLAG

        cmd = [constants.EXT_DD, "if=%s" % src, "of=%s" % dst,
               "bs=%d" % iounit, "seek=%s" % iooffset, "skip=%s" % iooffset,
               "conv=%s" % conv, 'count=%s' % count]

        if oflag:
            cmd.append("oflag=%s" % oflag)

        if not stop:
            (rc, out, err) = execCmd(cmd, sudo=False, nice=utils.NICENESS.HIGH,
                                     ioclass=utils.IOCLASS.IDLE)
        else:
            (rc, out, err) = watchCmd(cmd, stop=stop,
                                      recoveryCallback=recoveryCallback,
                                      nice=utils.NICENESS.HIGH,
                                      ioclass=utils.IOCLASS.IDLE)

        if rc:
            raise se.MiscBlockWriteException(dst, offset, size)

        if not validateDDBytes(err, iounit * count):
            raise se.MiscBlockWriteIncomplete(dst, offset, size)

        left = left % iounit
        offset = baseoffset + size - left

    return (rc, out, err)
Ejemplo n.º 5
0
 def __init__(self, repoPath, sdUUID, imgUUID, volUUID):
     self.repoPath = repoPath
     self.sdUUID = sdUUID
     self.imgUUID = imgUUID
     self.volUUID = volUUID
     self.volumePath = None
     self.imagePath = None
     if not imgUUID or imgUUID == BLANK_UUID:
         raise se.InvalidParameterException("imgUUID", imgUUID)
     if not volUUID or volUUID == BLANK_UUID:
         raise se.InvalidParameterException("volUUID", volUUID)
     self.voltype = None
     self.validate()
Ejemplo n.º 6
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, )
Ejemplo n.º 7
0
def validateDDBytes(ddstderr, size):
    log.debug("err: %s, size: %s" % (ddstderr, size))
    try:
        size = int(size)
    except (ValueError, ):
        raise se.InvalidParameterException("size", str(size))

    if len(ddstderr) != 3:
        raise se.InvalidParameterException("len(ddstderr)", ddstderr)

    try:
        xferred = int(ddstderr[2].split()[0])
    except (ValueError, ):
        raise se.InvalidParameterException("ddstderr", ddstderr[2])

    if xferred != size:
        return False
    return True
Ejemplo n.º 8
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)

        mysd = sdCache.produce(sdUUID=sdUUID)
        try:
            lvm.getLV(sdUUID, volUUID)
        except se.LogicalVolumeDoesNotExistError:
            pass  #OK, this is a new volume
        else:
            raise se.VolumeAlreadyExists(volUUID)

        imageDir = image.Image(repoPath).create(sdUUID, imgUUID)
        vol_path = os.path.join(imageDir, volUUID)
        pvol = None
        voltype = "LEAF"

        try:
            if srcVolUUID != volume.BLANK_UUID:
                # We have a parent
                if srcImgUUID == volume.BLANK_UUID:
                    srcImgUUID = imgUUID
                pvol = BlockVolume(repoPath, sdUUID, srcImgUUID, srcVolUUID)
                # Cannot create snapshot for ILLEGAL volume
                if not pvol.isLegal():
                    raise se.createIllegalVolumeSnapshotError(pvol.volUUID)

                if imgUUID != srcImgUUID:
                    pvol.share(imageDir, hard=False)
                    pvol = BlockVolume(repoPath, sdUUID, imgUUID, srcVolUUID)

                # override size param by parent's size
                size = pvol.getSize()
        except se.StorageException:
            cls.log.error("Unexpected error", exc_info=True)
            raise
        except Exception, e:
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeCannotGetParent(
                "blockVolume can't get parent %s for volume %s: %s" %
                (srcVolUUID, volUUID, str(e)))
Ejemplo n.º 9
0
def validateUUID(uuid, name="uuid"):
    """
    Ensure that uuid structure is 32 bytes long and is of the form: 8-4-4-4-12 (where each number depicts the amount of hex digits)

    Even though UUIDs can contain capital letters (because HEX strings are case insensitive) we usually compare uuids with the `==`
    operator, having uuids with upper case letters will cause unexpected bug so we filter them out
    """
    m = UUID_REGEX.match(uuid)
    if m is None:
        raise se.InvalidParameterException(name, uuid)
    return True
Ejemplo n.º 10
0
def validateUUID(uuid, name="uuid", blank=True):
    """
    Ensure that uuid structure is 32 bytes long and is of the form: 8-4-4-4-12
    (where each number depicts the amount of hex digits)

    Even though UUIDs can contain capital letters (because HEX strings are case
    insensitive) we usually compare uuids with the `==` operator, having uuids
    with upper case letters will cause unexpected bug so we filter them out.
    The blank argument specifies if it's allowed for the uuid to be blank or
    not.
    """
    try:
        m = UUID_REGEX.match(uuid)
    except TypeError:
        raise se.InvalidParameterException(name, uuid)

    if m is None:
        raise se.InvalidParameterException(name, uuid)

    if not blank and uuid == UUID_BLANK:
        raise se.InvalidParameterException(name, uuid)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
def validateSize(size, name):
    """
    Validate number of bytes as string and convert to number of sectors,
    rounding up to next sectors.

    Raises InvalidParameterException if value is not a string or if it could
    not be converted to integer.
    """
    if not isinstance(size, basestring):
        log.error("Number of sectors as int is not supported, use size in "
                  "bytes as string")
        raise se.InvalidParameterException("size", size)
    size = validateN(size, name)
    return (size + SECTOR_SIZE - 1) / SECTOR_SIZE
Ejemplo n.º 13
0
    def connect(self, domType, conList):
        """
        Connect to a storage low level entity (server).
        """
        self.log.info("Request to connect %s storage server",
                      sd.type2name(domType))
        conParams = self.__validateConnectionParams(domType, conList)

        if domType == sd.NFS_DOMAIN:
            return self.__connectFileServer(conParams, fileUtils.FSTYPE_NFS)
        elif domType == sd.LOCALFS_DOMAIN:
            return self.__connectLocalConnection(conParams)
        elif domType in sd.BLOCK_DOMAIN_TYPES:
            return self.__connectiSCSIServer(conParams)
        else:
            raise se.InvalidParameterException("type", domType)
Ejemplo n.º 14
0
    def validate(self, domType, conList):
        """
        Validate that we can connect to a storage server.
        """
        self.log.info("Request to validate %s storage server",
                      sd.type2name(domType))
        conParams = self.__validateConnectionParams(domType, conList)

        if domType == sd.NFS_DOMAIN:
            return self.__validateFileServer(conParams, fileUtils.FSTYPE_NFS)
        elif domType == sd.LOCALFS_DOMAIN:
            return self.__validateLocalConnection(conParams)
        elif domType in sd.BLOCK_DOMAIN_TYPES:
            return self.__validateiSCSIConnection(conParams)
        else:
            raise se.InvalidParameterException("type", domType)
Ejemplo n.º 15
0
def validateN(number, name):
    n = validateInt(number, name)
    if n < 0:
        raise se.InvalidParameterException(name, number)
    return n
Ejemplo n.º 16
0
 def validateID(cls, taskID):
     if not taskID or "." in taskID:
         raise se.InvalidParameterException("taskID", taskID)
Ejemplo n.º 17
0
def validateInt(number, name):
    try:
        return int(number)
    except:
        raise se.InvalidParameterException(name, number)
Ejemplo n.º 18
0
def validateInt(number, name):  #FIXME: Consider using confutils validator?
    try:
        return int(number)
    except:
        raise se.InvalidParameterException(name, number)