Ejemplo n.º 1
0
 def __init__(self):
     self._cpex_lock=RLock() # cpex switch list lock, used for setting/getting the "primary" cpex switch.
     self._cache_lock=Lock() # domain value cache lock.
     self._cpex_switch_map_lock = Lock() # lock for cpex switches cache data structure
     self._cache_value=None
     self._cache_time=0
     self._cpex_switch_map_cache=SwitchMap({})
     self._cpex_switch_map_time=0
     self.ttl=30
     self._reinit()
     return
Ejemplo n.º 2
0
class EnergywiseDomain(Node):
    def __init__(self):
        self._cpex_lock=RLock() # cpex switch list lock, used for setting/getting the "primary" cpex switch.
        self._cache_lock=Lock() # domain value cache lock.
        self._cpex_switch_map_lock = Lock() # lock for cpex switches cache data structure
        self._cache_value=None
        self._cache_time=0
        self._cpex_switch_map_cache=SwitchMap({})
        self._cpex_switch_map_time=0
        self.ttl=30
        self._reinit()
        return
    def _not_running(self, *args, **kw):
        raise ENotRunning("%r is not running." % self.as_node_url())
    def _empty_domain_usage(self, importance=100, skipCache=False):
        return 0.0
    def _reinit(self):
        self._cpex_switches = []
        self._snmp_switches = []
        self._all_switches = []
        self._all_domains = []
        self.domain = ''
        self.trend_node = None
        self.energywise_domain_usage = self._not_running
        return
    def configure(self, config):
         Node.configure(self, config)
         set_attribute(self, 'ttl', 30, config, int)
         return
    def configuration(self):
         config = Node.configuration(self)
         get_attribute(self, 'ttl', config, str)
         return config
    def start(self):
        self._cpex_lock.acquire()
        try:
            for child in self.children_nodes():
                if isinstance(child,EnergywiseSwitch):
                    if child.PROTOCOL_SNMP == child.protocol:
                        self._snmp_switches.append(child)
                    else:
                        self._cpex_switches.append(child)
                    self._all_switches.append(child)
                elif isinstance(child,EnergywiseDomain):
                    self._all_domains.append(child)
            # elif @fixme magic hook for reverse compatibility.
            if self._snmp_switches and self._cpex_switches:
                raise EConfiguration(
                    "All switches in a domain must be configurtion to use the"
                    " same protocol."
                    )
            self._cpex_switches.sort(_cpex_switch_cmp) 
        finally:
            self._cpex_lock.release()
        if not self.domain:
            self.domain = _find_domain(self)
        if self._snmp_switches:
            self.energywise_domain_usage = self.snmp_domain_usage
        elif self._cpex_switches:
            self.energywise_domain_usage = self.cpex_domain_usage
        else:
            self.energywise_domain_usage = self._empty_domain_usage
        Node.start(self)
        return
    def stop(self):
        self._reinit()
        Node.stop(self)
        return
    def cpex_domain_usage(self, importance=100, skipCache=False, max_attempts=3):
        self._cpex_lock.acquire()
        aggr_result = 0
        try:
            if not self._cpex_switches:
                raise ENoDomainSwitches(
                    "No switches are configured for the %r domain." % self.domain
                    )
            for switch in self._cpex_switches:
                for i in range(0, max_attempts):
                    try:
                        result = switch.cpex_domain_usage(importance)
                        if result:
                            aggr_result += result
                            break
                    except:
                        pass
        except ENoDomainSwitches:
            raise
        finally:
            self._cpex_lock.release()
        return aggr_result
    # caching for cpex switches under a domain
    # @return A dictionary of Energywise usage values keyed by switch address, possibly from cache.
    def cpex_switch_usage_map(self, importance=100, skipCache=False):
        self._cpex_switch_map_lock.acquire()
        try:
            if skipCache or self._is_cpex_switch_map_stale(time.time()):
                #fetch actual value
                usage_map = self._cpex_switch_usage_map(importance)
                self._update_cpex_switch_map(usage_map, time.time())
            return self._cpex_switch_map_cache
        finally:
            self._cpex_switch_map_lock.release()
        raise EUnreachableCode("Executed unreachable code!")
    ##
    # Call cpex_switch_usage_map on the primary cpex switch.
    # @return A dictionary of Energywise usage values keyed by switch address.
    def _cpex_switch_usage_map(self, importance=100, max_attempts=3):
        self._cpex_lock.acquire()
        aggr_result = {}
        try:
            if not self._cpex_switches:
                raise ENoDomainSwitches(
                    "No switches are configured for the %r domain." % self.domain
                    )
            for switch in self._cpex_switches:
                for i in range(0, max_attempts):
                    try:
                        result = switch.cpex_switch_usage_map(importance)
                        if result:
                            aggr_result.update(result)
                            break
                    except:
                        pass
        except ENoDomainSwitches:
            raise
        finally:
            self._cpex_lock.release()
        return aggr_result
    def snmp_domain_usage(self, importance=100, skipCache=False):
        result = 0
        for switch in self._snmp_switches:
            try:
                result += switch.snmp_switch_usage(importance, skipCache)
            except:
                msglog.exception()
                msglog.log("Energywise",msglog.types.ERR,
                           "Failed to get data from %r switch" %switch.name
                           )
        return result
    def _is_cpex_switch_map_stale(self, timestamp):
        return (self._cpex_switch_map_time + self.ttl) < timestamp
    def _update_cpex_switch_map(self, switch_map, timestamp):
        self._cpex_switch_map_cache = SwitchMap(switch_map)
        self._cpex_switch_map_time = timestamp
    def _is_domain_cache_stale(self,timestamp):
        assert self._cache_lock.locked()
        return (self._cache_time + self.ttl) < timestamp
    def _update_domain_cache(self,value, timestamp):
        self._cache_value = value
        self._cache_time = timestamp
    #caching the domain-usage
    def aggregate_domain_usage(self, importance=100, skipCache=False):
        self._cache_lock.acquire()
        try:
            if skipCache or self._is_domain_cache_stale(time.time()):
                    #fetch the actual value and update the cache
                try:
                    result = self.energywise_domain_usage(importance, skipCache)
                except:
                    msglog.exception()
                    result = 0
                for sub in self._all_domains:
                        result += sub.aggregate_domain_usage(importance, skipCache)
                self._update_domain_cache(result, time.time())
                return self._cache_value
            else:
                # use the cached value
                return self._cache_value
        finally:
            self._cache_lock.release()
        raise EUnreachableCode("Executed unreachable code!") 
    def new_trend(self,period):
        return new_trend(self,period)
    def delete_trend(self):
        return delete_trend(self)
    def get(self, skipCache=False):
        return self.aggregate_domain_usage()
    def get_result(self, skipCache=False):
        return Result(self.get(skipCache), time.time(), cached=False)