Add a devserver call that can list staged contents of a build.

This will help with knowing why an update failed.

TEST=Executed the call on a local devserver. Added a unittest.
BUG=chromium:348097, chromium:349044, chromium:349047

Change-Id: I9c1a1a0ba9212852ad243eec728a010b5ed0b0fc
Reviewed-on: https://chromium-review.googlesource.com/189672
Tested-by: Prashanth B <beeps@chromium.org>
Reviewed-by: Dan Shi <dshi@chromium.org>
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Queue: Prashanth B <beeps@chromium.org>
diff --git a/devserver.py b/devserver.py
index 73fb39a..043e376 100755
--- a/devserver.py
+++ b/devserver.py
@@ -454,6 +454,32 @@
         artifacts, files))
 
   @cherrypy.expose
+  def list_image_dir(self, **kwargs):
+    """Take an archive url and list the contents in its staged directory.
+
+    Args:
+      kwargs:
+        archive_url: Google Storage URL for the build.
+
+    Example:
+      To list the contents of where this devserver should have staged
+      gs://image-archive/<board>-release/<build> call:
+      http://devserver_url:<port>/list_image_dir?archive_url=<gs://..>
+
+    Returns:
+      A string with information about the contents of the image directory.
+    """
+    archive_url = self._canonicalize_archive_url(kwargs.get('archive_url'))
+    download_helper = downloader.Downloader(updater.static_dir, archive_url)
+    try:
+      image_dir_contents = download_helper.ListBuildDir()
+    except build_artifact.ArtifactDownloadError as e:
+      return 'Cannot list the contents of staged artifacts. %s' % e
+    if not image_dir_contents:
+      return '%s has not been staged on this devserver.' % archive_url
+    return image_dir_contents
+
+  @cherrypy.expose
   def stage(self, **kwargs):
     """Downloads and caches the artifacts from Google Storage URL.