Commit 23d95cff authored by Bernardo Dal Seno's avatar Bernardo Dal Seno

Unit tests for bdev and utils.lvm

Also amended a comment of a tested method.
The tests are for methods introduced in commit 63c73073 (LVM disk creation
uses dedicated PVs).
Signed-off-by: default avatarBernardo Dal Seno <bdalseno@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent 9ef3e121
......@@ -1032,6 +1032,7 @@ python_tests = \
test/py/ganeti.utils.io_unittest-runasroot.py \
test/py/ganeti.utils.io_unittest.py \
test/py/ganeti.utils.log_unittest.py \
test/py/ganeti.utils.lvm_unittest.py \
test/py/ganeti.utils.mlock_unittest.py \
test/py/ganeti.utils.nodesetup_unittest.py \
test/py/ganeti.utils.process_unittest.py \
......
......@@ -542,7 +542,7 @@ class LogicalVolume(BlockDev):
"""Compute the number of PVs needed for an LV (with exclusive storage).
@type size: float
@param size: LV size
@param size: LV size in MiB
@param pvs_info: list of objects.LvmPvInfo, cannot be empty
@rtype: integer
@return: number of PVs needed
......
#!/usr/bin/python
#
# Copyright (C) 2006, 2007, 2010, 2012 Google Inc.
# Copyright (C) 2006, 2007, 2010, 2012, 2013 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -23,13 +23,15 @@
import os
import random
import unittest
from ganeti import bdev
from ganeti import errors
from ganeti import compat
from ganeti import constants
from ganeti import errors
from ganeti import objects
from ganeti import utils
from ganeti import pathutils
import testutils
......@@ -493,5 +495,82 @@ class TestLoadAllowedFileStoragePaths(testutils.GanetiTestCase):
])
class TestExclusiveStoragePvs(unittest.TestCase):
"""Test cases for functions dealing with LVM PV and exclusive storage"""
# Allowance for rounding
_EPS = 1e-4
_MARGIN = constants.PART_MARGIN + constants.PART_RESERVED + _EPS
@staticmethod
def _GenerateRandomPvInfo(rnd, name, vg):
# Granularity is .01 MiB
size = rnd.randint(1024 * 100, 10 * 1024 * 1024 * 100)
if rnd.choice([False, True]):
free = float(rnd.randint(0, size)) / 100.0
else:
free = float(size) / 100.0
size = float(size) / 100.0
attr = "a-"
return objects.LvmPvInfo(name=name, vg_name=vg, size=size, free=free,
attributes=attr)
def testGetStdPvSize(self):
"""Test cases for bdev.LogicalVolume._GetStdPvSize()"""
rnd = random.Random(9517)
for _ in range(0, 50):
# Identical volumes
pvi = self._GenerateRandomPvInfo(rnd, "disk", "myvg")
onesize = bdev.LogicalVolume._GetStdPvSize([pvi])
self.assertTrue(onesize <= pvi.size)
self.assertTrue(onesize > pvi.size * (1 - self._MARGIN))
for length in range(2, 10):
n_size = bdev.LogicalVolume._GetStdPvSize([pvi] * length)
self.assertEqual(onesize, n_size)
# Mixed volumes
for length in range(1, 10):
pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")
for _ in range(0, length)]
std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
self.assertTrue(compat.all(std_size <= pvi.size for pvi in pvlist))
self.assertTrue(compat.any(std_size > pvi.size * (1 - self._MARGIN)
for pvi in pvlist))
pvlist.append(pvlist[0])
p1_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
self.assertEqual(std_size, p1_size)
def testComputeNumPvs(self):
"""Test cases for bdev.LogicalVolume._ComputeNumPvs()"""
rnd = random.Random(8067)
for _ in range(0, 1000):
pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")]
lv_size = float(rnd.randint(10 * 100, 1024 * 1024 * 100)) / 100.0
num_pv = bdev.LogicalVolume._ComputeNumPvs(lv_size, pvlist)
std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
self.assertTrue(num_pv >= 1)
self.assertTrue(num_pv * std_size >= lv_size)
self.assertTrue((num_pv - 1) * std_size < lv_size * (1 + self._EPS))
def testGetEmptyPvNames(self):
"""Test cases for bdev.LogicalVolume._GetEmptyPvNames()"""
rnd = random.Random(21126)
for _ in range(0, 100):
num_pvs = rnd.randint(1, 20)
pvlist = [self._GenerateRandomPvInfo(rnd, "disk%d" % n, "myvg")
for n in range(0, num_pvs)]
for num_req in range(1, num_pvs + 2):
epvs = bdev.LogicalVolume._GetEmptyPvNames(pvlist, num_req)
epvs_set = compat.UniqueFrozenset(epvs)
if len(epvs) > 1:
self.assertEqual(len(epvs), len(epvs_set))
for pvi in pvlist:
if pvi.name in epvs_set:
self.assertEqual(pvi.size, pvi.free)
else:
# There should be no remaining empty PV when less than the
# requeste number of PVs has been returned
self.assertTrue(len(epvs) == num_req or pvi.free != pvi.size)
if __name__ == "__main__":
testutils.GanetiTestProgram()
#!/usr/bin/python
#
# Copyright (C) 2013 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""Script for testing ganeti.utils.lvm"""
import unittest
from ganeti import constants
from ganeti import utils
from ganeti.objects import LvmPvInfo
import testutils
class TestLvmExclusiveCheckNodePvs(unittest.TestCase):
"""Test cases for LvmExclusiveCheckNodePvs()"""
_VG = "vg"
_SMALL_PV = LvmPvInfo(name="small", vg_name=_VG, size=100e3, free=40e3,
attributes="a-")
_MED_PV = LvmPvInfo(name="medium", vg_name=_VG, size=400e3, free=40e3,
attributes="a-")
_BIG_PV = LvmPvInfo(name="big", vg_name=_VG, size=1e6, free=400e3,
attributes="a-")
# Allowance for rounding
_EPS = 1e-4
def testOnePv(self):
errmsgs = utils.LvmExclusiveCheckNodePvs([self._MED_PV])
self.assertFalse(errmsgs)
def testEqualPvs(self):
errmsgs = utils.LvmExclusiveCheckNodePvs([self._MED_PV] * 2)
self.assertFalse(errmsgs)
errmsgs = utils.LvmExclusiveCheckNodePvs([self._SMALL_PV] * 3)
self.assertFalse(errmsgs)
def testTooDifferentPvs(self):
errmsgs = utils.LvmExclusiveCheckNodePvs([self._MED_PV, self._BIG_PV])
self.assertEqual(len(errmsgs), 1)
errmsgs = utils.LvmExclusiveCheckNodePvs([self._MED_PV, self._SMALL_PV])
self.assertEqual(len(errmsgs), 1)
def testBoundarySizeCases(self):
medpv1 = self._MED_PV.Copy()
medpv2 = self._MED_PV.Copy()
errmsgs = utils.LvmExclusiveCheckNodePvs([medpv1, medpv2, self._MED_PV])
self.assertFalse(errmsgs)
# Just within the margins
medpv1.size = self._MED_PV.size * (1 - constants.PART_MARGIN + self._EPS)
medpv2.size = self._MED_PV.size * (1 + constants.PART_MARGIN - self._EPS)
errmsgs = utils.LvmExclusiveCheckNodePvs([medpv1, medpv2, self._MED_PV])
self.assertFalse(errmsgs)
# Just outside the margins
medpv1.size = self._MED_PV.size * (1 - constants.PART_MARGIN - self._EPS)
medpv2.size = self._MED_PV.size * (1 + constants.PART_MARGIN)
errmsgs = utils.LvmExclusiveCheckNodePvs([medpv1, medpv2, self._MED_PV])
self.assertTrue(errmsgs)
medpv1.size = self._MED_PV.size * (1 - constants.PART_MARGIN)
medpv2.size = self._MED_PV.size * (1 + constants.PART_MARGIN + self._EPS)
errmsgs = utils.LvmExclusiveCheckNodePvs([medpv1, medpv2, self._MED_PV])
self.assertTrue(errmsgs)
if __name__ == "__main__":
testutils.GanetiTestProgram()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment