ability to return bucket info in get_account, bucket stats on account screen
smbaker [Thu, 1 Nov 2012 05:20:12 +0000 (22:20 -0700)]
apps/gacks/API.py
apps/gacks/gacksenforce.py
apps/gacks/gacksid.py
apps/gacksadmin/account.php
apps/gacksadmin/gacks_functions.php

index 9f42aeb..00aed7b 100644 (file)
@@ -31,7 +31,7 @@ from gackspolicy import GacksPolicyDirectory
 from gacksenforce import GacksEnforcer
 from gacksnodepicker import GacksNodePicker
 from gacksnodestatus import GacksNodeStatus
-from gacksid import str_to_gacksid, hrn_matches_gacksid
+from gacksid import str_to_gacksid, hrn_matches_gacksid, str_to_hrn
 from gackshandler_plc import set_logger_name as gackshandler_plc_set_logger_name
 from gacksnodepicker import set_logger_name as gacksnodepicker_set_logger_name
 from gacksbilling import GacksBilling
@@ -770,10 +770,18 @@ class RemoteApi(AuthenticatedApi):
     def get_account(self, authToken_str, name, kind, create_if_not_exist=False):
         (authToken, callerGID, objectGID) = self.authenticateToken(authToken_str, [name, kind, create_if_not_exist])
 
+        want_bucket = False
+        if kind=="user_bucket":
+            # little bit of a hack. "user_bucket" means to fetch the user account
+            # and the bucket analysis
+            kind="user"
+            want_bucket = True
+
+        orig_name = name
         name = str_to_gacksid(name)
 
         acct = self.accounts.get_account(name, kind, create_if_not_exist=create_if_not_exist)
-        if acct:
+        if acct is not None:
             acct.apply_inRate()
             if acct.is_dirty() or acct.created:
                 acct.commit()
@@ -781,7 +789,11 @@ class RemoteApi(AuthenticatedApi):
             result = acct.as_dict()
 
             # fill in some policy fields as they are useful to the clients
-            policy = self.policies.get_policy(acct.level, None)
+            policy = self.policies.get_policy(acct.level, "plc.vicci.cores")
+            if policy is None:
+                # there wasn't a policy associated with plc.vicci.cores. Try to find any policy.
+                # this shouldn't happen
+                policy = self.policies.get_policy(acct.level, None)
             if policy is not None:
                 result['term'] = policy.term
                 result['membershipFee'] = policy.membershipFee
@@ -791,6 +803,13 @@ class RemoteApi(AuthenticatedApi):
                     upgradeDict[x.name] = x.as_dict()
                 result['upgrades'] = upgradeDict
 
+                if want_bucket:
+                    hrn = str_to_hrn(orig_name)
+                    bucket_acct = self.accounts.get_account(name, "bucket")
+                    if bucket_acct is not None:
+                        enforcer = GacksEnforcer(self.accounts, self.policies, self.calendar, self.resources)
+                        result['bucketAnalysis'] = enforcer.check_bucket(hrn, policy, "plc.vicci.cores", [], acct, enforce=False)
+
             return result
         else:
             return None
@@ -1015,7 +1034,7 @@ class RemoteApi(AuthenticatedApi):
     def admin_mail_invoices(self, authToken_str, filter={}):
         (authToken, callerGID, objectGID) = self.authenticateToken(authToken_str, [])
 
-        return self.billing.mail_invoices(filter)
+        return self.billing.mail_invoices(filter, email_list=["smbaker@gmail.com"])
 
 
 
index 1151b6e..0219103 100644 (file)
@@ -77,22 +77,22 @@ class GacksEnforcer:
         if (maxUnitsConcurrent >= 0) and (total > maxUnitsConcurrent):
             raise GacksEnforcerTooManyConcurrent(total)
 
-    def check_bucket(self, name, policy, resource, handles, account):
+    def check_bucket(self, name, policy, resource, handles, account, enforce=True):
         # if policy doesn't use a bucket, then return
         if policy.bucketInRate<0 or policy.bucketMax<0:
-            return
-
-        print "check_bucket"
+            return []
 
         # load and/or initialize the bucket
-        bucketAccount = self.accounts.get_account(hrn_to_gacksid(name), "bucket", create_if_not_exist=True)
+        bucketAccount = self.accounts.get_account(account.name, "bucket", create_if_not_exist=True)
         bucketAccount.inRate = policy.bucketInRate
         bucketAccount.maxBalance = policy.bucketMax
         if (bucketAccount.created):
             bucketAccount.balance = policy.bucketInit
             bucketAccount.commit()
 
-        all_handles = self.calendar.query_overlap(handles[0].id, hasAllocator=name)
+        results = [(0, bucketAccount.balance, 0)]
+
+        all_handles = self.calendar.query_overlap(resource, hasAllocator=name)
         all_handles = all_handles + handles
 
         # sort them by start time
@@ -139,17 +139,19 @@ class GacksEnforcer:
 
             bucketAccount.apply_inRate(t)
 
-            print time.ctime(t), bucketAccount.balance, total
+            results.append((t, bucketAccount.balance, total))
             #for handle in active_handles:
             #    print "  ", time.ctime(handle.timeStart), time.ctime(handle.timeStop)
 
-            if total > bucketAccount.balance:
+            if (total > bucketAccount.balance) and (enforce):
                 raise GacksEnforcerBucketUnderflow(t, total, bucketAccount.balance)
 
             bucketAccount.adjust_balance(-total)
 
             t = t + BUCKET_QUANTUM
 
+        return results
+
     def check_handles(self, name, handles, account, reservationKind):
         id = handles[0].id
         policy = self.policies.get_policy(account.level, id)
index 2a14039..98d1c8b 100644 (file)
@@ -7,6 +7,12 @@ def slicename_to_gacksid(slicename):
 def hrn_to_gacksid(hrn):
     return hrn_to_pl_slicename(hrn)
 
+def str_to_hrn(s):
+    if s.startswith("hrn:"):
+        return s[4:]
+    else:
+        return None
+
 def str_to_gacksid(s):
     if s.startswith("gacksid:"):
         return s[8:]
index 3aac566..c74cd06 100644 (file)
@@ -166,7 +166,39 @@ $invoices = $gacksapi->get_invoice(NULL, NULL, NULL, NULL, $filter, FALSE);
 \r
 invoice_table($invoices, $account_name, $account_token, array());\r
 \r
-$toggle->end();\r
+//------------------------- bucket analysis --------------------------------\r
+\r
+$account_hrn = slice_to_hrn($account_name);\r
+$bucketAccount = $gacksapi->get_account(gackshrn($account_hrn), "user_bucket");\r
+\r
+if (($bucketAccount) && (array_key_exists("bucketAnalysis", $bucketAccount))) {\r
+    $toggle = new PlekitToggle ('account',"Bucket Analysis",\r
+                            array('bubble'=>'Show bucket analysis',\r
+                                  'visible'=>get_arg('show_bucket',true)));\r
+\r
+    $toggle->start();\r
+\r
+    $headers=array();\r
+    $headers["time"] = "string";\r
+    $headers["balance"] = "string";\r
+    $headers["in-use"] = "string";\r
+\r
+    $table = new PlekitTable("bucketAnalysis", $headers, 1);\r
+    $table->start();\r
+\r
+    $bucketAnalysis = $bucketAccount['bucketAnalysis'];\r
+    foreach ( $bucketAnalysis as $row ) {\r
+        $table->row_start();\r
+        $table->cell($row[0]);\r
+        $table->cell($row[1]);\r
+        $table->cell($row[2]);\r
+        $table->row_end();\r
+    }\r
+\r
+    $table->end();\r
+\r
+    $toggle->end();\r
+}\r
 \r
 include 'plc_footer.php';\r
 \r
index 626cd40..58d5a8d 100644 (file)
@@ -40,6 +40,8 @@ function l_gacks_advanced($value, $url)        { $eurl=urlencode($url); return "
 
 function gacksid($x) { return "gacksid:" . $x; }
 
+function gackshrn($x) { return "hrn:" . $x; }
+
 function slice_to_hrn($slice)
 {
    $slice = str_replace("_", ".", $slice);