1# Copyright (c) 2011 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Platform-specific utility methods shared by several scripts.""" 6 7import os 8import subprocess 9 10import google.path_utils 11 12 13class PlatformUtility(object): 14 def __init__(self, base_dir): 15 """Args: 16 base_dir: the base dir for running tests. 17 """ 18 self._base_dir = base_dir 19 self._httpd_cmd_string = None # used for starting/stopping httpd 20 self._bash = "/bin/bash" 21 22 def _UnixRoot(self): 23 """Returns the path to root.""" 24 return "/" 25 26 def GetFilesystemRoot(self): 27 """Returns the root directory of the file system.""" 28 return self._UnixRoot() 29 30 def GetTempDirectory(self): 31 """Returns the file system temp directory 32 33 Note that this does not use a random subdirectory, so it's not 34 intrinsically secure. If you need a secure subdir, use the tempfile 35 package. 36 """ 37 return os.getenv("TMPDIR", "/tmp") 38 39 def FilenameToUri(self, path, use_http=False, use_ssl=False, port=8000): 40 """Convert a filesystem path to a URI. 41 42 Args: 43 path: For an http URI, the path relative to the httpd server's 44 DocumentRoot; for a file URI, the full path to the file. 45 use_http: if True, returns a URI of the form http://127.0.0.1:8000/. 46 If False, returns a file:/// URI. 47 use_ssl: if True, returns HTTPS URL (https://127.0.0.1:8000/). 48 This parameter is ignored if use_http=False. 49 port: The port number to append when returning an HTTP URI 50 """ 51 if use_http: 52 protocol = 'http' 53 if use_ssl: 54 protocol = 'https' 55 return "%s://127.0.0.1:%d/%s" % (protocol, port, path) 56 return "file://" + path 57 58 def GetStartHttpdCommand(self, output_dir, 59 httpd_conf_path, mime_types_path, 60 document_root=None, apache2=False): 61 """Prepares the config file and output directory to start an httpd server. 62 Returns a list of strings containing the server's command line+args. 63 64 Args: 65 output_dir: the path to the server's output directory, for log files. 66 It will be created if necessary. 67 httpd_conf_path: full path to the httpd.conf file to be used. 68 mime_types_path: full path to the mime.types file to be used. 69 document_root: full path to the DocumentRoot. If None, the DocumentRoot 70 from the httpd.conf file will be used. Note that the httpd.conf 71 file alongside this script does not specify any DocumentRoot, so if 72 you're using that one, be sure to specify a document_root here. 73 apache2: boolean if true will cause this function to return start 74 command for Apache 2.x as opposed to Apache 1.3.x. This flag 75 is ignored on Linux (but preserved here for compatibility in 76 function signature with win), where apache2 is used always 77 """ 78 79 exe_name = "apache2" 80 cert_file = google.path_utils.FindUpward(self._base_dir, 'tools', 81 'python', 'google', 82 'httpd_config', 'httpd2.pem') 83 ssl_enabled = os.path.exists('/etc/apache2/mods-enabled/ssl.conf') 84 85 httpd_vars = { 86 "httpd_executable_path": 87 os.path.join(self._UnixRoot(), "usr", "sbin", exe_name), 88 "httpd_conf_path": httpd_conf_path, 89 "ssl_certificate_file": cert_file, 90 "document_root" : document_root, 91 "server_root": os.path.join(self._UnixRoot(), "usr"), 92 "mime_types_path": mime_types_path, 93 "output_dir": output_dir, 94 "ssl_mutex": "file:"+os.path.join(output_dir, "ssl_mutex"), 95 "ssl_session_cache": 96 "shmcb:" + os.path.join(output_dir, "ssl_scache") + "(512000)", 97 "user": os.environ.get("USER", "#%d" % os.geteuid()), 98 "lock_file": os.path.join(output_dir, "accept.lock"), 99 } 100 101 google.path_utils.MaybeMakeDirectory(output_dir) 102 103 # We have to wrap the command in bash 104 # -C: process directive before reading config files 105 # -c: process directive after reading config files 106 # Apache wouldn't run CGIs with permissions==700 unless we add 107 # -c User "<username>" 108 httpd_cmd_string = ( 109 '%(httpd_executable_path)s' 110 ' -f %(httpd_conf_path)s' 111 ' -c \'TypesConfig "%(mime_types_path)s"\'' 112 ' -c \'CustomLog "%(output_dir)s/access_log.txt" common\'' 113 ' -c \'ErrorLog "%(output_dir)s/error_log.txt"\'' 114 ' -c \'PidFile "%(output_dir)s/httpd.pid"\'' 115 ' -C \'User "%(user)s"\'' 116 ' -C \'ServerRoot "%(server_root)s"\'' 117 ' -c \'LockFile "%(lock_file)s"\'' 118 ) 119 120 if document_root: 121 httpd_cmd_string += ' -C \'DocumentRoot "%(document_root)s"\'' 122 123 if ssl_enabled: 124 httpd_cmd_string += ( 125 ' -c \'SSLCertificateFile "%(ssl_certificate_file)s"\'' 126 ' -c \'SSLMutex "%(ssl_mutex)s"\'' 127 ' -c \'SSLSessionCache "%(ssl_session_cache)s"\'' 128 ) 129 130 # Save a copy of httpd_cmd_string to use for stopping httpd 131 self._httpd_cmd_string = httpd_cmd_string % httpd_vars 132 133 httpd_cmd = [self._bash, "-c", self._httpd_cmd_string] 134 return httpd_cmd 135 136 def GetStopHttpdCommand(self): 137 """Returns a list of strings that contains the command line+args needed to 138 stop the http server used in the http tests. 139 140 This tries to fetch the pid of httpd (if available) and returns the 141 command to kill it. If pid is not available, kill all httpd processes 142 """ 143 144 if not self._httpd_cmd_string: 145 return ["true"] # Haven't been asked for the start cmd yet. Just pass. 146 # Add a sleep after the shutdown because sometimes it takes some time for 147 # the port to be available again. 148 return [self._bash, "-c", self._httpd_cmd_string + ' -k stop && sleep 5'] 149