Package roswtf :: Module environment
[frames] | no frames]

Source Code for Module roswtf.environment

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2009, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id$ 
 34   
 35  """ 
 36  Rules for checking ROS environment state. 
 37  """ 
 38   
 39  import os 
 40  import socket 
 41  import stat 
 42  import string 
 43  import sys 
 44   
 45  from os.path import isdir, isfile 
 46  from roswtf.rules import warning_rule, error_rule 
 47   
 48  #TODO: unit tests 
 49   
50 -def paths(path):
51 """ 52 @return: paths contained in path variable. path must conform to OS 53 conventions for path separation (i.e. colon-separated on Unix) 54 @rtype: [str] 55 """ 56 if path: 57 return path.split(os.pathsep) 58 return []
59
60 -def is_executable(path):
61 """ 62 @return: True if path has executable permissions 63 @rtype: bool 64 """ 65 mode = os.stat(path)[stat.ST_MODE] 66 return mode & (stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
67 68 try: 69 from urllib.parse import urlparse #Python 3 70 except ImportError: 71 from urlparse import urlparse #Python 2 72
73 -def invalid_url(url):
74 """ 75 @return: error message if \a url is not a valid url. \a url is 76 allowed to be empty as that check is considered separately. 77 @rtype: str 78 """ 79 if not url: 80 return #caught by different rule 81 p = urlparse(url) 82 if p[0] != 'http': 83 return "protocol is not 'http'" 84 if not p[1]: 85 return "address is missing" 86 if not ':' in p[1]: 87 return "port number is missing" 88 try: 89 splits = p[1].split(':') 90 if len(splits) != 2: 91 return "invalid address string [%s]"%p[1] 92 int(splits[1]) 93 except ValueError: 94 return "port number [%s] is invalid"%(splits[1])
95 96 # Error-checking functions for more advanced checks 97
98 -def ros_root_check(ctx, ros_root=None):
99 """ 100 @param ros_root: override ctx, useful for when ctx is not created yet 101 @type ros_root: str 102 """ 103 if ros_root is not None: 104 path = ros_root 105 else: 106 path = ctx.ros_root 107 if os.path.basename(os.path.normpath(path)) not in ['ros', 'rosbuild']: 108 return "ROS_ROOT [%s] must end in directory named 'ros'"%path
109
110 -def _writable_dir_check(ctx, path, name):
111 """ 112 If path is not None, validate that it is a writable directory 113 """ 114 if path is None: 115 return 116 if isfile(path): 117 return "%s [%s] must point to a directory, not a file"%(name, path) 118 if not os.access(path, os.W_OK): 119 return "%s [%s] is not writable"%(name, path)
120
121 -def ros_home_check(ctx):
122 return _writable_dir_check(ctx, ctx.env.get('ROS_HOME', None), 'ROS_HOME')
123 -def ros_log_dir_check(ctx):
124 return _writable_dir_check(ctx, ctx.env.get('ROS_LOG_DIR', None), 'ROS_LOG_DIR')
125 -def ros_test_results_dir_check(ctx):
126 return _writable_dir_check(ctx, ctx.env.get('ROS_TEST_RESULTS_DIR', None), 'ROS_TEST_RESULTS_DIR')
127
128 -def pythonpath_check(ctx):
129 # used to have a lot more checks here, but trying to phase out need for roslib on custom PYTHONPATH 130 path = ctx.pythonpath 131 roslib_count = len(set([p for p in paths(path) if 'roslib' in p])) 132 if roslib_count > 1: 133 return "Multiple roslib directories in PYTHONPATH (there should only be one)"
134
135 -def rosconsole_config_file_check(ctx):
136 if 'ROSCONSOLE_CONFIG_FILE' in ctx.env: 137 return not isfile(ctx.env['ROSCONSOLE_CONFIG_FILE'])
138
139 -def path_check(ctx):
140 # rosdeb setup can clobber local ros stuff, so try and detect this 141 path = ctx.env['PATH'] 142 idx = path.find('/usr/bin') 143 if idx < 0: 144 return 145 if os.path.exists('/usr/lib/ros/'): 146 rr_idx = path.find(ctx.ros_root) 147 if rr_idx > -1 and rr_idx > idx: 148 return True
149
150 -def ros_master_uri_hostname(ctx):
151 uri = ctx.ros_master_uri 152 parsed = urlparse(uri) 153 p = urlparse(uri) 154 if not p[1]: 155 return #caught by different rule 156 if not ':' in p[1]: 157 return #caught by different rule 158 try: 159 splits = p[1].split(':') 160 if len(splits) != 2: 161 return #caught by different rule 162 #TODO IPV6: only check for IPv6 when IPv6 is enabled 163 socket.getaddrinfo(splits[0], 0, 0, 0, socket.SOL_TCP) 164 165 except socket.gaierror: 166 return "Unknown host %s"%splits[0]
167 168 # Error/Warning Rules 169 170 environment_warnings = [ 171 (path_check, 172 "PATH has /usr/bin set before ROS_ROOT/bin, which can cause problems as there is system install of ROS on this machine. You may wish to put ROS_ROOT/bin first"), 173 (lambda ctx: ctx.ros_package_path is None, 174 "ROS_PACKAGE_PATH is not set. This is not required, but is unusual"), 175 (lambda ctx: len(paths(ctx.ros_package_path)) == 0, 176 "ROS_PACKAGE_PATH is empty. This is not required, but is unusual"), 177 (lambda ctx: not ctx.ros_master_uri, 178 "ROS_MASTER_URI is empty. This is not required, but is unusual"), 179 (ros_master_uri_hostname, 180 "Cannot resolve hostname in ROS_MASTER_URI [%(ros_master_uri)s]"), 181 (rosconsole_config_file_check, 182 "ROS_CONSOLE_CONFIG_FILE does not point to an existing file"), 183 ] 184 185 environment_errors = [ 186 # ROS_ROOT 187 (lambda ctx: not isdir(ctx.ros_root), 188 "ROS_ROOT [%(ros_root)s] does not point to a directory"), 189 (ros_root_check, 190 "ROS_ROOT is invalid: "), 191 192 # ROS_PACKAGE_PATH 193 (lambda ctx: [d for d in paths(ctx.ros_package_path) if d and isfile(d)], 194 "Path(s) in ROS_PACKAGE_PATH [%(ros_package_path)s] points to a file instead of a directory: "), 195 (lambda ctx: [d for d in paths(ctx.ros_package_path) if d and not isdir(d) and not (os.path.basename(d) == 'stacks' and os.path.exists(os.path.join(os.path.dirname(d), '.catkin')))], 196 "Not all paths in ROS_PACKAGE_PATH [%(ros_package_path)s] point to an existing directory: "), 197 198 # PYTHONPATH 199 (lambda ctx: [d for d in paths(ctx.pythonpath) if d and not isdir(d)], 200 "Not all paths in PYTHONPATH [%(pythonpath)s] point to a directory: "), 201 (pythonpath_check, 202 "PYTHONPATH [%(pythonpath)s] is invalid: "), 203 204 # ROS_HOME, ROS_LOG_DIR, ROS_TEST_RESULTS_DIR 205 (ros_home_check, "ROS_HOME is invalid: "), 206 (ros_log_dir_check, "ROS_LOG_DIR is invalid: "), 207 (ros_test_results_dir_check, "ROS_TEST_RESULTS_DIR is invalid: "), 208 209 (lambda ctx: invalid_url(ctx.ros_master_uri), 210 "ROS_MASTER_URI [%(ros_master_uri)s] is not a valid URL: "), 211 212 ] 213
214 -def wtf_check_environment(ctx):
215 #TODO: check ROS_BOOST_ROOT 216 for r in environment_warnings: 217 warning_rule(r, r[0](ctx), ctx) 218 for r in environment_errors: 219 error_rule(r, r[0](ctx), ctx)
220