DevServer: Add a new devserver call to list all control files' content.

Now when a suite job is created, it calls devserver to list all control
files' path, and then call devserver X times to get the content of each
control file, where X equals to the length of the control file list.
Since a suite job may fetch more than 1000+ control files, and all the
thouands of calls are made over ssh. It's significantly slower than
previous directly calling devserver by http.

The new call 'list_suite_controls' goes through the lists of all control files
for a suite and a build, and return the contents of these control files.

BUG=chromium:602562
TEST=local run devserver
curl
http://127.0.0.1:8082/list_suite_controls?suite_name=suite_attr_wrapper&build=veyron_speedy-paladin/R52-8182.0.0-rc3
expected return:
["# Copyright control_file_content1", ..., "# Copyright
control_file_contentX"]

Change-Id: Id5e46e31212eda98d0e044be20cf657985f985bf
Reviewed-on: https://chromium-review.googlesource.com/338931
Commit-Ready: Xixuan Wu <[email protected]>
Tested-by: Xixuan Wu <[email protected]>
Reviewed-by: Dan Shi <[email protected]>
diff --git a/devserver.py b/devserver.py
index 54c25e3..26a46d3 100755
--- a/devserver.py
+++ b/devserver.py
@@ -932,6 +932,43 @@
       raise common_util.DevServerHTTPError(500, str(errmsg))
 
   @cherrypy.expose
+  def list_suite_controls(self, **kwargs):
+    """Return a list of contents of all known control files.
+
+    Example URL:
+      To List all control files' content:
+      http://dev-server/list_suite_controls?suite_name=bvt&
+      build=daisy_spring-release/R29-4279.0.0
+
+    Args:
+      build: The build i.e. x86-alex-release/R18-1514.0.0-a1-b1450.
+      suite_name: List the control files belonging to that suite.
+
+    Returns:
+      A list of contents of all control files are provided.
+    """
+    if not kwargs:
+      return _PrintDocStringAsHTML(self.controlfiles)
+
+    if 'build' not in kwargs:
+      raise common_util.DevServerHTTPError(500, 'Error: build= is required!')
+
+    if 'suite_name' not in kwargs:
+      raise common_util.DevServerHTTPError(500, 'Error: suite_name= is required!')
+
+    control_file_list = [
+        line.rstrip() for line in common_util.GetControlFileListForSuite(
+            updater.static_dir, kwargs['build'],
+            kwargs['suite_name']).splitlines()]
+
+    control_file_content_list = []
+    for control_path in control_file_list:
+      control_file_content_list.append(common_util.GetControlFile(
+          updater.static_dir, kwargs['build'], control_path))
+
+    return json.dumps(control_file_content_list)
+
+  @cherrypy.expose
   def controlfiles(self, **kwargs):
     """Return a control file or a list of all known control files.