1*9c5db199SXin Li# Copyright 2017 The Chromium OS Authors. All rights reserved. 2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 3*9c5db199SXin Li# found in the LICENSE file. 4*9c5db199SXin Lifrom contextlib import contextmanager 5*9c5db199SXin Li 6*9c5db199SXin Liimport logging 7*9c5db199SXin Liimport multiprocessing 8*9c5db199SXin Liimport os 9*9c5db199SXin Liimport shutil 10*9c5db199SXin Liimport tempfile 11*9c5db199SXin Liimport six.moves.socketserver 12*9c5db199SXin Liimport six.moves.SimpleHTTPServer 13*9c5db199SXin Li 14*9c5db199SXin Liimport common 15*9c5db199SXin Lifrom autotest_lib.client.bin import utils 16*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 17*9c5db199SXin Lifrom autotest_lib.site_utils.lxc import constants 18*9c5db199SXin Li 19*9c5db199SXin Li 20*9c5db199SXin Li@contextmanager 21*9c5db199SXin Lidef serve_locally(file_path): 22*9c5db199SXin Li """Starts an http server on the localhost, to serve the given file. 23*9c5db199SXin Li 24*9c5db199SXin Li Copies the given file to a temporary location, then starts a local http 25*9c5db199SXin Li server to serve that file. Intended for use with unit tests that require 26*9c5db199SXin Li some URL to download a file (see testInstallSsp as an example). 27*9c5db199SXin Li 28*9c5db199SXin Li @param file_path: The path of the file to serve. 29*9c5db199SXin Li 30*9c5db199SXin Li @return The URL at which the file will be served. 31*9c5db199SXin Li """ 32*9c5db199SXin Li p = None 33*9c5db199SXin Li try: 34*9c5db199SXin Li # Copy the target file into a tmpdir for serving. 35*9c5db199SXin Li tmpdir = tempfile.mkdtemp() 36*9c5db199SXin Li shutil.copy(file_path, tmpdir) 37*9c5db199SXin Li 38*9c5db199SXin Li httpd = six.moves.socketserver.TCPServer( 39*9c5db199SXin Li ('', 0), six.moves.SimpleHTTPServer.SimpleHTTPRequestHandler) 40*9c5db199SXin Li port = httpd.socket.getsockname()[1] 41*9c5db199SXin Li 42*9c5db199SXin Li # Start the http daemon in the tmpdir to serve the file. 43*9c5db199SXin Li def serve(): 44*9c5db199SXin Li """Serves the tmpdir.""" 45*9c5db199SXin Li os.chdir(tmpdir) 46*9c5db199SXin Li httpd.serve_forever() 47*9c5db199SXin Li p = multiprocessing.Process(target=serve) 48*9c5db199SXin Li p.daemon = True 49*9c5db199SXin Li p.start() 50*9c5db199SXin Li 51*9c5db199SXin Li utils.poll_for_condition( 52*9c5db199SXin Li condition=lambda: http_up(port), 53*9c5db199SXin Li timeout=constants.NETWORK_INIT_TIMEOUT, 54*9c5db199SXin Li sleep_interval=constants.NETWORK_INIT_CHECK_INTERVAL) 55*9c5db199SXin Li url = 'http://127.0.0.1:{port}/{filename}'.format( 56*9c5db199SXin Li port=port, filename=os.path.basename(file_path)) 57*9c5db199SXin Li logging.debug('Serving %s as %s', file_path, url) 58*9c5db199SXin Li yield url 59*9c5db199SXin Li finally: 60*9c5db199SXin Li if p is not None: 61*9c5db199SXin Li p.terminate() 62*9c5db199SXin Li shutil.rmtree(tmpdir) 63*9c5db199SXin Li 64*9c5db199SXin Li 65*9c5db199SXin Lidef http_up(port): 66*9c5db199SXin Li """Checks for an http server on localhost:port. 67*9c5db199SXin Li 68*9c5db199SXin Li @param port: The port to check. 69*9c5db199SXin Li """ 70*9c5db199SXin Li try: 71*9c5db199SXin Li utils.run('curl --head http://127.0.0.1:%d' % port) 72*9c5db199SXin Li return True 73*9c5db199SXin Li except error.CmdError: 74*9c5db199SXin Li return False 75