On Mon, Nov 17, 2014 at 7:56 PM, 'Aaron Karper' via ganeti-devel <[email protected]> wrote: > The temporary reservation manager is sufficiently independent to be > moved to a separte submodule. > > Signed-off-by: Aaron Karper <[email protected]> > --- > Makefile.am | 3 +- > lib/config/__init__.py | 68 +---------------------- > lib/config/temporary_reservations.py | 101 > +++++++++++++++++++++++++++++++++++ > 3 files changed, 105 insertions(+), 67 deletions(-) > create mode 100644 lib/config/temporary_reservations.py > > diff --git a/Makefile.am b/Makefile.am > index 67df7db..e83e33b 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -513,7 +513,8 @@ cmdlib_cluster_PYTHON = \ > lib/cmdlib/cluster/verify.py > > config_PYTHON = \ > - lib/config/__init__.py > + lib/config/__init__.py \ > + lib/config/temporary_reservations.py > > hypervisor_PYTHON = \ > lib/hypervisor/__init__.py \ > diff --git a/lib/config/__init__.py b/lib/config/__init__.py > index 816e947..57f6d66 100644 > --- a/lib/config/__init__.py > +++ b/lib/config/__init__.py > @@ -51,6 +51,8 @@ import time > import threading > import itertools > > +from ganeti.config.temporary_reservations import TemporaryReservationManager > + > from ganeti import errors > from ganeti import utils > from ganeti import constants > @@ -135,72 +137,6 @@ def _ValidateConfig(data): > data['version']) > > > -class TemporaryReservationManager(object): > - """A temporary resource reservation manager. > - > - This is used to reserve resources in a job, before using them, making sure > - other jobs cannot get them in the meantime. > - > - """ > - def __init__(self): > - self._ec_reserved = {} > - > - def Reserved(self, resource): > - for holder_reserved in self._ec_reserved.values(): > - if resource in holder_reserved: > - return True > - return False > - > - def Reserve(self, ec_id, resource): > - if self.Reserved(resource): > - raise errors.ReservationError("Duplicate reservation for resource '%s'" > - % str(resource)) > - if ec_id not in self._ec_reserved: > - self._ec_reserved[ec_id] = set([resource]) > - else: > - self._ec_reserved[ec_id].add(resource) > - > - def DropECReservations(self, ec_id): > - if ec_id in self._ec_reserved: > - del self._ec_reserved[ec_id] > - > - def GetReserved(self): > - all_reserved = set() > - for holder_reserved in self._ec_reserved.values(): > - all_reserved.update(holder_reserved) > - return all_reserved > - > - def GetECReserved(self, ec_id): > - """ Used when you want to retrieve all reservations for a specific > - execution context. E.g when commiting reserved IPs for a specific > - network. > - > - """ > - ec_reserved = set() > - if ec_id in self._ec_reserved: > - ec_reserved.update(self._ec_reserved[ec_id]) > - return ec_reserved > - > - def Generate(self, existing, generate_one_fn, ec_id): > - """Generate a new resource of this type > - > - """ > - assert callable(generate_one_fn) > - > - all_elems = self.GetReserved() > - all_elems.update(existing) > - retries = 64 > - while retries > 0: > - new_resource = generate_one_fn() > - if new_resource is not None and new_resource not in all_elems: > - break > - else: > - raise errors.ConfigurationError("Not able generate new resource" > - " (last tried: %s)" % new_resource) > - self.Reserve(ec_id, new_resource) > - return new_resource > - > - > def _MatchNameComponentIgnoreCase(short_name, names): > """Wrapper around L{utils.text.MatchNameComponent}. > > diff --git a/lib/config/temporary_reservations.py > b/lib/config/temporary_reservations.py > new file mode 100644 > index 0000000..c90c23c > --- /dev/null > +++ b/lib/config/temporary_reservations.py > @@ -0,0 +1,101 @@ > +# > +# > + > +# Copyright (C) 2014 Google Inc. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions are > +# met: > +# > +# 1. Redistributions of source code must retain the above copyright notice, > +# this list of conditions and the following disclaimer. > +# > +# 2. Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in the > +# documentation and/or other materials provided with the distribution. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS > +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED > +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, > +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, > +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR > +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS > +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > + > +"""Reserve resources, so that jobs can't take them. > + > +""" > + > +from ganeti import errors > + > + > +class TemporaryReservationManager(object): > + """A temporary resource reservation manager. > + > + This is used to reserve resources in a job, before using them, making sure > + other jobs cannot get them in the meantime. > + > + """ > + def __init__(self): > + self._ec_reserved = {} > + > + def Reserved(self, resource): > + for holder_reserved in self._ec_reserved.values(): > + if resource in holder_reserved: > + return True > + return False > + > + def Reserve(self, ec_id, resource): > + if self.Reserved(resource): > + raise errors.ReservationError("Duplicate reservation for resource '%s'" > + % str(resource)) > + if ec_id not in self._ec_reserved: > + self._ec_reserved[ec_id] = set([resource]) > + else: > + self._ec_reserved[ec_id].add(resource) > + > + def DropECReservations(self, ec_id): > + if ec_id in self._ec_reserved: > + del self._ec_reserved[ec_id] > + > + def GetReserved(self): > + all_reserved = set() > + for holder_reserved in self._ec_reserved.values(): > + all_reserved.update(holder_reserved) > + return all_reserved > + > + def GetECReserved(self, ec_id): > + """ Used when you want to retrieve all reservations for a specific > + execution context. E.g when commiting reserved IPs for a specific > + network. > + > + """ > + ec_reserved = set() > + if ec_id in self._ec_reserved: > + ec_reserved.update(self._ec_reserved[ec_id]) > + return ec_reserved > + > + def Generate(self, existing, generate_one_fn, ec_id): > + """Generate a new resource of this type > + > + """ > + assert callable(generate_one_fn) > + > + all_elems = self.GetReserved() > + all_elems.update(existing) > + retries = 64 > + while retries > 0: > + new_resource = generate_one_fn() > + if new_resource is not None and new_resource not in all_elems: > + break > + else: > + raise errors.ConfigurationError("Not able generate new resource" > + " (last tried: %s)" % new_resource) > + self.Reserve(ec_id, new_resource) > + return new_resource > -- > 2.1.0.rc2.206.gedb03e5 >
LGTM, thanks. Michele -- Google Germany GmbH Dienerstr. 12 80331 München Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschäftsführer: Graham Law, Christine Elizabeth Flores
