Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/core/admin.py b/xos/core/admin.py
index 97e76ff..675b8c2 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -34,10 +34,41 @@
 
 def backend_icon(obj):
     (icon, tooltip) = obj.get_backend_icon()
+
     icon_url = ICON_URLS.get(icon, "unknown")
 
+    (exponent,last_success,last_failure,failures) = obj.get_backend_details()
+
+    # FIXME: Need to clean this up by separating Javascript from Python
+    if (obj.pk):
+        script = """
+        <script type="text/javascript">
+            $(document).ready(function () {
+                $("#show_details_%d").click(function () {
+                    $("#status%d").dialog({modal: true, height: 200, width: 200 });
+                });
+            });
+        </script>
+        """%(obj.pk,obj.pk)
+
+        div = """
+        <div style="display:none;" id="status%d" title="Details">
+                <p>Backoff Exponent: %r</p>
+                <p>Last Success: %r</p>
+                <p>Failures: %r</p>
+                <p>Last Failure: %r</p>
+                    </div>
+        """%(obj.pk,exponent,last_success,failures,last_failure)
+        a = '<a id="show_details_%d" href="#">'%obj.pk
+        astop = '</a>'
+    else:
+        div = ''
+        script = ''
+        a = ''
+        astop = ''
+
     if tooltip:
-        return '<span style="min-width:16px;" title="%s"><img src="%s"></span>' % (tooltip, icon_url)
+        return '%s %s <span style="min-width:16px;" title="%s">%s<img src="%s">%s</span>' % (script, div, tooltip, a,  icon_url, astop)
     else:
         return '<span style="min-width:16px;"><img src="%s"></span>' % icon_url
 
diff --git a/xos/core/models/plcorebase.py b/xos/core/models/plcorebase.py
index 360792f..9f7aa4c 100644
--- a/xos/core/models/plcorebase.py
+++ b/xos/core/models/plcorebase.py
@@ -1,4 +1,5 @@
 import datetime
+import json
 import os
 import sys
 from django import db
@@ -118,6 +119,38 @@
             validators[field.name] = l
         return validators
 
+    def get_backend_details(self):
+        try:
+            scratchpad = json.loads(self.backend_register)
+        except AttributeError:
+            return (None, None, None, None)
+
+        try:
+            exponent = scratchpad['exponent']
+        except KeyError:
+            exponent = None
+
+        try:
+            last_success_time = scratchpad['last_success']
+            dt = datetime.datetime.fromtimestamp(last_success_time)
+            last_success = dt.strftime("%Y-%m-%d %H:%M")
+        except KeyError:
+            last_success = None
+
+        try:
+            failures = scratchpad['failures']
+        except KeyError:
+            failures=None
+
+        try:
+            last_failure_time = scratchpad['last_failure']
+            dt = datetime.datetime.fromtimestamp(last_failure_time)
+            last_failure = dt.strftime("%Y-%m-%d %H:%M")
+        except KeyError:
+            last_failure = None
+
+        return (exponent, last_success, last_failure, failures)
+
     def get_backend_icon(self):
         is_perfect = (self.backend_status is not None) and self.backend_status.startswith("1 -")
         is_good = (self.backend_status is not None) and (self.backend_status.startswith("0 -") or self.backend_status.startswith("1 -"))
diff --git a/xos/model_policies/model_policy_ControllerSlice.py b/xos/model_policies/model_policy_ControllerSlice.py
index 1861c66..bfe7995 100644
--- a/xos/model_policies/model_policy_ControllerSlice.py
+++ b/xos/model_policies/model_policy_ControllerSlice.py
@@ -8,9 +8,18 @@
         except:
             his_status_code = 0
  
+        fields = []
         if (my_status_code not in [0,his_status_code]):
             controller_slice.slice.backend_status = controller_slice.backend_status
-            controller_slice.slice.save(update_fields = ['backend_status'])
+            fields+=['backend_status']
+
+        if (controller_slice.backend_register != controller_slice.slice.backend_register):
+            controller_slice.slice.backend_register = controller_slice.backend_register
+            fields+=['backend_register']
+
+        controller_slice.slice.save(update_fields = fields)
+
+        
     except Exception,e:
         print str(e)	
         pass
diff --git a/xos/openstack_observer/syncstep.py b/xos/openstack_observer/syncstep.py
index 21327d7..0a25c58 100644
--- a/xos/openstack_observer/syncstep.py
+++ b/xos/openstack_observer/syncstep.py
@@ -10,6 +10,7 @@
 from observer.ansible import *
 from dependency_walker import *
 
+from time import time
 import json
 import time
 import pdb
@@ -228,7 +229,7 @@
                     else:
                         self.sync_record(o)
                         o.enacted = datetime.now() # Is this the same timezone? XXX
-                        scratchpad = {'next_run':0, 'exponent':0}
+                        scratchpad = {'next_run':0, 'exponent':0, 'last_success':time.time()}
                         o.backend_register = json.dumps(scratchpad)
                         o.backend_status = "1 - OK"
                         o.save(update_fields=['enacted','backend_status','backend_register'])
@@ -258,7 +259,7 @@
                         scratchpad['exponent']
                     except:
                         logger.log_exc("Exception while updating scratchpad")
-                        scratchpad = {'next_run':0, 'exponent':0}
+                        scratchpad = {'next_run':0, 'exponent':0, 'last_success':time.time(),'failures':0}
 
                     # Second failure
                     if (scratchpad['exponent']):
@@ -271,7 +272,17 @@
                             delay=8*60*60
                         scratchpad['next_run'] = time.time() + delay
 
-                    scratchpad['exponent']+=1
+                    try:
+                        scratchpad['exponent']+=1
+                    except:
+                        scratchpad['exponent']=1
+
+                    try:
+                        scratchpad['failures']+=1
+                    except KeyError:
+                        scratchpad['failures']=1
+
+                    scratchpad['last_failure']=time.time()
 
                     o.backend_register = json.dumps(scratchpad)