Esempio n. 1
0
def decimal_valid(edit_field, disk_win=None):
    '''Check text to see if it is a decimal number of precision no
    greater than the tenths place.
    
    '''
    text = edit_field.get_text().lstrip()
    if text.endswith(" "):
        raise UIMessage(_('Only the digits 0-9 and "." are valid.'))
    vals = text.split(".")
    if len(vals) > 2:
        raise UIMessage(_('A number can only have one "."'))
    try:
        if len(vals[0]) > 0:
            int(vals[0])
        if len(vals) > 1 and len(vals[1]) > 0:
            int(vals[1])
    except ValueError:
        raise UIMessage(_('Only the digits 0-9 and "." are valid.'))
    if len(vals) > 1 and len(vals[1]) > 1:
        raise UIMessage(_("Size can be specified to only one decimal place."))
    if disk_win is not None:
        text = text.rstrip(".")
        if not text:
            text = "0"
        new_size = DiskSpace(text + "gb")
        max_size = edit_field.data_obj.get_max_size(disk_win.disk_info)

        # When comparing sizes, check only to the first decimal place,
        # as that is all the user sees. (Rounding errors that could
        # cause the partition/slice layout to be invalid get cleaned up
        # prior to target instantiation)
        new_size_rounded = round(new_size.size_as("gb"), 1)
        max_size_rounded = round(max_size, 1)
        if new_size_rounded > max_size_rounded:
            raise UIMessage(
                _("The new size (%(size).1f) is greater than "
                  "the available space (%(avail).1f)") % {
                      "size": new_size_rounded,
                      "avail": max_size_rounded
                  })
        size_diff = abs(new_size.size_as("gb") - edit_field.data_obj.orig_size)
        if size_diff > DiskWindow.SIZE_PRECISION:
            edit_field.data_obj.size = new_size
            edit_field.data_obj.adjust_offset(disk_win.disk_info)
        else:
            edit_field.data_obj.size = "%fgb" % edit_field.data_obj.orig_size
        disk_win.update_avail_space()
        disk_win.no_ut_refresh()
        part_field = disk_win.find_part_field(edit_field.data_obj)[1]
        disk_win.mark_if_destroyed(part_field)
    return True
Esempio n. 2
0
def get_recommended_size():
    '''Returns the recommended size for the installation, in GB'''
    if DiskWindow.REC_SIZE is None:
        try:
            swap_dump = SwapDump()
            rec_size = str(get_rec_install_size(swap_dump)) + "mb"
            DiskWindow.REC_SIZE = DiskSpace(rec_size)
            rec_size = DiskWindow.REC_SIZE.size_as("gb")
            rec_size = round_to_multiple(rec_size, 0.1)
            DiskWindow.REC_SIZE.size = "%sgb" % rec_size
        except (InstallationError):
            logging.warn("Unable to determine recommended install size")
            DiskWindow.REC_SIZE = DiskSpace("10gb")
    return DiskWindow.REC_SIZE
Esempio n. 3
0
 def set_size(self, size):
     '''Set this disk's size. size must be either a DiskSpace or a string
     that will be accepted by DiskSpace.__init__
     
     '''
     if isinstance(size, DiskSpace):
         self._size = deepcopy(size)
     else:
         self._size = DiskSpace(size)
Esempio n. 4
0
 def get_endblock(self):
     '''Returns the ending 'offset' of this partition, as a DiskSpace'''
     try:
         start_pt = self.offset.size_as("b")
         end_pt = self.size.size_as("b")
         return DiskSpace(str(start_pt + end_pt) + "b")
     except AttributeError:
         raise AttributeError("%s does not have valid size data" %
                              self.__class__.__name__)
Esempio n. 5
0
 def set_offset(self, offset):
     '''Set this partition's offset. Must be either a DiskSpace object
     or a string that will be accepted by DiskSpace.__init__
     
     '''
     if isinstance(offset, DiskSpace):
         self._offset = deepcopy(offset)
     else:
         self._offset = DiskSpace(offset)
