nebraska: Allow passing critical_update=true in the URL

We need a way to respond to an update/install request with
'deadline=now' (means it is a critical update). This is mostly for
tests and cros flash because the updater does not do update if the OOBE
is not processed yet. So in most cases we need to request a critical
update so the AU does not block it.

This CL allows calling into nebraska server with URLs like:
http://<ip>:<port>/critical_update=true so we can respond with
'deadline=now'

BUG=chromium:920404
TEST= sudo ./nebraska.py --port 10000;
Then this for non critical updates:
  curl -X POST -d @request.xml http://localhost:10000;
And this for critical updates:
  curl -X POST -d @request.xml http://localhost:10000/critical_update=true;
TEST=platform/dev/nebraska/run_unittests

Change-Id: Ic83783150865061da8a9d99f94595c1fa9c11f10
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/1708892
Tested-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Nicolas Norvez <norvez@chromium.org>
Commit-Queue: Amin Hassani <ahassani@chromium.org>
diff --git a/nebraska/nebraska.py b/nebraska/nebraska.py
index 0a598a5..430313c 100755
--- a/nebraska/nebraska.py
+++ b/nebraska/nebraska.py
@@ -19,6 +19,7 @@
 import sys
 import threading
 import traceback
+import urlparse
 
 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
 from datetime import datetime, time
@@ -725,14 +726,23 @@
     """HTTP request handler for Omaha requests."""
 
     def do_POST(self):
-      """Responds to XML-formatted Omaha requests."""
+      """Responds to XML-formatted Omaha requests.
+
+      The URL path can be like:
+        - https://<ip>:<port>/?critical_update=true # For requesting a critical
+          update response
+      """
       request_len = int(self.headers.getheader('content-length'))
       request = self.rfile.read(request_len)
       logging.debug('Received request: %s', request)
 
+      parsed_query = urlparse.parse_qs(urlparse.urlparse(self.path).query)
+      critical_update = parsed_query.get('critical_update', []) == ['true']
+
       try:
         request_obj = Request(request)
-        response = self.server.owner.nebraska.GetResponseToRequest(request_obj)
+        response = self.server.owner.nebraska.GetResponseToRequest(
+            request_obj, critical_update=critical_update)
       except Exception as err:
         logging.error('Failed to handle request (%s)', str(err))
         logging.error(traceback.format_exc())
diff --git a/nebraska/nebraska_unittest.py b/nebraska/nebraska_unittest.py
index 2bd4d7b..762c2bc 100755
--- a/nebraska/nebraska_unittest.py
+++ b/nebraska/nebraska_unittest.py
@@ -28,6 +28,7 @@
   # pylint: disable=super-init-not-called
   def __init__(self):
     self.headers = mock.MagicMock()
+    self.path = mock.MagicMock()
     self.send_response = mock.MagicMock()
     self.send_error = mock.MagicMock()
     self.send_header = mock.MagicMock()
@@ -64,18 +65,30 @@
   def testDoPostSuccess(self):
     """Tests do_POST success."""
     nebraska_handler = MockNebraskaHandler()
-    test_response = "foobar"
+    test_response = 'foobar'
 
     with mock.patch('nebraska.Nebraska.GetResponseToRequest') as response_mock:
       with mock.patch('nebraska.Request') as _:
         response_mock.return_value = test_response
         nebraska_handler.do_POST()
 
+        response_mock.assert_called_once_with(mock.ANY, critical_update=False)
         nebraska_handler.send_response.assert_called_once_with(200)
         nebraska_handler.send_header.assert_called_once()
         nebraska_handler.end_headers.assert_called_once()
         nebraska_handler.wfile.write.assert_called_once_with(test_response)
 
+  def testDoPostSuccessWithCriticalUpdate(self):
+    """Tests do_POST success with critical update."""
+    nebraska_handler = MockNebraskaHandler()
+    nebraska_handler.path = '/?critical_update=true'
+
+    with mock.patch('nebraska.Nebraska.GetResponseToRequest') as response_mock:
+      with mock.patch('nebraska.Request') as _:
+        nebraska_handler.do_POST()
+
+        response_mock.assert_called_once_with(mock.ANY, critical_update=True)
+
   def testDoPostInvalidRequest(self):
     """Test do_POST invalid request."""
     nebraska_handler = MockNebraskaHandler()