mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/osd
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/mds
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/mgr
+mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/crash
+mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/crash/posted
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/radosgw
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-osd
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-mds
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-rgw
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-mgr
mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/bootstrap-rbd
-mkdir -p %{buildroot}%{_localstatedir}/lib/ceph/crash
%if 0%{?suse_version}
# create __pycache__ directories and their contents
%files
%files base
+%{_bindir}/ceph-crash
%{_bindir}/crushtool
%{_bindir}/monmaptool
%{_bindir}/osdmaptool
%{_libdir}/ceph/erasure-code/libec_*.so*
%dir %{_libdir}/ceph/compressor
%{_libdir}/ceph/compressor/libceph_*.so*
+%{_unitdir}/ceph-crash.service
%ifarch x86_64
%dir %{_libdir}/ceph/crypto
%{_libdir}/ceph/crypto/libceph_*.so*
%{_mandir}/man8/monmaptool.8*
%{_mandir}/man8/ceph-kvstore-tool.8*
#set up placeholder directories
+%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/crash
+%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/crash/posted
%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/tmp
%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/bootstrap-osd
%attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/bootstrap-mds
%if 0%{?suse_version}
%fillup_only
if [ $1 -eq 1 ] ; then
-/usr/bin/systemctl preset ceph.target >/dev/null 2>&1 || :
+/usr/bin/systemctl preset ceph.target ceph-crash.service >/dev/null 2>&1 || :
fi
%endif
%if 0%{?fedora} || 0%{?rhel}
-%systemd_post ceph.target
+%systemd_post ceph.target ceph-crash.service
%endif
if [ $1 -eq 1 ] ; then
-/usr/bin/systemctl start ceph.target >/dev/null 2>&1 || :
+/usr/bin/systemctl start ceph.target ceph-crash.service >/dev/null 2>&1 || :
fi
%preun base
%if 0%{?suse_version}
-%service_del_preun ceph.target
+%service_del_preun ceph.target ceph-crash.service
%endif
%if 0%{?fedora} || 0%{?rhel}
-%systemd_preun ceph.target
+%systemd_preun ceph.target ceph-crash.service
%endif
%postun base
var/lib/ceph/bootstrap-rbd
var/lib/ceph/tmp
var/lib/ceph/crash
+var/lib/ceph/crash/posted
etc/init.d/ceph
+lib/systemd/system/ceph-crash.service
+usr/bin/ceph-crash
usr/bin/ceph-debugpack
usr/bin/ceph-run
usr/bin/crushtool
configure_file(ceph-post-file.in
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ceph-post-file @ONLY)
+configure_file(ceph-crash.in
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ceph-crash @ONLY)
+
if(WITH_TESTS)
install(PROGRAMS
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ceph-debugpack
install(PROGRAMS
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ceph
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ceph-post-file
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ceph-crash
${CMAKE_SOURCE_DIR}/src/ceph-run
${CMAKE_SOURCE_DIR}/src/ceph-clsinfo
DESTINATION bin)
--- /dev/null
+#!@PYTHON_EXECUTABLE@
+# -*- mode:python -*-
+# vim: ts=4 sw=4 smarttab expandtab
+
+import argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+logging.basicConfig(level=logging.INFO)
+log = logging.getLogger(__name__)
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-p', '--path', default='/var/lib/ceph/crash',
+ help='base path to monitor for crash dumps')
+ parser.add_argument(
+ '-d', '--delay', default=10.0, type=float,
+ help='minutes to delay between scans (0 to exit after one)',
+ )
+ return parser.parse_args()
+
+
+def post_crash(path):
+ pr = subprocess.Popen(
+ args=['timeout', '30', 'ceph', 'crash', 'post', '-i', '-'],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ f = open(os.path.join(path, 'meta'), 'r')
+ stdout, stderr = pr.communicate(input=f.read())
+ rc = pr.wait()
+ f.close()
+ if rc != 0:
+ log.warning('post %s failed: %s' % (path, stderr))
+ return rc
+
+
+def scrape_path(path):
+ for p in os.listdir(path):
+ crashpath = os.path.join(path, p)
+ metapath = os.path.join(crashpath, 'meta')
+ donepath = os.path.join(crashpath, 'done')
+ if os.path.isfile(metapath):
+ if not os.path.isfile(donepath):
+ # hang out just for a bit; either we interrupted the dump
+ # or the daemon crashed before finishing it
+ time.sleep(1)
+ if not os.path.isfile(donepath):
+ return
+ # ok, we can process this one
+ rc = post_crash(crashpath)
+ if rc == 0:
+ os.rename(crashpath, os.path.join(path, 'posted/', p))
+ log.debug(
+ "posted %s and renamed %s -> %s " %
+ (metapath, p, os.path.join('posted/', p))
+ )
+
+
+def main():
+ args = parse_args()
+ postdir = os.path.join(args.path, 'posted')
+
+ while not os.path.isdir(postdir):
+ log.error("%s does not exist; please create" % postdir)
+ time.sleep(30)
+
+ log.info("monitoring path %s, delay %ds" % (args.path, args.delay * 60.0))
+ while True:
+ scrape_path(args.path)
+ if args.delay == 0:
+ sys.exit(0)
+ time.sleep(args.delay * 60)
+
+
+if __name__ == "__main__":
+ main()
enable ceph-mon.target
enable ceph-osd.target
enable ceph-radosgw.target
+enable ceph-crash.service
CACHE PATH "Location for systemd service environmental variable settings files")
set(SYSTEMD_ENV_FILE "${CEPH_SYSTEMD_ENV_DIR}/ceph")
foreach(service
+ ceph-crash
ceph-fuse@
ceph-mds@
ceph-mgr@
--- /dev/null
+[Unit]
+Description=Ceph crash dump collector
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/ceph-crash
+Restart=always
+RestartSec=10
+StartLimitInterval=10min
+StartLimitBurst=10
+
+[Install]
+WantedBy=ceph.target