# # NodeManager plugin - first step of handling reservable nodes # Thierry Parmentelat # """ Manages running slices when reservation_policy is 'lease_or_idle' or 'lease_or_shared' """ import time import threading import logger import account import database # there is an implicit assumption that this triggers after slicemanager priority = 45 # this instructs nodemanager that we want to use the latest known data in case the plc link is down persistent_data = True # of course things would be simpler if node manager was to create one instance of the plugins # instead of blindly caling functions in the module... ############################## # rough implementation for a singleton class def Singleton (klass, *args, **kwds): if not hasattr(klass, '_instance'): klass._instance=klass(*args, **kwds) return klass._instance def start(): return Singleton(reservation).start() def GetSlivers(data, conf = None, plc = None): return Singleton(reservation).GetSlivers(data, conf, plc) ############################## class reservation: debug=False debug=True def __init__ (self): # the last snapshot of data exposed by GetSlivers self.data = None # this is a dict mapping a raounded timestamp to the corr. Timer object self.timers = {} #################### def start(self): logger.log("reservation: plugin performing dummy start...") # this method is entirely about making sure that we have events scheduled # at the intervals where there is a lease that starts or ends def GetSlivers (self, data, conf=None, plc=None): # check we're using a compliant GetSlivers if 'reservation_policy' not in data: logger.log_missing_data("reservation.GetSlivers", 'reservation_policy') return self.reservation_policy=data['reservation_policy'] if 'leases' not in data: logger.log_missing_data("reservation.GetSlivers", 'leases') return # store data locally # since we've asked for persistent_data, we should not get an empty data here if data: self.data = data # regular nodes are not affected if self.reservation_policy == 'none': return elif self.reservation_policy not in ['lease_or_idle', 'lease_or_shared']: logger.log("reservation: ignoring -- unexpected value for reservation_policy %r"%self.reservation_policy) return # at this point we have reservation_policy in ['lease_or_idle', 'lease_or_shared'] # we make no difference for now logger.log("reservation.GetSlivers: reservable node -- policy=%s"%self.reservation_policy) self.sync_timers_from_leases() logger.log("reservation.GetSlivers: listing timers") if reservation.debug: self.list_timers() #################### # the granularity is set in the API (initial value is 15 minutes) # and it used to round all leases start/until times # changing this dynamically can have some weird effects of course.. def granularity (self): try: return self.data['lease_granularity'] # in case we'd try to access this before it's populated.. except: return 60*60 # round to granularity def round_time (self, time): granularity=self.granularity() return ((int(time)+granularity/2)/granularity)*granularity def clear_timers (self): for timer in list(self.timers.values()): timer.cancel() self.timers={} def sync_timers_from_leases (self): self.clear_timers() for lease in self.data['leases']: self.ensure_timer_from_until(lease['t_from'], lease['t_until']) # assuming t1