1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
49
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
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
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
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
93
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
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
118 return _writable_dir_check(ctx, ctx.env.get('ROS_HOME', None), 'ROS_HOME')
120 return _writable_dir_check(ctx, ctx.env.get('ROS_LOG_DIR', None), 'ROS_LOG_DIR')
122 return _writable_dir_check(ctx, ctx.env.get('ROS_TEST_RESULTS_DIR', None), 'ROS_TEST_RESULTS_DIR')
123
125
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
132 if 'ROSCONSOLE_CONFIG_FILE' in ctx.env:
133 return not isfile(ctx.env['ROSCONSOLE_CONFIG_FILE'])
134
136
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
147 uri = ctx.ros_master_uri
148 parsed = urlparse.urlparse(uri)
149 p = urlparse.urlparse(uri)
150 if not p[1]:
151 return
152 if not ':' in p[1]:
153 return
154 try:
155 splits = p[1].split(':')
156 if len(splits) != 2:
157 return
158
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
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
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
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
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
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
216