38 from __future__
import with_statement
46 from diagnostic_msgs.msg
import DiagnosticArray, DiagnosticStatus, KeyValue
48 roslib.load_manifest(
'diagnostic_common_diagnostics')
55 stat_dict = { 0:
'OK', 1:
'Warning', 2:
'Error' }
56 temp_dict = { 0:
'OK', 1:
'Hot', 2:
'Critical Hot' }
57 usage_dict = { 0:
'OK', 1:
'Low Disk Space', 2:
'Very Low Disk Space' }
59 REMOVABLE = [
'/dev/sg1',
'/dev/sdb']
65 hd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
66 hd_sock.connect((hostname, port))
69 newdat = hd_sock.recv(1024)
72 sock_data = sock_data + newdat
75 sock_vals = sock_data.decode().split(
'|')
83 while idx + 5 < len(sock_vals):
84 this_drive = sock_vals[idx + 1]
85 this_make = sock_vals[idx + 2]
86 this_temp = sock_vals[idx + 3]
90 if this_make
in makes:
94 drives.append(this_drive)
95 makes.append(this_make)
96 temps.append(this_temp)
100 return True, drives, makes, temps
102 rospy.logerr(traceback.format_exc())
103 return False, [
'Exception'], [traceback.format_exc()], [
'0']
107 time_since_update = rospy.get_time() - last_update_time
110 if 20 < time_since_update <= 35:
111 stale_status =
'Lagging'
112 if stat.level == DiagnosticStatus.OK:
113 stat.message = stale_status
114 elif stat.message.find(stale_status) < 0:
115 stat.message =
', '.join([stat.message, stale_status])
116 stat.level = max(stat.level, DiagnosticStatus.WARN)
117 if time_since_update > 35:
118 stale_status =
'Stale'
119 if stat.level == DiagnosticStatus.OK:
120 stat.message = stale_status
121 elif stat.message.find(stale_status) < 0:
122 stat.message =
', '.join([stat.message, stale_status])
123 stat.level = max(stat.level, DiagnosticStatus.ERROR)
127 stat.values.insert(0, KeyValue(key=
'Update Status', value=stale_status))
128 stat.values.insert(1, KeyValue(key=
'Time Since Update', value=str(time_since_update)))
132 def __init__(self, hostname, diag_hostname, home_dir=''):
138 rospy.logwarn(
'Not warning for HD temperatures is deprecated. This will be removed in D-turtle')
141 self.
_diag_pub = rospy.Publisher(
'/diagnostics', DiagnosticArray, queue_size=10)
151 self.
_temp_stat.name =
"%s HD Temperature" % diag_hostname
152 self.
_temp_stat.level = DiagnosticStatus.ERROR
155 self.
_temp_stat.values = [KeyValue(key=
'Update Status', value=
'No Data'),
156 KeyValue(key=
'Time Since Last Update', value=
'N/A')]
162 self.
_usage_stat.name =
'%s HD Usage' % diag_hostname
163 self.
_usage_stat.values = [KeyValue(key=
'Update Status', value=
'No Data' ),
164 KeyValue(key=
'Time Since Last Update', value=
'N/A')]
180 if rospy.is_shutdown():
185 diag_strs = [KeyValue(key=
'Update Status', value=
'OK'),
186 KeyValue(key=
'Time Since Last Update', value=
'0')]
187 diag_level = DiagnosticStatus.OK
191 for index
in range(0, len(drives)):
194 if not temp.isnumeric()
and drives[index]
not in REMOVABLE:
195 temp_level = DiagnosticStatus.ERROR
197 elif not temp.isnumeric()
and drives[index]
in REMOVABLE:
198 temp_level = DiagnosticStatus.OK
201 temp_level = DiagnosticStatus.OK
202 if float(temp) > hd_temp_warn:
203 temp_level = DiagnosticStatus.WARN
204 if float(temp) > hd_temp_error:
205 temp_level = DiagnosticStatus.ERROR
207 diag_level = max(diag_level, temp_level)
209 diag_strs.append(KeyValue(key=
'Disk %d Temp Status' % index, value=temp_dict[temp_level]))
210 diag_strs.append(KeyValue(key=
'Disk %d Mount Pt.' % index, value=drives[index]))
211 diag_strs.append(KeyValue(key=
'Disk %d Device ID' % index, value=makes[index]))
212 diag_strs.append(KeyValue(key=
'Disk %d Temp' % index, value=temp))
215 diag_level = DiagnosticStatus.ERROR
223 self.
_temp_stat.message = temp_dict[diag_level]
230 if not rospy.is_shutdown():
237 if rospy.is_shutdown():
242 diag_vals = [KeyValue(key=
'Update Status', value=
'OK'),
243 KeyValue(key=
'Time Since Last Update', value=
'0')]
244 diag_level = DiagnosticStatus.OK
248 p = subprocess.Popen([
"df",
"-P",
"--block-size=1G", self.
_home_dir],
249 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
250 stdout, stderr = p.communicate()
251 retcode = p.returncode
255 diag_vals.append(KeyValue(key=
'Disk Space Reading', value=
'OK'))
257 for row
in stdout.split(
'\n'):
258 if len(row.split()) < 2:
260 if not row.split()[1].isnumeric()
or float(row.split()[1]) < 10:
264 g_available = row.split()[-3]
265 name = row.split()[0]
266 size = row.split()[1]
267 mount_pt = row.split()[-1]
269 if float(g_available) > low_hd_level:
270 level = DiagnosticStatus.OK
271 elif float(g_available) > critical_hd_level:
272 level = DiagnosticStatus.WARN
274 level = DiagnosticStatus.ERROR
276 diag_vals.append(KeyValue(
277 key=
'Disk %d Name' % row_count, value=name))
278 diag_vals.append(KeyValue(
279 key=
'Disk %d Available' % row_count, value=g_available))
280 diag_vals.append(KeyValue(
281 key=
'Disk %d Size' % row_count, value=size))
282 diag_vals.append(KeyValue(
283 key=
'Disk %d Status' % row_count, value=stat_dict[level]))
284 diag_vals.append(KeyValue(
285 key=
'Disk %d Mount Point' % row_count, value=mount_pt))
287 diag_level = max(diag_level, level)
288 diag_message = usage_dict[diag_level]
291 diag_vals.append(KeyValue(key=
'Disk Space Reading', value=
'Failed'))
292 diag_level = DiagnosticStatus.ERROR
293 diag_message = stat_dict[diag_level]
296 rospy.logerr(traceback.format_exc())
298 diag_vals.append(KeyValue(key=
'Disk Space Reading', value=
'Exception'))
299 diag_vals.append(KeyValue(key=
'Disk Space Ex', value=traceback.format_exc()))
301 diag_level = DiagnosticStatus.ERROR
302 diag_message = stat_dict[diag_level]
311 if not rospy.is_shutdown():
321 msg = DiagnosticArray()
322 msg.header.stamp = rospy.get_rostime()
335 if __name__ ==
'__main__':
336 hostname = socket.gethostname()
339 parser = optparse.OptionParser(usage=
"usage: hd_monitor.py [--diag-hostname=cX]")
340 parser.add_option(
"--diag-hostname", dest=
"diag_hostname",
341 help=
"Computer name in diagnostics output (ex: 'c1')",
342 metavar=
"DIAG_HOSTNAME",
343 action=
"store", default = hostname)
344 options, args = parser.parse_args(rospy.myargv())
350 hostname_clean = hostname.translate(hostname.maketrans(
'-',
'_'))
352 rospy.init_node(
'hd_monitor_%s' % hostname_clean)
353 except rospy.exceptions.ROSInitException:
354 print(
'HD monitor is unable to initialize node. Master may not be running.')
357 hd_monitor =
hd_monitor(hostname, options.diag_hostname, home_dir)
358 rate = rospy.Rate(1.0)
361 while not rospy.is_shutdown():
363 hd_monitor.publish_stats()
364 except KeyboardInterrupt:
366 except Exception
as e:
367 traceback.print_exc()
370 hd_monitor.cancel_timers()