diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:12:16 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:12:16 +0000 |
commit | 920c091ac3ee15079194c82ae8a7a18215f3f23c (patch) | |
tree | d28515d1e7732e2b6d077df1b4855ace3f4ac84f /tools/python/google/httpd_utils.py | |
parent | ae2c20f398933a9e86c387dcc465ec0f71065ffc (diff) | |
download | chromium_src-920c091ac3ee15079194c82ae8a7a18215f3f23c.zip chromium_src-920c091ac3ee15079194c82ae8a7a18215f3f23c.tar.gz chromium_src-920c091ac3ee15079194c82ae8a7a18215f3f23c.tar.bz2 |
Add tools to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/python/google/httpd_utils.py')
-rw-r--r-- | tools/python/google/httpd_utils.py | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/tools/python/google/httpd_utils.py b/tools/python/google/httpd_utils.py new file mode 100644 index 0000000..7f76ca6 --- /dev/null +++ b/tools/python/google/httpd_utils.py @@ -0,0 +1,219 @@ +#!/bin/env python +# Copyright 2008, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""A class to help start/stop a local apache http server.""" + +import logging +import optparse +import os +import subprocess +import sys +import time +import urllib + +import google.path_utils +import google.platform_utils + +class HttpdNotStarted(Exception): pass + +def ApacheConfigDir(start_dir): + """Returns a path to the directory holding the Apache config files.""" + return google.path_utils.FindUpward(start_dir, 'tools', 'python', + 'google', 'httpd_config') + + +def GetCygserverPath(start_dir, apache2=False): + """Returns the path to the directory holding cygserver.exe file.""" + cygserver_path = None + if apache2: + cygserver_path = google.path_utils.FindUpward(start_dir, 'third_party', + 'cygwin', 'usr', 'sbin') + return cygserver_path + + +def StartServer(document_root=None, output_dir=None, apache2=False): + """Starts a local server on port 8000 using the basic configuration files. + + Args: + document_root: If present, specifies the document root for the server; + otherwise, the filesystem's root (e.g., C:/ or /) will be used. + output_dir: If present, specifies where to put server logs; otherwise, + they'll be placed in the system's temp dir (e.g., $TEMP or /tmp). + apache2: boolean if true will cause this function to configure + for Apache 2.x as opposed to Apache 1.3.x + + Returns: the ApacheHttpd object that was created + """ + script_dir = google.path_utils.ScriptDir() + platform_util = google.platform_utils.PlatformUtility(script_dir) + if not output_dir: + output_dir = platform_util.GetTempDirectory() + if not document_root: + document_root = platform_util.GetFilesystemRoot() + apache_config_dir = ApacheConfigDir(script_dir) + if apache2: + httpd_conf_path = os.path.join(apache_config_dir, 'httpd2.conf') + else: + httpd_conf_path = os.path.join(apache_config_dir, 'httpd.conf') + mime_types_path = os.path.join(apache_config_dir, 'mime.types') + start_cmd = platform_util.GetStartHttpdCommand(output_dir, + httpd_conf_path, + mime_types_path, + document_root, + apache2=apache2) + stop_cmd = platform_util.GetStopHttpdCommand() + httpd = ApacheHttpd(start_cmd, stop_cmd, [8000], + cygserver_path=GetCygserverPath(script_dir, apache2)) + httpd.StartServer() + return httpd + + +def StopServers(apache2=False): + """Calls the platform's stop command on a newly created server, forcing it + to stop. + + The details depend on the behavior of the platform stop command. For example, + it's often implemented to kill all running httpd processes, as implied by + the name of this function. + + Args: + apache2: boolean if true will cause this function to configure + for Apache 2.x as opposed to Apache 1.3.x + """ + script_dir = google.path_utils.ScriptDir() + platform_util = google.platform_utils.PlatformUtility(script_dir) + httpd = ApacheHttpd('', platform_util.GetStopHttpdCommand(), [], + cygserver_path=GetCygserverPath(script_dir, apache2)) + httpd.StopServer(force=True) + + +class ApacheHttpd(object): + def __init__(self, start_command, stop_command, port_list, + cygserver_path=None): + """Args: + start_command: command list to call to start the httpd + stop_command: command list to call to stop the httpd if one has been + started. May kill all httpd processes running on the machine. + port_list: list of ports expected to respond on the local machine when + the server has been successfully started. + cygserver_path: Path to cygserver.exe. If specified, exe will be started + with server as well as stopped when server is stopped. + """ + self._http_server_proc = None + self._start_command = start_command + self._stop_command = stop_command + self._port_list = port_list + self._cygserver_path = cygserver_path + + def StartServer(self): + if self._http_server_proc: + return + if self._cygserver_path: + cygserver_exe = os.path.join(self._cygserver_path, "cygserver.exe") + cygbin = google.path_utils.FindUpward(cygserver_exe, 'third_party', + 'cygwin', 'bin') + env = os.environ + env['PATH'] += ";" + cygbin + subprocess.Popen(cygserver_exe, env=env) + logging.info('Starting http server') + self._http_server_proc = subprocess.Popen(self._start_command) + + # Ensure that the server is running on all the desired ports. + for port in self._port_list: + if not self._UrlIsAlive('http://127.0.0.1:%s/' % str(port)): + raise HttpdNotStarted('Failed to start httpd on port %s' % str(port)) + + def _UrlIsAlive(self, url): + """Checks to see if we get an http response from |url|. + We poll the url 5 times with a 1 second delay. If we don't + get a reply in that time, we give up and assume the httpd + didn't start properly. + + Args: + url: The URL to check. + Return: + True if the url is alive. + """ + wait_time = 5 + while wait_time > 0: + try: + response = urllib.urlopen(url) + # Server is up and responding. + return True + except IOError: + pass + wait_time -= 1 + # Wait a second and try again. + time.sleep(1) + + return False + + def StopServer(self, force=False): + """If we started an httpd.exe process, or if force is True, call + self._stop_command (passed in on init so it can be platform-dependent). + This will presumably kill it, and may also kill any other httpd.exe + processes that are running. + """ + if force or self._http_server_proc: + logging.info('Stopping http server') + kill_proc = subprocess.Popen(self._stop_command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + logging.info('%s\n%s' % (kill_proc.stdout.read(), + kill_proc.stderr.read())) + self._http_server_proc = None + if self._cygserver_path: + subprocess.Popen(["taskkill.exe", "/f", "/im", "cygserver.exe"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + +if '__main__' == __name__: + # Provide some command line params for starting/stopping the http server + # manually. + option_parser = optparse.OptionParser() + option_parser.add_option('-k', '--server', help='Server action (start|stop)') + option_parser.add_option('-r', '--root', help='Document root (optional)') + option_parser.add_option('-a', '--apache2', action='store_true', + default=False, help='Starts Apache 2 instead of Apache 1.3 (default).') + options, args = option_parser.parse_args() + + if not options.server: + print ("Usage: %s -k {start|stop} [-r document_root] [--apache2]" % + sys.argv[0]) + sys.exit(0) + + document_root = None + if options.root: + document_root = options.root + + if 'start' == options.server: + StartServer(document_root, apache2=options.apache2) + else: + StopServers(apache2=options.apache2) |