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 import urlparse
69 -def invalid_url(url):
70 """ 71 @return: error message if \a url is not a valid url. \a url is 72 allowed to be empty as that check is considered separately. 73 @rtype: str 74 """ 75 if not url: 76 return #caught by different rule 77 p = urlparse.urlparse(url) 78 if p[0] != 'http': 79 return "protocol is not 'http'" 80 if not p[1]: 81 return "address is missing" 82 if not ':' in p[1]: 83 return "port number is missing" 84 try: 85 splits = p[1].split(':') 86 if len(splits) != 2: 87 return "invalid address string [%s]"%p[1] 88 string.atoi(splits[1]) 89 except ValueError: 90 return "port number [%s] is invalid"%(splits[1])
91 92 # Error-checking functions for more advanced checks 93
94 -def ros_root_check(ctx, ros_root=None):
95 """ 96 @param ros_root: override ctx, useful for when ctx is not created yet 97 @type ros_root: str 98 """ 99 if ros_root is not None: 100 path = ros_root 101 else: 102 path = ctx.ros_root 103 if os.path.basename(os.path.normpath(path)) not in ['ros', 'rosbuild']: 104 return "ROS_ROOT [%s] must end in directory named 'ros'"%path
105
106 -def _writable_dir_check(ctx, path, name):
107 """ 108 If path is not None, validate that it is a writable directory 109 """ 110 if path is None: 111 return 112 if isfile(path): 113 return "%s [%s] must point to a directory, not a file"%(name, path) 114 if not os.access(path, os.W_OK): 115 return "%s [%s] is not writable"%(name, path)
116
117 -def ros_home_check(ctx):
118 return _writable_dir_check(ctx, ctx.env.get('ROS_HOME', None), 'ROS_HOME')
119 -def ros_log_dir_check(ctx):
120 return _writable_dir_check(ctx, ctx.env.get('ROS_LOG_DIR', None), 'ROS_LOG_DIR')
121 -def ros_test_results_dir_check(ctx):
122 return _writable_dir_check(ctx, ctx.env.get('ROS_TEST_RESULTS_DIR', None), 'ROS_TEST_RESULTS_DIR')
123
124 -def pythonpath_check(ctx):
125 # used to have a lot more checks here, but trying to phase out need for roslib on custom PYTHONPATH 126 path = ctx.pythonpath 127 roslib_count = len(set([p for p in paths(path) if 'roslib' in p])) 128 if roslib_count > 1: 129 return "Multiple roslib directories in PYTHONPATH (there should only be one)"
130
131 -def rosconsole_config_file_check(ctx):
132 if 'ROSCONSOLE_CONFIG_FILE' in ctx.env: 133 return not isfile(ctx.env['ROSCONSOLE_CONFIG_FILE'])
134
135 -def path_check(ctx):
136 # rosdeb setup can clobber local ros stuff, so try and detect this 137 path = ctx.env['PATH'] 138 idx = path.find('/usr/bin') 139 if idx < 0: 140 return 141 if os.path.exists('/usr/lib/ros/'): 142 rr_idx = path.find(ctx.ros_root) 143 if rr_idx > -1 and rr_idx > idx: 144 return True
145
146 -def ros_master_uri_hostname(ctx):
147 uri = ctx.ros_master_uri 148 parsed = urlparse.urlparse(uri) 149 p = urlparse.urlparse(uri) 150 if not p[1]: 151 return #caught by different rule 152 if not ':' in p[1]: 153 return #caught by different rule 154 try: 155 splits = p[1].split(':') 156 if len(splits) != 2: 157 return #caught by different rule 158 #TODO IPV6: only check for IPv6 when IPv6 is enabled 159 socket.getaddrinfo(splits[0], 0, 0, 0, socket.SOL_TCP) 160 161 except socket.gaierror, e: 162 return "Unknown host %s"%splits[0]
163 164 # Error/Warning Rules 165 166 environment_warnings = [ 167 (path_check, 168 "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"), 169 (lambda ctx: ctx.ros_package_path is None, 170 "ROS_PACKAGE_PATH is not set. This is not required, but is unusual"), 171 (lambda ctx: len(paths(ctx.ros_package_path)) == 0, 172 "ROS_PACKAGE_PATH is empty. This is not required, but is unusual"), 173 (lambda ctx: not ctx.ros_master_uri, 174 "ROS_MASTER_URI is empty. This is not required, but is unusual"), 175 (ros_master_uri_hostname, 176 "Cannot resolve hostname in ROS_MASTER_URI [%(ros_master_uri)s]"), 177 (rosconsole_config_file_check, 178 "ROS_CONSOLE_CONFIG_FILE does not point to an existing file"), 179 ] 180 181 environment_errors = [ 182 # ROS_ROOT 183 (lambda ctx: not isdir(ctx.ros_root), 184 "ROS_ROOT [%(ros_root)s] does not point to a directory"), 185 (ros_root_check, 186 "ROS_ROOT is invalid: "), 187 188 # ROS_PACKAGE_PATH 189 (lambda ctx: [d for d in paths(ctx.ros_package_path) if d and isfile(d)], 190 "Path(s) in ROS_PACKAGE_PATH [%(ros_package_path)s] points to a file instead of a directory: "), 191 (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')))], 192 "Not all paths in ROS_PACKAGE_PATH [%(ros_package_path)s] point to an existing directory: "), 193 194 # PYTHONPATH 195 (lambda ctx: [d for d in paths(ctx.pythonpath) if d and not isdir(d)], 196 "Not all paths in PYTHONPATH [%(pythonpath)s] point to a directory: "), 197 (pythonpath_check, 198 "PYTHONPATH [%(pythonpath)s] is invalid: "), 199 200 # ROS_HOME, ROS_LOG_DIR, ROS_TEST_RESULTS_DIR 201 (ros_home_check, "ROS_HOME is invalid: "), 202 (ros_log_dir_check, "ROS_LOG_DIR is invalid: "), 203 (ros_test_results_dir_check, "ROS_TEST_RESULTS_DIR is invalid: "), 204 205 (lambda ctx: invalid_url(ctx.ros_master_uri), 206 "ROS_MASTER_URI [%(ros_master_uri)s] is not a valid URL: "), 207 208 ] 209
210 -def wtf_check_environment(ctx):
211 #TODO: check ROS_BOOST_ROOT 212 for r in environment_warnings: 213 warning_rule(r, r[0](ctx), ctx) 214 for r in environment_errors: 215 error_rule(r, r[0](ctx), ctx)
216