gfch100: add reboot, factory reset buttons to UI

	* b/29420365
	* also catch presterastats error and continue rather than
	  throw exception (so ui updates while rebooting)
      	* also fix tabs

Change-Id: I7699bb2db930b216b7957dd525c88e996619ca69
diff --git a/craftui/craftui.py b/craftui/craftui.py
index a87df55..33753e9 100755
--- a/craftui/craftui.py
+++ b/craftui/craftui.py
@@ -307,7 +307,17 @@
 
   def Configure(self):
     if self.validator.config == 'true':
-      Config.Run(['reboot'])
+      cmd = '(sleep 5; reboot)&'
+      os.system(cmd)
+
+
+class FactoryReset(Config):
+  """Factory Reset."""
+
+  def Configure(self):
+    if self.validator.config == 'true':
+      cmd = 'zap --i-really-mean-it --erase-backups && ((sleep 5; reboot) &)'
+      os.system(cmd)
 
 
 class CraftUI(object):
@@ -344,7 +354,8 @@
 
       'acm_on': GlaukusACM(VTrueFalse),
 
-      'reboot': Reboot(VTrueFalse)
+      'reboot': Reboot(VTrueFalse),
+      'factory_reset': FactoryReset(VTrueFalse)
   }
   ifmap = {
       'craft0': 'craft',
@@ -465,7 +476,10 @@
       stats = subprocess.check_output(['presterastats'])
     except subprocess.CalledProcessError as e:
       print 'warning: "presterastats" failed: ', e
-    data['switch'] = json.loads(stats)['port-interface-statistics']
+    try:
+      data['switch'] = json.loads(stats)['port-interface-statistics']
+    except ValueError as e:
+      print 'warning: "presterastats" json parse failed: ', e
 
   def AddVlans(self, data):
     """Run ip -d link and parse results for vlans."""
@@ -593,24 +607,6 @@
       print 'GET config HTML page'
       self.render(ui.wwwroot + '/config.thtml', peerurl='/config/?peer=1')
 
-  class RestartHandler(digest.DigestAuthMixin, tornado.web.RequestHandler):
-    """Restart the box."""
-
-    def get(self):
-      ui = self.settings['ui']
-      if not ui.Authenticate(self):
-        return
-      print 'displaying restart interstitial screen'
-      self.render('restarting.html')
-
-    def post(self):
-      ui = self.settings['ui']
-      if not ui.AuthenticateAdmin(self):
-        return
-      print 'user requested restart'
-      self.redirect('/restart')
-      os.system('(sleep 5; reboot) &')
-
   class JsonHandler(digest.DigestAuthMixin, tornado.web.RequestHandler):
     """Provides JSON-formatted content to be displayed in the UI."""
 
@@ -662,7 +658,6 @@
         (r'^/status/?$', self.StatusHandler),
         (r'^/config/?$', self.ConfigHandler),
         (r'^/content.json/?$', self.JsonHandler),
-        (r'^/restart/?$', self.RestartHandler),
         (r'^/static/([^/]*)$', tornado.web.StaticFileHandler,
          {'path': self.wwwroot + '/static'}),
     ]
diff --git a/craftui/craftui_test.sh b/craftui/craftui_test.sh
index 7c6a0c3..efa921b 100755
--- a/craftui/craftui_test.sh
+++ b/craftui/craftui_test.sh
@@ -134,9 +134,9 @@
 
     for auth in "" "$baduser_auth" "$badpass_auth"; do
       for n in status config content.json; do
-	testname "page $n bad auth ($url, $auth)"
-	$curl $auth $url/$n |& grep 'WWW-Authenticate: Digest'
-	check_success
+        testname "page $n bad auth ($url, $auth)"
+        $curl $auth $url/$n |& grep 'WWW-Authenticate: Digest'
+        check_success
       done
     done
 
@@ -185,10 +185,10 @@
     admin=$(echo -n admin | base64)
     new=$(echo -n ducky | base64)
     d='{ "config": [ { "password_guest": {
-	  "admin": "'"$admin"'",
-	  "new": "'"$new"'",
-	  "confirm": "'"$new"'"
-	} } ] }'
+          "admin": "'"$admin"'",
+          "new": "'"$new"'",
+          "confirm": "'"$new"'"
+        } } ] }'
     $curl $admin_auth -d "$d" $url/content.json |& grep '"error": 0}'
     check_success
 
@@ -196,10 +196,10 @@
     testname "password not base64 ($url)"
     new=ducky
     d='{ "config": [ { "password_guest": {
-	  "admin": "'"$admin"'",
-	  "new": "'"$new"'",
-	  "confirm": "'"$new"'"
-	} } ] }'
+          "admin": "'"$admin"'",
+          "new": "'"$new"'",
+          "confirm": "'"$new"'"
+        } } ] }'
     $curl $admin_auth -d "$d" $url/content.json |& grep '"error": 1}'
     check_success
 
diff --git a/craftui/www/config.thtml b/craftui/www/config.thtml
index 11736c3..5152015 100644
--- a/craftui/www/config.thtml
+++ b/craftui/www/config.thtml
@@ -247,15 +247,36 @@
         </table>
       </div>
     </div>
+
     <div class="tab">
       <input type="radio" id="tab-5" name="tab-group-1">
-      <label for="tab-5">Debug</label>
+      <label for="tab-5">Reboot</label>
+      <div class="content">
+        <input hidden id=reboot type=text value="true">
+        <input type=submit value=Reboot onclick="CraftUI.config('reboot')">
+        <span class="values">
+          <span id=reboot_result>...</span>
+        </span>
+        <br>
+        <br>
+        <input hidden id=factory_reset type=text value="true">
+        <input type=submit value="Factory Reset" onclick="CraftUI.config('factory_reset')">
+        <span class="values">
+          <span id=factory_reset_result>...</span>
+        </span>
+      </div>
+    </div>
+
+    <div class="tab">
+      <input type="radio" id="tab-6" name="tab-group-1">
+      <label for="tab-6">Debug</label>
       <div class="content">
         <b>refreshCount:</b><span class="values" id="platform/refreshCount">...</span><br>
         <b>unhandled xml:</b><span class="values">
           <textarea id=unhandled cols=60 rows=30>...</textarea></span><br>
       </div>
     </div>
+
   </div>
   <script src="static/craft.js"></script>
 </body>
diff --git a/craftui/www/status.thtml b/craftui/www/status.thtml
index 86a7ac8..2f4d402 100644
--- a/craftui/www/status.thtml
+++ b/craftui/www/status.thtml
@@ -440,10 +440,6 @@
       <input type="radio" id="tab-6" name="tab-group-1">
       <label for="tab-6">Debug</label>
       <div class="content">
-        <form action=/startisostream method=post>
-          {% module xsrf_form_html() %}
-          <button id="isostream_button">Run Test</button>
-        </form>
         <b>refreshCount:</b><span class="values" id="platform/refreshCount">...</span><br>
         <b>unhandled xml:</b><span class="values">
           <textarea id=unhandled cols=60 rows=30>...</textarea></span><br>