1 from PLC.Config import Config
2 from PLC.Faults import *
4 from datetime import datetime, timedelta
5 from pyaspects.meta import MetaAspect
8 class BaseRateLimit(object):
11 self.config = Config("/etc/planetlab/plc_config")
13 self.prefix = "ratelimit"
14 self.minutes = 3 # The time period
15 self.requests = 10 # Number of allowed requests in that time period
16 self.expire_after = (self.minutes + 1) * 60
18 def before(self, wobj, data, *args, **kwargs):
19 # ratelimit_128.112.139.115_201011091532 = 1
20 # ratelimit_128.112.139.115_201011091533 = 14
21 # ratelimit_128.112.139.115_201011091534 = 11
22 # Now, on every request we work out the keys for the past five minutes and use get_multi to retrieve them.
23 # If the sum of those counters exceeds the maximum allowed for that time period, we block the request.
25 api_method_name = wobj.name
26 api_method_source = wobj.source
28 if api_method_source == None or api_method_source[0] == self.config.PLC_API_HOST:
31 mc = memcache.Client(['%s:11211'] % self.config.PLC_API_HOST)
33 current_key = '%s_%s_%s' % (self.prefix, api_method_source[0], now.strftime('%Y%m%d%H%M'))
35 keys_to_check = ['%s_%s_%s' % (self.prefix, api_method_source[0], (now - timedelta(minutes = minute)).strftime('%Y%m%d%H%M')) for minute in range(self.minutes + 1)]
40 mc.set(current_key, 1, time=self.expire_after)
42 result = mc.get_multi(keys_to_check)
45 total_requests += result[i]
47 if total_requests > self.requests:
48 raise PLCPermissionDenied, "Maximum allowed number of API calls exceeded"
50 def after(self, wobj, data, *args, **kwargs):
53 class RateLimitAspect_class(BaseRateLimit):
54 __metaclass__ = MetaAspect
55 name = "ratelimitaspect_class"
58 BaseRateLimit.__init__(self)
60 def before(self, wobj, data, *args, **kwargs):
61 BaseRateLimit.before(self, wobj, data, *args, **kwargs)
63 def after(self, wobj, data, *args, **kwargs):
64 BaseRateLimit.after(self, wobj, data, *args, **kwargs)
66 RateLimitAspect = RateLimitAspect_class