37 from __future__
import with_statement
39 roslib.load_manifest(
'pr2_computer_monitor')
45 from threading
import Timer
47 from time
import sleep
52 from diagnostic_msgs.msg
import DiagnosticArray, DiagnosticStatus, KeyValue
56 if sys.version_info[:3] == (2, 7, 3):
58 threading._DummyThread._Thread__stop =
lambda x: 42
67 stat_dict = { 0:
'OK', 1:
'Warning', 2:
'Error' }
68 temp_dict = { 0:
'OK', 1:
'Hot', 2:
'Critical Hot' }
69 usage_dict = { 0:
'OK', 1:
'Low Disk Space', 2:
'Very Low Disk Space' }
71 REMOVABLE = [
'/dev/sda']
76 hd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
77 hd_sock.connect((hostname, port))
80 newdat = hd_sock.recv(1024)
83 newdat = newdat.decode()
84 sock_data = sock_data + newdat
87 sock_vals = sock_data.split(
'|')
95 while idx + 5 < len(sock_vals):
96 this_drive = sock_vals[idx + 1]
97 this_make = sock_vals[idx + 2]
98 this_temp = sock_vals[idx + 3]
102 if this_make
in makes:
106 drives.append(this_drive)
107 makes.append(this_make)
108 temps.append(this_temp)
112 return True, drives, makes, temps
114 rospy.logerr(traceback.format_exc())
115 return False, [
'Exception' ], [ traceback.format_exc() ], [ 0 ]
118 time_since_update = rospy.get_time() - last_update_time
121 if time_since_update > 20
and time_since_update <= 35:
122 stale_status =
'Lagging'
123 if stat.level == DiagnosticStatus.OK:
124 stat.message = stale_status
125 elif stat.message.find(stale_status) < 0:
126 stat.message =
', '.join([stat.message, stale_status])
127 stat.level = max(stat.level, DiagnosticStatus.WARN)
128 if time_since_update > 35:
129 stale_status =
'Stale'
130 if stat.level == DiagnosticStatus.OK:
131 stat.message = stale_status
132 elif stat.message.find(stale_status) < 0:
133 stat.message =
', '.join([stat.message, stale_status])
134 stat.level = max(stat.level, DiagnosticStatus.ERROR)
138 stat.values.insert(0, KeyValue(key =
'Update Status', value = stale_status))
139 stat.values.insert(1, KeyValue(key =
'Time Since Update', value = str(time_since_update)))
142 def __init__(self, hostname, diag_hostname, home_dir = ''):
148 rospy.logwarn(
'Not warning for HD temperatures is deprecated. This will be removed in D-turtle')
151 self.
_diag_pub = rospy.Publisher(
'/diagnostics', DiagnosticArray, queue_size=10)
161 self.
_temp_stat.name =
"%s HD Temperature" % diag_hostname
162 self.
_temp_stat.level = DiagnosticStatus.ERROR
165 self.
_temp_stat.values = [ KeyValue(key =
'Update Status', value =
'No Data'),
166 KeyValue(key =
'Time Since Last Update', value =
'N/A') ]
172 self.
_usage_stat.name =
'%s HD Usage' % diag_hostname
173 self.
_usage_stat.values = [ KeyValue(key =
'Update Status', value =
'No Data' ),
174 KeyValue(key =
'Time Since Last Update', value =
'N/A') ]
190 if rospy.is_shutdown():
195 diag_strs = [ KeyValue(key =
'Update Status', value =
'OK' ) ,
196 KeyValue(key =
'Time Since Last Update', value =
'0' ) ]
197 diag_level = DiagnosticStatus.OK
202 for index
in range(0, len(drives)):
205 if not temp.isnumeric()
and drives[index]
not in REMOVABLE:
206 temp_level = DiagnosticStatus.ERROR
208 elif not temp.isnumeric()
and drives[index]
in REMOVABLE:
209 temp_level = DiagnosticStatus.OK
212 temp_level = DiagnosticStatus.OK
213 if float(temp) > hd_temp_warn:
214 temp_level = DiagnosticStatus.WARN
215 if float(temp) > hd_temp_error:
216 temp_level = DiagnosticStatus.ERROR
218 diag_level = max(diag_level, temp_level)
220 diag_strs.append(KeyValue(key =
'Disk %d Temp Status' % index, value = temp_dict[temp_level]))
221 diag_strs.append(KeyValue(key =
'Disk %d Mount Pt.' % index, value = drives[index]))
222 diag_strs.append(KeyValue(key =
'Disk %d Device ID' % index, value = makes[index]))
223 diag_strs.append(KeyValue(key =
'Disk %d Temp' % index, value = temp))
226 diag_level = DiagnosticStatus.ERROR
234 self.
_temp_stat.message = temp_dict[diag_level]
241 if not rospy.is_shutdown():
248 if rospy.is_shutdown():
253 diag_vals = [ KeyValue(key =
'Update Status', value =
'OK' ),
254 KeyValue(key =
'Time Since Last Update', value =
'0' ) ]
255 diag_level = DiagnosticStatus.OK
259 p = subprocess.Popen([
"df",
"-P",
"--block-size=1G", self.
_home_dir],
260 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
261 stdout, stderr = p.communicate()
262 stdout = stdout.decode()
263 retcode = p.returncode
267 diag_vals.append(KeyValue(key =
'Disk Space Reading', value =
'OK'))
269 for row
in stdout.split(
'\n'):
270 if len(row.split()) < 2:
272 if not row.split()[1].isnumeric()
or float(row.split()[1]) < 10:
276 g_available = row.split()[-3]
277 name = row.split()[0]
278 size = row.split()[1]
279 mount_pt = row.split()[-1]
281 if (float(g_available) > low_hd_level):
282 level = DiagnosticStatus.OK
283 elif (float(g_available) > critical_hd_level):
284 level = DiagnosticStatus.WARN
286 level = DiagnosticStatus.ERROR
288 diag_vals.append(KeyValue(
289 key =
'Disk %d Name' % row_count, value = name))
290 diag_vals.append(KeyValue(
291 key =
'Disk %d Available' % row_count, value = g_available))
292 diag_vals.append(KeyValue(
293 key =
'Disk %d Size' % row_count, value = size))
294 diag_vals.append(KeyValue(
295 key =
'Disk %d Status' % row_count, value = stat_dict[level]))
296 diag_vals.append(KeyValue(
297 key =
'Disk %d Mount Point' % row_count, value = mount_pt))
299 diag_level = max(diag_level, level)
300 diag_message = usage_dict[diag_level]
303 diag_vals.append(KeyValue(key =
'Disk Space Reading', value =
'Failed'))
304 diag_level = DiagnosticStatus.ERROR
305 diag_message = stat_dict[diag_level]
309 rospy.logerr(traceback.format_exc())
311 diag_vals.append(KeyValue(key =
'Disk Space Reading', value =
'Exception'))
312 diag_vals.append(KeyValue(key =
'Disk Space Ex', value = traceback.format_exc()))
314 diag_level = DiagnosticStatus.ERROR
315 diag_message = stat_dict[diag_level]
324 if not rospy.is_shutdown():
335 msg = DiagnosticArray()
336 msg.header.stamp = rospy.get_rostime()
351 if __name__ ==
'__main__':
352 hostname = socket.gethostname()
355 parser = optparse.OptionParser(usage=
"usage: hd_monitor.py [--diag-hostname=cX]")
356 parser.add_option(
"--diag-hostname", dest=
"diag_hostname",
357 help=
"Computer name in diagnostics output (ex: 'c1')",
358 metavar=
"DIAG_HOSTNAME",
359 action=
"store", default = hostname)
360 options, args = parser.parse_args(rospy.myargv())
367 rospy.init_node(
'hd_monitor_%s' % hostname)
368 except rospy.exceptions.ROSInitException:
369 print(
'HD monitor is unable to initialize node. Master may not be running.')
372 hd_monitor =
hd_monitor(hostname, options.diag_hostname, home_dir)
373 rate = rospy.Rate(1.0)
376 while not rospy.is_shutdown():
378 hd_monitor.publish_stats()
379 except KeyboardInterrupt:
381 except Exception
as e:
382 traceback.print_exc()
384 hd_monitor.cancel_timers()