gs_archive_server: add list_dir rpc

The list_dir RPC lists all the files available inside a specific GS
archive URL. This RPC is necessary to implement fake omaha.

BUG=chromium:1078188
TEST=Ran curl -XGET
http://localhost:<gsa_port>/<image_archive>/<board>/<version>. Full
output can be found at http://gpaste/5738938083835904.

Change-Id: I6553b345bff6b84cb74e4466ce38d52dcea8bb10
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2274923
Tested-by: Sanika Kulkarni <sanikak@chromium.org>
Commit-Queue: Sanika Kulkarni <sanikak@chromium.org>
Reviewed-by: Congbin Guo <guocb@chromium.org>
Auto-Submit: Sanika Kulkarni <sanikak@chromium.org>
diff --git a/gs_cache/gs_archive_server.py b/gs_cache/gs_archive_server.py
index 33d7a50..3430881 100644
--- a/gs_cache/gs_archive_server.py
+++ b/gs_cache/gs_archive_server.py
@@ -265,6 +265,19 @@
     self._caching_server = caching_server
 
   @cherrypy.expose
+  @_to_cherrypy_error
+  def list_dir(self, *args):
+    """Lists contents of specified GS bucket/<board>/version."""
+    path = 'gs://%s' % _check_file_extension('/'.join(args))
+    gs_cmd = ['gsutil', 'ls', path]
+    try:
+      proc = subprocess.Popen(gs_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+      content, error = proc.communicate()
+    except subprocess.CalledProcessError as e:
+      raise cherrypy.HTTPError(httplib.NOT_FOUND, e.output)
+    return content
+
+  @cherrypy.expose
   @cherrypy.config(**{'response.stream': True})
   @_to_cherrypy_error
   def list_member(self, *args):