* Byte limits are in KB when passed or requested via XMLRPC to NM. Bytes otherwise.
[mom.git] / bwmon.py
index b31e893..ed9cd7b 100755 (executable)
--- a/bwmon.py
+++ b/bwmon.py
@@ -54,14 +54,13 @@ default_maxexemptrate = bwlimit.bwmax
 # 1.5 Mbit or 16.4 GB per day
 #default_avgexemptrate = 1500000
 
-# 4 Gbyte per day. 4 * 1024K * 1024M * 1024G 
-default_ByteThresh = 4294967296
+# 5.4 Gbyte per day. 5.4 * 1024 k * 1024M * 1024G 
 # 5.4 Gbyte per day max allowed transfered per recording period
-default_ByteMax = 5798205850 
-# 14 Gbyte per day
-default_ExemptByteThresh = 15032385536
+default_ByteMax = 5798205850
+default_ByteThresh = int(.8 * default_ByteMax) 
 # 16.4 Gbyte per day max allowed transfered per recording period to I2
 default_ExemptByteMax = 17609365914 
+default_ExemptByteThresh = int(.8 * default_ExemptByteMax) 
 
 
 # Average over 1 day
@@ -100,12 +99,8 @@ class Slice:
        ByteThresh - After thresh, cap node to (maxbyte - bytes)/(time left in period)
        ExemptByteMax - Same as above, but for i2.
        ExemptByteThresh - i2 ByteThresh
-       #last_maxexemptrate - last recorded maxexemptrate from NM.  Slice attribute.
-       #last_maxrate - last recorded maxrate from NM.  Slice attribute.
-       #last_ByteMax - Last recorded from NM. total volume of data allowed.
-       #last_ByteThresh - Last recorded from NM.  After thresh, cap node to (maxbyte - bytes)/(period - t)
-       #last_ExemptByteMax - Last recorded from NM.  Same as above, but for i2.
-       #last_ExemptByteThresh - Last recorded from NM.  i2 ByteThresh
+       maxrate - max_rate slice attribute. 
+       maxexemptrate - max_exempt_rate slice attribute.
 
     """
 
@@ -121,12 +116,6 @@ class Slice:
                self.ExemptByteThresh = default_ExemptByteThresh
                self.maxrate = default_maxrate
                self.maxexemptrate = default_maxexemptrate
-               #self.last_maxrate = default_maxrate
-               #self.last_maxexemptrate = default_maxexemptrate        
-               #self.last_ByteMax = default_ByteMax
-               #self.last_ByteThresh = default_ByteThresh
-               #self.last_ExemptByteMax = default_ExemptByteMax
-               #self.last_ExemptByteThresh = default_ExemptByteThresh
 
                # Get real values where applicable
                self.reset(maxrate, maxexemptrate, bytes, exemptbytes)
@@ -139,8 +128,41 @@ class Slice:
                try:
                        vals = nm.query(self.name, 
                                [('nm_net_max_rate', self.maxrate),
-                               ('nm_net_max_exempt_rate', self.maxexemptrate)])
-                       (self.maxrate, self.maxexemptrate) = vals
+                               ('nm_net_max_exempt_rate', self.maxexemptrate),
+                               ("nm_net_max_byte", int(self.ByteMax / 1024)),
+                               ("nm_net_max_exempt_byte", int(self.ExemptByteMax / 1024)),
+                               ("nm_net_max_thresh_byte", int( .8 * self.ByteMax / 1024)),
+                               ("nm_net_max_thresh_exempt_byte", int(.8 * self.ExemptByteMax / 1024)),
+                               ("nm_net_avg_rate", 0),
+                               ("nm_net_avg_exempt_rate", 0)])
+
+                       (self.maxrate,
+                               self.maxexemptrate,
+                               ByteMax,
+                               ExemptByteMax,
+                               ByteThresh,
+                               ExemptByteThresh,
+                               avgrate,
+                               avgexemptrate) = vals
+                       
+                       # The shitty bit.  Gotta bias the limits so as not to overflow xmlrpc
+                       self.ByteMax = ByteMax * 1024 
+                       self.ByteThresh = ByteMax * 1024 
+                       self.ExemptByteMax = ExemptByteMax * 1024 
+                       self.ExemptByteThresh = ExemptByteThresh * 1024 
+
+                       # The hack here is that when i pass 0 to the xmlrpc request to NM, 
+                       # for rate limits and it comes back non zero, then screw the byte limits.
+                       # Mult by the period and recompute the byte limits.  The thought is
+                       # If/when PLC switches to byte limits, the avgrates wont be used as
+                       # slice attributes and will return as 0
+                       if (avgrate != 0):
+                               self.ByteMax = avgrate * period 
+                               self.ByteThresh = int(self.ByteMax * .8)
+
+                       if (avgexemptrate != 0):
+                               self.ExemptByteMax = avgexemptrate * period
+                               self.ExemptByteThresh = int(self.ExemptByteMax * .8)
 
                except Exception, err:
                        print "Warning: Exception received while querying NM:", err
@@ -164,19 +186,16 @@ class Slice:
                if (self.maxrate != maxrate) or (self.maxexemptrate != maxexemptrate):
                        print "%s reset to %s/%s" % \
                                  (self.name,
-                                  bwlimit.format_tc_rate(self.maxrate),
-                                  bwlimit.format_tc_rate(self.maxexemptrate))
+                                  #bwlimit.format_tc_rate(self.maxrate),
+                                  self.maxrate,
+                                  #bwlimit.format_tc_rate(self.maxexemptrate))
+                                  self.maxexemptrate)
                        bwlimit.set(xid = self.xid, maxrate = self.maxrate, maxexemptrate = self.maxexemptrate)
 
        def update(self, maxrate, maxexemptrate, bytes, exemptbytes):
                """
-               Update byte counts and check if average rates have been
-               exceeded. In the worst case (instantaneous usage of the entire
-               average daily byte limit at the beginning of the recording
-               period), the slice will be immediately capped and will get to
-               send twice the average daily byte limit. In the common case,
-               it will get to send slightly more than the average daily byte
-               limit.
+               Update byte counts and check if byte limits have been
+               exceeded. 
                """
        
                # Query Node Manager for max rate overrides
@@ -191,7 +210,8 @@ class Slice:
                                  'period': format_period(period)} 
 
                if bytes >= (self.bytes + self.ByteThresh):
-                       new_maxrate = (self.ByteMax - self.ByteThresh)/(period - (time.time() - self.time))
+                       new_maxrate = \
+                       int((self.ByteMax - self.bytes + bytes)/(period - time.time() - self.time))
                else:
                        new_maxrate = maxrate
 
@@ -204,7 +224,7 @@ class Slice:
 
                if verbose:
                        print "%(slice)s %(class)s " \
-                                 "%(bytes)s, %(limit)s (%(new_maxrate)s avg)" % \
+                                 "%(bytes)s of %(limit)s (%(new_maxrate)s maxrate)" % \
                                  params
 
                # Cap low bandwidth burst rate
@@ -214,7 +234,7 @@ class Slice:
        
                if exemptbytes >= (self.exemptbytes + self.ExemptByteThresh):
                        new_maxexemptrate = \
-                       (self.ExemptByteMax - self.ExemptByteThresh)/(period - (time.time() - self.time))
+                       int((self.ExemptByteMax - (self.bytes + bytes))/(period - (time.time() - self.time)))
                else:
                        new_maxexemptrate = maxexemptrate
 
@@ -223,11 +243,11 @@ class Slice:
                params['bytes'] = format_bytes(exemptbytes - self.exemptbytes)
                params['maxrate'] = bwlimit.format_tc_rate(maxexemptrate)
                params['limit'] = format_bytes(self.ExemptByteMax)
-               params['new_maxrate'] = bwlimit.format_tc_rate(new_maxexemptrate)
+               params['new_maxexemptrate'] = bwlimit.format_tc_rate(new_maxexemptrate)
 
                if verbose:
                        print "%(slice)s %(class)s " \
-                                 "%(bytes)s, %(limit)s (%(new_maxrate)s avg)" % params
+                                 "%(bytes)s of %(limit)s (%(new_maxrate)s maxrate)" % params
 
                # Cap high bandwidth burst rate
                if new_maxexemptrate != maxexemptrate:
@@ -239,13 +259,15 @@ class Slice:
                        bwlimit.set(xid = self.xid, maxrate = new_maxrate, maxexemptrate = new_maxexemptrate)
 
                # Notify slice
-               if message:
-                       subject = "pl_mom capped bandwidth of slice %(slice)s on %(hostname)s" % params
-                       if debug:
-                               print subject
-                               print message + (footer % params)
-                       else:
-                               slicemail(self.name, subject, message + (footer % params))
+               #if message:
+               #       subject = "pl_mom capped bandwidth of slice %(slice)s on %(hostname)s" % params
+               #       if debug:
+               #               print subject
+               #               print message + (footer % params)
+               #       else:
+               #               slicemail(self.name, subject, message + (footer % params))
+
+
 
 def usage():
        print """
@@ -328,8 +350,17 @@ def main():
                 bytes, exemptbytes) = params
                live.append(xid)
                
-               # Delete Me
-               print("name %s , minrate %s, maxrate %s, minexemptrate %s, maxexemptrate %s, bytes %s, exemptbytes %s" % (bwlimit.get_slice(xid), minrate, maxrate, minexemptrate, maxexemptrate, bytes, exemptbytes))
+               if verbose:
+                       print("\nRunning stats for %s from tc."\
+                           "\nminrate %s, maxrate %s, minexemptrate %s,"\
+                               " maxexemptrate %s, bytes %s, exemptbytes %s" % \
+                               (bwlimit.get_slice(xid), 
+                               bwlimit.format_tc_rate(minrate),
+                               bwlimit.format_tc_rate(maxrate), 
+                               bwlimit.format_tc_rate(minexemptrate),
+                               bwlimit.format_tc_rate(maxexemptrate), 
+                               bytes, 
+                               exemptbytes))
 
                # Ignore root and default buckets
                if xid == root_xid or xid == default_xid: