[Autotest] Add staging thread count in devserver

Add a global variable to count staging thread. The count can be retrieved from
check_health call. Potential use of this count is to do load balancing across
available devservers.

BUG=chromium:246361
TEST=tested with run_suite with localhost setup as devserver.
DEPLOY=apache

Change-Id: Ie3c54457ce0378e4d12692acc0b4ef8715b3d619
Reviewed-on: https://gerrit.chromium.org/gerrit/57524
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Queue: Dan Shi <dshi@chromium.org>
Tested-by: Dan Shi <dshi@chromium.org>
diff --git a/devserver.py b/devserver.py
index 238a65d..bdc502b 100755
--- a/devserver.py
+++ b/devserver.py
@@ -50,6 +50,7 @@
 import subprocess
 import sys
 import tempfile
+import threading
 import types
 from logging import handlers
 
@@ -61,7 +62,6 @@
 import downloader
 import log_util
 
-
 # Module-local log function.
 def _Log(message, *args):
   return log_util.LogWithTag('DEVSERVER', message, *args)
@@ -375,6 +375,11 @@
 
   api = ApiRoot()
 
+  # Number of threads that devserver is staging images.
+  _staging_thread_count = 0
+  # Lock used to lock increasing/decreasing count.
+  _staging_thread_count_lock = threading.Lock()
+
   def __init__(self):
     self._builder = None
     self._telemetry_lock_dict = common_util.LockDict()
@@ -422,6 +427,7 @@
     return self.stage(archive_url=kwargs.get('archive_url'),
                       artifacts='full_payload,test_suites,stateful')
 
+
   @cherrypy.expose
   def stage(self, **kwargs):
     """Downloads and caches the artifacts from Google Storage URL.
@@ -464,10 +470,17 @@
     if not artifacts:
       raise DevServerError('No artifacts specified.')
 
-    downloader.Downloader(updater.static_dir, archive_url).Download(
-        artifacts.split(','))
+    with DevServerRoot._staging_thread_count_lock:
+      DevServerRoot._staging_thread_count += 1
+    try:
+      downloader.Downloader(updater.static_dir, archive_url).Download(
+          artifacts.split(','))
+    finally:
+      with DevServerRoot._staging_thread_count_lock:
+        DevServerRoot._staging_thread_count -= 1
     return 'Success'
 
+
   @cherrypy.expose
   def setup_telemetry(self, **kwargs):
     """Extracts and sets up telemetry
@@ -729,7 +742,9 @@
     """Collect the health status of devserver to see if it's ready for staging.
 
     @return: A JSON dictionary containing all or some of the following fields:
-        free_disk (int):        free disk space in GB
+        free_disk (int):            free disk space in GB
+        staging_thread_count (int): number of devserver threads currently
+            staging an image
     """
     # Get free disk space.
     stat = os.statvfs(updater.static_dir)
@@ -737,6 +752,7 @@
 
     return json.dumps({
         'free_disk': free_disk,
+        'staging_thread_count': DevServerRoot._staging_thread_count,
     })