Esempio n. 6
0
def get_minimum_size():
    '''Returns the minimum disk space needed for installation, in GB. The
    value returned from get_min_install_size is rounded up to the nearest
    tenth of a gigabyte, so that the UI ensures enough space is allocated,
    given that the UI only allows for precision to tenths of a gigabyte.
    
    '''
    if DiskWindow.MIN_SIZE is None:
        try:
            swap_dump = SwapDump()
            min_size = str(get_min_install_size(swap_dump)) + "mb"
            DiskWindow.MIN_SIZE = DiskSpace(min_size)
            min_size = DiskWindow.MIN_SIZE.size_as("gb")
            min_size = round_to_multiple(min_size, 0.1)
            DiskWindow.MIN_SIZE.size = "%sgb" % min_size
        except (InstallationError):
            logging.warn("Unable to determine minimum install size")
            DiskWindow.MIN_SIZE = DiskSpace("6gb")
    return DiskWindow.MIN_SIZE
Esempio n. 7
0
    def modified(self, off_by=UI_PRECISION):
        '''Returns False if and only if this SliceInfo was instantiated from
        a tgt.Slice, and this SliceInfo does not differ in substance
        from the tgt.Slice from which it was instantiated.
        
        Size, offset, type and number are compared to determine
        whether this slice has been modified.
        
        off_by - A string or DiskSpace indicating a rounding factor. Any size
        data (offset, size) that differs by less than the given amount is
        assumed to be unchanged. e.g., if the tgt.Slice indicates a size
        of 10.05GB and this SliceInfo has a size of 10.1GB, and off_by
        is the default of 0.1GB, then it is assumed that the represented
        slice has not changed. (The original tgt.Slice size should be
        used, for accuracy)
        
        '''
        if self._tgt_slice is None:
            return True

        if not isinstance(off_by, DiskSpace):
            off_by = DiskSpace(off_by)
        off_by_bytes = off_by.size_as("b")

        if self.number != self._tgt_slice.number:
            return True

        if self.type[0] != self._tgt_slice.type:
            return True

        if self.type[1] != self._tgt_slice.user:
            return True

        tgt_size = self._tgt_slice.blocks * self._tgt_slice.geometry.blocksz
        if abs(tgt_size - self.size.size_as("b")) > off_by_bytes:
            return True

        tgt_offset = self._tgt_slice.offset * self._tgt_slice.geometry.blocksz
        if abs(tgt_offset - self.offset.size_as("b")) > off_by_bytes:
            return True

        return False
Esempio n. 8
0
def get_image_size():
    '''Total size of the software in the image is stored in the 
       /.cdrom/.image_info indicated by the keywoard IMAGE_SIZE.
       This function retrieves that value from the .image_file
       The size recorded in the .image_file is in KB, other functions
       in this file uses the value in MB, so, this function will
       return the size in MB

       Returns:
           size of retrieved from the .image_info file in MB

    '''
    img_size = 0
    try:
        with open(IMAGE_INFO, 'r') as ih:
            for line in ih:
                (opt, val) = line.split("=")
                if opt == IMAGE_SIZE_KEYWORD:
                    # Remove the '\n' character read from
                    # the file, and convert to integer
                    img_size = int(val.rstrip('\n'))
                    break
    except IOError as ioe:
        logging.error("Failed to access %s", IMAGE_INFO)
        logging.exception(ioe)
        raise InstallationError
    except ValueError as ive:
        logging.error("Invalid file format in %s", IMAGE_INFO)
        logging.exception(ive)
        raise InstallationError

    if (img_size == 0):
        # We should have read in a size by now
        logging.error("Unable to read the image size from %s", IMAGE_INFO)
        raise InstallationError

    return (DiskSpace(str(img_size) + "kb").size_as("mb"))
       just indicates that something is wrong

    '''
    pass


class NotEnoughSpaceError(Exception):
    '''There's not enough space in the target disk for successful installation

    '''
    pass


# All sizes are in MB
MIN_SWAP_SIZE = 512
MAX_SWAP_SIZE = DiskSpace("32gb").size_as("mb")  #32G
MIN_DUMP_SIZE = 256
MAX_DUMP_SIZE = DiskSpace("16gb").size_as("mb")  #16G
OVERHEAD = 1024
FUTURE_UPGRADE_SPACE = DiskSpace("2gb").size_as("mb")  #2G
ZVOL_REQ_MEM = 900  # Swap ZVOL is required if memory is below this


class SwapDump:
    ''' All information associated with swap and dump'''
    ''' The type of swap/dump.  Define them as strings so debugging output
        is easier to read.
    '''
    SLICE = "Slice"
    ZVOL = "ZVOL"
    NONE = "None"
Esempio n. 10
0
'''
Object to represent Partitions
'''

from copy import copy, deepcopy
from functools import cmp_to_key
import logging

import osol_install.tgt as tgt
from osol_install.profile.disk_space import DiskSpace, round_to_multiple, \
                                            round_down
from osol_install.profile.slice_info import SliceInfo, UI_PRECISION

# Minimum space between partitions before presenting it as 'unused' space
# Used by PartitionInfo.add_unused_parts()
MIN_GAP_SIZE = DiskSpace("1gb")

# Minimum space between logical partitions before presenting it as
# 'unused' space. Used by DiskInfo.add_unused_parts()
MIN_LOGICAL_GAP_SIZE = DiskSpace("100mb")


# Pylint gets confused and thinks PartitionInfo.size and PartitionInfo.offset
# are strings, but they are actually DiskSpace objects
# pylint: disable-msg=E1103
class PartitionInfo(object):
    '''Represents a single partition on a disk on the system.
    
    EDITABLE_PART_TYPES is a list of primary partition types for which
    modifying the size is supported.
    
Esempio n. 11
0
class SliceInfo(object):
    '''Represents a single slice on a partition or slice.'''
    MAX_SLICES = 8
    MAX_VTOC = DiskSpace("2tb")

    BACKUP_SLICE = 2
    x86_BOOT_SLICE = 8
    x86_ALT_SLICE = 9
    UNUSED = (None, None)
    UNUSED_TEXT = "Unused"
    DEFAULT_POOL = UserString("")
    ZPOOL = tgt.Slice.AZPOOL
    ZPOOL_TYPES = [
        tgt.Slice.AZPOOL, tgt.Slice.EZPOOL, tgt.Slice.SZPOOL, tgt.Slice.CZPOOL
    ]
    ROOT_POOL = (ZPOOL, DEFAULT_POOL)
    LEGACY = "legacy"
    UFS = tgt.Slice.FS
    UFS_TEXT = "UFS"
    UNKNOWN = "???"

    TYPES = [UNUSED, ROOT_POOL]

    def __init__(self,
                 slice_num=0,
                 size=None,
                 offset=None,
                 blocksz=512,
                 slice_type=None,
                 readonly=False,
                 unmountable=True,
                 tag=None,
                 tgt_slice=None):
        '''Constructor takes either a tgt_slice, which should be a tgt.Slice
        object, or a set of parameters. If tgt_slice is supplied, all other
        parameters are ignored.
        
        '''
        self._tgt_slice = tgt_slice
        self._size = None
        self._offset = None
        self.previous_size = None
        if tgt_slice:
            size = str(tgt_slice.blocks * tgt_slice.geometry.blocksz) + "b"
            self.size = size
            offset = str(tgt_slice.offset * tgt_slice.geometry.blocksz) + "b"
            self.blocksz = tgt_slice.geometry.blocksz
            self.offset = offset
            self.number = tgt_slice.number
            self.readonly = tgt_slice.readonly
            self.type = (tgt_slice.type, tgt_slice.user)
            self.last_mount = tgt_slice.last_mount
            self.unmountable = tgt_slice.unmountable
            self.tag = tgt_slice.tag
        else:
            self.readonly = readonly
            if slice_type is None:
                slice_type = SliceInfo.UNUSED
            if len(slice_type) != 2:
                raise TypeError("slice_type must be tuple of length 2")
            self.type = slice_type
            self.unmountable = unmountable
            self.size = size
            self.blocksz = blocksz
            self.offset = offset
            self.number = slice_num
            self.last_mount = None
            self.tag = tag
        self.original_type = self.type

    def __str__(self):
        result = ["Slice Info (%s):" % self.number]
        result.append("Type: %s:%s" % self.type)
        result.append("Offset: %s" % self.offset)
        result.append("Size: %s" % self.size)
        return "\n".join(result)

    @staticmethod
    def compare(left, right):
        '''Returns an integer such that this method can be passed to
        list.sort() and the list will be sorted in disk layout order.
        
        The backup slice is always listed last
        
        '''
        if isinstance(left, tgt.Slice):
            left = SliceInfo(left)
        if not isinstance(left, SliceInfo):
            return NotImplemented

        if isinstance(right, tgt.Slice):
            right = SliceInfo(right)
        if not isinstance(right, SliceInfo):
            return NotImplemented

        if left.number == SliceInfo.BACKUP_SLICE:
            return 1
        elif right.number == SliceInfo.BACKUP_SLICE:
            return -1

        left_off = left.offset.size_as("b")
        right_off = right.offset.size_as("b")
        if left_off < right_off:
            return -1
        elif left_off > right_off:
            return 1
        else:
            return 0

    def get_offset(self):
        '''Return this slice's offset as a DiskSpace object'''
        return self._offset

    def set_offset(self, offset):
        '''Set this slice's offset. Must be either a DiskSpace object
        or a string that will be accepted by DiskSpace.__init__
        
        '''
        if isinstance(offset, DiskSpace):
            self._offset = deepcopy(offset)
        else:
            self._offset = DiskSpace(offset)

    def get_size(self):
        '''Returns this slice's size as a DiskSpace object'''
        return self._size

    def set_size(self, size):
        '''Set this slice's size. size must be either a DiskSpace or a
        string that will be accepted by DiskSpace.__init__
        
        '''
        if isinstance(size, DiskSpace):
            self._size = deepcopy(size)
        else:
            self._size = DiskSpace(size)

    def get_type(self):
        '''Returns this SliceInfo's 'type'
        Here for interface compatibility with PartitionInfo.get_type()'''
        return self.type

    def get_blocks(self):
        '''Return the number of blocks on this slice'''
        return int(self.size.size_as("b") / self.blocksz)

    size = property(get_size, set_size)
    offset = property(get_offset, set_offset)

    def get_description(self):
        '''Return a string suitable for representing this slice in a UI'''
        description = None
        if self.number == SliceInfo.BACKUP_SLICE:
            description = tgt.Slice.BACKUP
        elif self.type == SliceInfo.UNUSED:
            description = SliceInfo.UNUSED_TEXT
        elif self.type[0] == SliceInfo.UFS:
            if self.last_mount:
                description = self.last_mount
            else:
                description = SliceInfo.UFS_TEXT
        elif self.type[0] == tgt.Slice.UNKNOWN:
            if self.tag == tgt.Slice.UNKNOWN:
                description = SliceInfo.UNKNOWN
            else:
                description = self.tag
        elif self.type[1] and self.type[1] != tgt.Slice.UNKNOWN:
            description = self.type[1]
        else:
            description = self.type[0]
        return str(description)

    def cycle_type(self, parent, extra_types=None):
        '''Cycle this partition's type. If extra_types is given, it should
        be a list of additional types - these will be considered when cycling
        to the next type
        
        '''
        if extra_types is None:
            extra_types = []
        if self.number == SliceInfo.BACKUP_SLICE:
            return

        has_solaris_data = (parent.get_solaris_data() is not None)
        types = set()
        types.update(SliceInfo.TYPES)
        types.update(extra_types)
        types = list(types)
        types.sort()
        if self.type in types:
            logging.debug("type in types, cycling next")
            type_index = types.index(self.type)
            type_index = (type_index + 1) % len(types)
            self.type = types[type_index]
            logging.debug("now %s-%s", *self.type)
        else:
            logging.debug("type NOT in types, setting to types[0]")
            self.original_type = self.type
            self.type = types[0]
        if self.type == SliceInfo.UNUSED:
            self.previous_size = self.size
            self.size = "0GB"
        elif self.is_rpool():
            if has_solaris_data:
                self.cycle_type(parent, extra_types)

    def get_endblock(self):
        '''Returns the ending 'offset' of this slice, as a DiskSpace'''
        try:
            start_pt = self.offset.size_as("b")
            end_pt = self.size.size_as("b")
            return DiskSpace(str(start_pt + end_pt) + "b")
        except AttributeError:
            raise AttributeError("%s does not have valid size data" %
                                 self.__class__.__name__)

    def get_max_size(self, parent):
        '''Return the maximum possible size this slice could consume,
        in gigabytes, based on adjacent unused space
        
        '''
        if self.number == SliceInfo.BACKUP_SLICE:
            return self.size.size_as("gb")
        msg_str = "get_max_size:%s:" % self.number
        slices = parent.slices
        if self not in slices:
            raise ValueError("This slice not in the parent!")
        self_idx = slices.index(self)
        prev_slice = None
        next_slice = None

        # Search for the slice prior to this one with the largest "endblock"
        # Since existing slices may overlap, this could be any slice prior
        # to the current one.
        for slice_info in reversed(slices[:self_idx]):
            if (slice_info.type != SliceInfo.UNUSED
                    and slice_info.number != SliceInfo.BACKUP_SLICE):
                if (prev_slice is None or
                        slice_info.get_endblock() > prev_slice.get_endblock()):
                    prev_slice = slice_info
        for slice_info in slices[self_idx + 1:]:
            if (slice_info.type != SliceInfo.UNUSED
                    and slice_info.number != SliceInfo.BACKUP_SLICE):
                next_slice = slice_info
                break
        if prev_slice is None:
            msg_str += "prev_part=None:start_pt=0:"
            start_pt = 0
        else:
            msg_str += "prev_part=%s:" % prev_slice.number
            start_pt = prev_slice.get_endblock().size_as("gb")
            msg_str += "start_pt=" + str(start_pt) + ":"

        if next_slice is None:
            msg_str += "next_part=None:end_pt="
            for slice_info in reversed(slices):
                # Use the backup slice to define the absolute max size
                # any given slice can be. (This is usually the last slice,
                # hence the use of a reversed iterator)
                if slice_info.number == SliceInfo.BACKUP_SLICE:
                    end_pt = slice_info.size.size_as("gb")
                    break
            else:
                # Default to the parent's size if there happens to be no S2
                end_pt = parent.size.size_as("gb")
            msg_str += str(end_pt) + ":"
        else:
            msg_str += "next_part=%s:" % next_slice.number
            end_pt = next_slice.offset.size_as("gb")
            msg_str += "end_pt=%s:" % end_pt
        max_space = end_pt - start_pt
        if max_space < 0:
            max_space = 0
        msg_str += "max_size=%s" % max_space
        logging.debug(msg_str)
        return max_space

    def editable(self, dummy):
        '''Returns True if the installer is capable of resizing this Slice'''
        return self.is_rpool()

    def adjust_offset(self, parent):
        '''Adjust this slice's offset such that it no longer overlaps
        with prior or subsequent slices, by comparing this slice's 
        offset with prior slices, and its endblock with subsequent ones.
        
        Additionally, any unused slices found are shifted to align
        with this slice's trailing edge, if needed.
        
        This function should only be called after ensuring that this slice's
        size is less than or equal its max_size (as given by get_max_size);
        the behavior of this function when attempting to adjust in both
        directions is undefined. Additionally, the slices on the parent
        should already be sorted in disk order.
        
        '''
        if self.number == SliceInfo.BACKUP_SLICE:
            return
        parts = parent.get_parts()
        self_idx = parts.index(self)
        endblock = self.get_endblock()
        endblock_bytes = endblock.size_as("gb")
        unused_parts = []

        pre_shift = 0
        for part in parts[:self_idx]:
            if (part.type == SliceInfo.UNUSED
                    or part.number == SliceInfo.BACKUP_SLICE):
                continue
            overlap = (part.get_endblock().size_as("gb") -
                       self.offset.size_as("gb"))
            pre_shift = max(pre_shift, overlap)

        if pre_shift > 0:
            new_offset = self.offset.size_as("gb") + pre_shift
            self.offset = str(new_offset) + "gb"

        post_shift = None
        for part in parts[self_idx + 1:]:
            if part.offset.size_as("gb") < endblock_bytes:
                if part.type == SliceInfo.UNUSED:
                    unused_parts.append(part)
                elif part.number != SliceInfo.BACKUP_SLICE:
                    post_shift = endblock_bytes - part.offset.size_as("gb")
                    break
            else:
                break
        else:
            # Check to ensure we don't slip past the end of the disk/partition
            max_endblock = parent.size.size_as("gb")
            if endblock_bytes > max_endblock:
                post_shift = endblock_bytes - max_endblock

        if post_shift is not None:
            new_offset = max(0, self.offset.size_as("gb") - post_shift)
            self.offset = str(new_offset) + "gb"
        new_endblock = self.get_endblock()
        for part in unused_parts:
            part.offset = new_endblock

    def to_tgt(self, parent):
        '''Transfer the install profile information to tgt format'''
        # Create tgt.Slice object

        if self.get_type() == SliceInfo.UNUSED:
            return None

        if not self.modified():
            return self._tgt_slice

        # Don't need to include the 'backup' slice, libti will
        # automatically create one appropriately
        if self.number == SliceInfo.BACKUP_SLICE:
            return None

        # Something changed, need to create a new one
        geo = tgt.Geometry(parent.cylsz, self.blocksz)

        # offset must be a multiple of tgt.Geometry.cylsz
        off = int(self.offset.size_as("b") / self.blocksz)
        offset = round_to_multiple(off, geo.cylsz)

        blocks = round_to_multiple(self.get_blocks(), geo.cylsz)

        tag = tgt.Slice.UNASSIGNED
        slice_type = self.type[0]
        user = self.type[1]
        sl = tgt.Slice(geo,
                       self.number,
                       tag,
                       slice_type,
                       offset,
                       blocks,
                       modified=True,
                       user=str(user),
                       unmountable=self.unmountable,
                       readonly=self.readonly)
        return (sl)

    def modified(self, off_by=UI_PRECISION):
        '''Returns False if and only if this SliceInfo was instantiated from
        a tgt.Slice, and this SliceInfo does not differ in substance
        from the tgt.Slice from which it was instantiated.
        
        Size, offset, type and number are compared to determine
        whether this slice has been modified.
        
        off_by - A string or DiskSpace indicating a rounding factor. Any size
        data (offset, size) that differs by less than the given amount is
        assumed to be unchanged. e.g., if the tgt.Slice indicates a size
        of 10.05GB and this SliceInfo has a size of 10.1GB, and off_by
        is the default of 0.1GB, then it is assumed that the represented
        slice has not changed. (The original tgt.Slice size should be
        used, for accuracy)
        
        '''
        if self._tgt_slice is None:
            return True

        if not isinstance(off_by, DiskSpace):
            off_by = DiskSpace(off_by)
        off_by_bytes = off_by.size_as("b")

        if self.number != self._tgt_slice.number:
            return True

        if self.type[0] != self._tgt_slice.type:
            return True

        if self.type[1] != self._tgt_slice.user:
            return True

        tgt_size = self._tgt_slice.blocks * self._tgt_slice.geometry.blocksz
        if abs(tgt_size - self.size.size_as("b")) > off_by_bytes:
            return True

        tgt_offset = self._tgt_slice.offset * self._tgt_slice.geometry.blocksz
        if abs(tgt_offset - self.offset.size_as("b")) > off_by_bytes:
            return True

        return False

    def destroyed(self, off_by=UI_PRECISION):
        '''Returns True if this slice previously had data, and has also
        been modified.
        
        '''
        if self.is_rpool():
            return True
        return (self._tgt_slice is not None and self.modified(off_by))

    def is_rpool(self):
        '''Returns True this slice is the default pool
        
        '''
        return (self.type[0] in SliceInfo.ZPOOL_TYPES
                and self.type[1] == SliceInfo.DEFAULT_POOL)

    def is_solaris_data(self):
        return self.is_rpool()
