dump.scm 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2021 Mathieu Othacehe <othacehe@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gnu installer dump)
  19. #:use-module (gnu installer utils)
  20. #:use-module (guix build utils)
  21. #:use-module (srfi srfi-11)
  22. #:use-module (ice-9 iconv)
  23. #:use-module (ice-9 match)
  24. #:use-module (ice-9 popen)
  25. #:use-module (ice-9 textual-ports)
  26. #:use-module (web client)
  27. #:use-module (web http)
  28. #:use-module (web response)
  29. #:use-module (webutils multipart)
  30. #:export (%core-dump
  31. prepare-dump
  32. make-dump
  33. send-dump-report))
  34. ;; The installer crash dump type.
  35. (define %dump-type "installer-dump")
  36. ;; The core dump file.
  37. (define %core-dump "/tmp/installer-core-dump")
  38. (define (result->list result)
  39. "Return the alist for the given RESULT."
  40. (hash-map->list (lambda (k v)
  41. (cons k v))
  42. result))
  43. (define* (prepare-dump key args #:key result)
  44. "Create a crash dump directory. KEY and ARGS represent the thrown error.
  45. RESULT is the installer result hash table. Returns the created directory path."
  46. (define now (localtime (current-time)))
  47. (define dump-dir
  48. (format #f "/tmp/dump.~a"
  49. (strftime "%F.%H.%M.%S" now)))
  50. (mkdir-p dump-dir)
  51. (with-directory-excursion dump-dir
  52. ;; backtrace
  53. (call-with-output-file "installer-backtrace"
  54. (lambda (port)
  55. (display-backtrace (make-stack #t) port)
  56. (print-exception port
  57. (stack-ref (make-stack #t) 1)
  58. key args)))
  59. ;; installer result
  60. (call-with-output-file "installer-result"
  61. (lambda (port)
  62. (write (result->list result) port)))
  63. ;; syslog
  64. (copy-file "/var/log/messages" "syslog")
  65. ;; core dump
  66. (when (file-exists? %core-dump)
  67. (copy-file %core-dump "core-dump"))
  68. ;; dmesg
  69. (let ((pipe (open-pipe* OPEN_READ "dmesg")))
  70. (call-with-output-file "dmesg"
  71. (lambda (port)
  72. (dump-port pipe port)
  73. (close-pipe pipe)))))
  74. dump-dir)
  75. (define* (make-dump dump-dir file-choices)
  76. "Create a crash dump archive from DUMP-DIR containing FILE-CHOICES.
  77. Returns the archive path."
  78. (define output (string-append (basename dump-dir) ".tar.gz"))
  79. (with-directory-excursion (dirname dump-dir)
  80. (apply system* "tar" "-zcf" output
  81. (map (lambda (f)
  82. (string-append (basename dump-dir) "/" f))
  83. file-choices)))
  84. (canonicalize-path (string-append (dirname dump-dir) "/" output)))
  85. (define* (send-dump-report dump
  86. #:key
  87. (url "https://dump.guix.gnu.org"))
  88. "Turn the DUMP archive into a multipart body and send it to the Guix crash
  89. dump server at URL."
  90. (define (match-boundary kont)
  91. (match-lambda
  92. (('boundary . (? string? b))
  93. (kont b))
  94. (x #f)))
  95. (define (response->string response)
  96. (bytevector->string
  97. (read-response-body response)
  98. "UTF-8"))
  99. (let-values (((body boundary)
  100. (call-with-input-file dump
  101. (lambda (port)
  102. (format-multipart-body
  103. `((,%dump-type . ,port)))))))
  104. (false-if-exception
  105. (response->string
  106. (http-post
  107. (string-append url "/upload")
  108. #:keep-alive? #t
  109. #:streaming? #t
  110. #:headers `((content-type
  111. . (multipart/form-data
  112. (boundary . ,boundary))))
  113. #:body body)))))