Add SpaceClaim object
We need to "transfer" non numeric sizes from deployment config to deployment driver. Now we have only one such "size" - this is "ramaining" constant. Also this object knows(will know), how to pass this claim to the storage object. Change-Id: I1956a0fcf60bfa5c0c3eda7ecb7c3dda176880ca
This commit is contained in:
parent
9abb3c5d80
commit
31486e41d4
|
@ -95,6 +95,22 @@ class TestDeviceFinder(unittest2.TestCase):
|
||||||
errors.BlockDeviceNotFoundError, finder, kind, needle)
|
errors.BlockDeviceNotFoundError, finder, kind, needle)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSpaceClaim(unittest2.TestCase):
|
||||||
|
def test_percentage(self):
|
||||||
|
claim = block_device.SpaceClaim.new_by_sizeunit(
|
||||||
|
block_device.SizeUnit.new_by_string('20 %'))
|
||||||
|
self.assertEqual(
|
||||||
|
(block_device.SpaceClaim.KIND_PERCENTAGE, (20, '%')),
|
||||||
|
(claim.kind, (claim.size.value, claim.size.unit)))
|
||||||
|
|
||||||
|
def test_exact(self):
|
||||||
|
claim = block_device.SpaceClaim.new_by_sizeunit(
|
||||||
|
block_device.SizeUnit.new_by_string('100 MiB'))
|
||||||
|
self.assertEqual(
|
||||||
|
(block_device.SpaceClaim.KIND_EXACT, (100, 'MiB')),
|
||||||
|
(claim.kind, (claim.size.value, claim.size.unit)))
|
||||||
|
|
||||||
|
|
||||||
class TestSizeUnit(unittest2.TestCase):
|
class TestSizeUnit(unittest2.TestCase):
|
||||||
def test_all_suffixes(self):
|
def test_all_suffixes(self):
|
||||||
for value, suffix, expect in (
|
for value, suffix, expect in (
|
||||||
|
|
|
@ -94,11 +94,65 @@ class DeviceFinder(object):
|
||||||
return end
|
return end
|
||||||
|
|
||||||
|
|
||||||
class SizeUnit(object):
|
# TODO(dbogun): this object can/should be removed
|
||||||
|
# The only reason why it exists - to keep "remaining" size. All other kinds can
|
||||||
|
# be stored into SizeUnit.
|
||||||
|
class SpaceClaim(utils.EqualComparisonMixin, object):
|
||||||
|
_kind = itertools.count()
|
||||||
|
KIND_EXACT = next(_kind)
|
||||||
|
KIND_PERCENTAGE = next(_kind)
|
||||||
|
KIND_BIGGEST = next(_kind)
|
||||||
|
del _kind
|
||||||
|
|
||||||
|
_kind_names = {
|
||||||
|
KIND_EXACT: 'EXACT',
|
||||||
|
KIND_PERCENTAGE: 'PERCENTAGE',
|
||||||
|
KIND_BIGGEST: 'REMAINING'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_biggest(cls):
|
||||||
|
return cls(None, cls.KIND_BIGGEST)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_by_sizeunit(cls, size):
|
||||||
|
if size.unit == '%':
|
||||||
|
return cls.new_percent(size)
|
||||||
|
return cls.new_exact(size)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_percent(cls, value):
|
||||||
|
if not isinstance(value, SizeUnit):
|
||||||
|
value = SizeUnit.new_by_string('{} %'.format(value))
|
||||||
|
if value.unit != '%':
|
||||||
|
raise TypeError('Unsuitable value for percentage space claim: '
|
||||||
|
'{!r}'.format(value))
|
||||||
|
return cls(value, cls.KIND_PERCENTAGE)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_exact(cls, value):
|
||||||
|
if not isinstance(value, SizeUnit):
|
||||||
|
value = SizeUnit.new_by_string('{} B'.format(value))
|
||||||
|
if value.bytes is None:
|
||||||
|
raise TypeError('Unsuitable value for exact space claim: '
|
||||||
|
'{!r}'.format(value))
|
||||||
|
return cls(value, cls.KIND_EXACT)
|
||||||
|
|
||||||
|
def __init__(self, size, kind):
|
||||||
|
self.size = size
|
||||||
|
self.kind = kind
|
||||||
|
|
||||||
|
def __call__(self, storage, from_tail=False):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<{} {}:{!r}>'.format(
|
||||||
|
type(self).__name__, self._kind_names[self.kind], self.size)
|
||||||
|
|
||||||
|
|
||||||
|
class SizeUnit(utils.EqualComparisonMixin, object):
|
||||||
bytes = None
|
bytes = None
|
||||||
|
|
||||||
_unit_multiplier = {
|
_unit_multiplier = {
|
||||||
'max': None,
|
|
||||||
'%': None,
|
'%': None,
|
||||||
's': 512,
|
's': 512,
|
||||||
'B': 1
|
'B': 1
|
||||||
|
@ -183,6 +237,12 @@ class SizeUnit(object):
|
||||||
if multiplier is not None:
|
if multiplier is not None:
|
||||||
self.bytes = int(value * multiplier)
|
self.bytes = int(value * multiplier)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
value = str(self)
|
||||||
|
if self.bytes is not None and self.unit != 'B':
|
||||||
|
value = '{} == {} B'.format(value, self.bytes)
|
||||||
|
return '<{}: {}>'.format(type(self).__name__, value)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.value == self.value_int:
|
if self.value == self.value_int:
|
||||||
value = self.value_int
|
value = self.value_int
|
||||||
|
@ -219,6 +279,18 @@ class SizeUnit(object):
|
||||||
'Illegal input for {}.value field: {!r}'.format(cls, value))
|
'Illegal input for {}.value field: {!r}'.format(cls, value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _comparable_shape(cls, target):
|
||||||
|
value = super(SizeUnit, cls)._comparable_shape(target)
|
||||||
|
if target.bytes is not None:
|
||||||
|
fields = ('bytes', )
|
||||||
|
else:
|
||||||
|
fields = ('value', 'value_int', 'unit')
|
||||||
|
value['payload'] = {
|
||||||
|
k: v for k, v in value['payload'].items()
|
||||||
|
if k in fields}
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class BlockDevicePayload(object):
|
class BlockDevicePayload(object):
|
||||||
def __init__(self, block, guid=None):
|
def __init__(self, block, guid=None):
|
||||||
|
|
|
@ -517,3 +517,19 @@ def list_opts():
|
||||||
:returns: a list of (group_name, opts) tuples
|
:returns: a list of (group_name, opts) tuples
|
||||||
"""
|
"""
|
||||||
return [(None, (u_opts))]
|
return [(None, (u_opts))]
|
||||||
|
|
||||||
|
|
||||||
|
class EqualComparisonMixin(object):
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, type(self)):
|
||||||
|
return NotImplemented
|
||||||
|
return self._comparable_shape(self) == other._comparable_shape(other)
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _comparable_shape(cls, target):
|
||||||
|
return {
|
||||||
|
'cls': cls,
|
||||||
|
'payload': vars(target)}
|
||||||
|
|
Loading…
Reference in New Issue