Esempio n. 12
0
#
# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
'''
Object to represent Slices
'''

from copy import deepcopy
from collections import UserString
import logging

import osol_install.tgt as tgt
from osol_install.profile.disk_space import DiskSpace, round_to_multiple

UI_PRECISION = DiskSpace("0.05gb")


# Pylint gets confused and thinks SliceInfo.size and SliceInfo.offset
# are strings, but they are actually DiskSpace objects
# pylint: disable-msg=E1103
class SliceInfo(object):
    '''Represents a single slice on a partition or slice.'''
    MAX_SLICES = 8
    MAX_VTOC = DiskSpace("2tb")

    BACKUP_SLICE = 2
    x86_BOOT_SLICE = 8
    x86_ALT_SLICE = 9
    UNUSED = (None, None)
    UNUSED_TEXT = "Unused"
Esempio n. 13
0
       just indicates that something is wrong

    '''
    pass


class NotEnoughSpaceError(Exception):
    '''There's not enough space in the target disk for successful installation

    '''
    pass


# All sizes are in MB
MIN_SWAP_SIZE = 512
MAX_SWAP_SIZE = DiskSpace("32gb").size_as("mb")  #32G
MIN_DUMP_SIZE = 256
MAX_DUMP_SIZE = DiskSpace("16gb").size_as("mb")  #16G
OVERHEAD = 1024
FUTURE_UPGRADE_SPACE = DiskSpace("2gb").size_as("mb")  #2G
ZVOL_REQ_MEM = 900  # Swap ZVOL is required if memory is below this


class SwapDump:
    ''' All information associated with swap and dump'''
    ''' The type of swap/dump.  Define them as strings so debugging output
        is easier to read.
    '''
    SLICE = "Slice"
    ZVOL = "ZVOL"
    NONE = "None"