.. so that tests that require these calls still work. Also use the mocked configuration for some tests that require functions related to IP reservations.
Signed-off-by: Petr Pudlak <[email protected]> --- test/py/cmdlib/testsupport/config_mock.py | 93 ++++++++++++++++++++++++++++++- test/py/ganeti.config_unittest.py | 14 +++-- 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/test/py/cmdlib/testsupport/config_mock.py b/test/py/cmdlib/testsupport/config_mock.py index 04dbeb2..de0e4d9 100644 --- a/test/py/cmdlib/testsupport/config_mock.py +++ b/test/py/cmdlib/testsupport/config_mock.py @@ -29,13 +29,17 @@ import uuid as uuid_module from ganeti import config from ganeti import constants from ganeti import errors -from ganeti import objects from ganeti.network import AddressPool +from ganeti import objects from ganeti import utils import mocks +RESERVE_ACTION = "reserve" +RELEASE_ACTION = "release" + + def _StubGetEntResolver(): return mocks.FakeGetentResolver() @@ -46,7 +50,7 @@ class ConfigMock(config.ConfigWriter): """ - def __init__(self): + def __init__(self, cfg_file="/dev/null"): self._cur_group_id = 1 self._cur_node_id = 1 self._cur_inst_id = 1 @@ -60,8 +64,9 @@ class ConfigMock(config.ConfigWriter): self._temporary_macs = config.TemporaryReservationManager() self._temporary_secrets = config.TemporaryReservationManager() self._temporary_lvs = config.TemporaryReservationManager() + self._temporary_ips = config.TemporaryReservationManager() - super(ConfigMock, self).__init__(cfg_file="/dev/null", + super(ConfigMock, self).__init__(cfg_file=cfg_file, _getents=_StubGetEntResolver(), offline=True) @@ -711,3 +716,85 @@ class ConfigMock(config.ConfigWriter): raise errors.ReservationError("LV already in use") else: self._temporary_lvs.Reserve(ec_id, lv_name) + + def _UnlockedCommitTemporaryIps(self, ec_id): + """Commit all reserved IP address to their respective pools + + """ + for action, address, net_uuid in self._temporary_ips.GetECReserved(ec_id): + self._UnlockedCommitIp(action, net_uuid, address) + + def _UnlockedCommitIp(self, action, net_uuid, address): + """Commit a reserved IP address to an IP pool. + + The IP address is taken from the network's IP pool and marked as reserved. + + """ + nobj = self._UnlockedGetNetwork(net_uuid) + pool = AddressPool(nobj) + if action == RESERVE_ACTION: + pool.Reserve(address) + elif action == RELEASE_ACTION: + pool.Release(address) + + def _UnlockedReleaseIp(self, net_uuid, address, ec_id): + """Give a specific IP address back to an IP pool. + + The IP address is returned to the IP pool designated by pool_id and marked + as reserved. + + """ + self._temporary_ips.Reserve(ec_id, + (RELEASE_ACTION, address, net_uuid)) + + def ReleaseIp(self, net_uuid, address, ec_id): + """Give a specified IP address back to an IP pool. + + This is just a wrapper around _UnlockedReleaseIp. + + """ + if net_uuid: + self._UnlockedReleaseIp(net_uuid, address, ec_id) + + def GenerateIp(self, net_uuid, ec_id): + """Find a free IPv4 address for an instance. + + """ + nobj = self._UnlockedGetNetwork(net_uuid) + pool = AddressPool(nobj) + + def gen_one(): + try: + ip = pool.GenerateFree() + except errors.AddressPoolError: + raise errors.ReservationError("Cannot generate IP. Network is full") + return (RESERVE_ACTION, ip, net_uuid) + + _, address, _ = self._temporary_ips.Generate([], gen_one, ec_id) + return address + + def _UnlockedReserveIp(self, net_uuid, address, ec_id, check=True): + """Reserve a given IPv4 address for use by an instance. + + """ + nobj = self._UnlockedGetNetwork(net_uuid) + pool = AddressPool(nobj) + try: + isreserved = pool.IsReserved(address) + isextreserved = pool.IsReserved(address, external=True) + except errors.AddressPoolError: + raise errors.ReservationError("IP address not in network") + if isreserved: + raise errors.ReservationError("IP address already in use") + if check and isextreserved: + raise errors.ReservationError("IP is externally reserved") + return self._temporary_ips.Reserve(ec_id, + (RESERVE_ACTION, + address, net_uuid)) + + def ReserveIp(self, net_uuid, address, ec_id, check=True): + """Reserve a given IPv4 address for use by an instance. + + """ + if net_uuid: + return self._UnlockedReserveIp(net_uuid, address, ec_id, check) diff --git a/test/py/ganeti.config_unittest.py b/test/py/ganeti.config_unittest.py index 7efa4b1..1c64203 100755 --- a/test/py/ganeti.config_unittest.py +++ b/test/py/ganeti.config_unittest.py @@ -42,6 +42,7 @@ from ganeti.config import TemporaryReservationManager import testutils import mocks import mock +from cmdlib.testsupport.config_mock import ConfigMock def _StubGetEntResolver(): @@ -67,6 +68,11 @@ class TestConfigRunner(unittest.TestCase): _getents=_StubGetEntResolver) return cfg + def _get_object_mock(self): + """Returns a mocked instance of ConfigWriter""" + cfg = ConfigMock(cfg_file=self.cfg_file) + return cfg + def _init_cluster(self, cfg): """Initializes the cfg object""" me = netutils.Hostname() @@ -136,7 +142,7 @@ class TestConfigRunner(unittest.TestCase): def testInstNodesNoDisks(self): """Test all_nodes/secondary_nodes when there are no disks""" # construct instance - cfg = self._get_object() + cfg = self._get_object_mock() inst = self._create_instance(cfg) cfg.AddInstance(inst, "my-job") @@ -152,7 +158,7 @@ class TestConfigRunner(unittest.TestCase): def testInstNodesPlainDisks(self): # construct instance - cfg = self._get_object() + cfg = self._get_object_mock() inst = self._create_instance(cfg) disks = [ objects.Disk(dev_type=constants.DT_PLAIN, size=128, @@ -178,7 +184,7 @@ class TestConfigRunner(unittest.TestCase): def testInstNodesDrbdDisks(self): # construct a second node - cfg = self._get_object() + cfg = self._get_object_mock() node_group = cfg.LookupNodeGroup(None) master_uuid = cfg.GetMasterNode() node2 = objects.Node(name="node2.example.com", group=node_group, @@ -253,7 +259,7 @@ class TestConfigRunner(unittest.TestCase): def testUpdateInstance(self): """Test updates on one instance object""" - cfg = self._get_object() + cfg = self._get_object_mock() # construct a fake instance inst = self._create_instance(cfg) fake_instance = objects.Instance() -- 2.0.0.526.g5318336
