* gnu/installer.scm (installer-program): Let the installer customize the dump archive. * gnu/installer/dump.scm (prepare-dump, make-dump): Split make-dump in prepare-dump, which copies the files necessary for the dump, and make-dump which creates the archive. * gnu/installer/record.scm (installer): Add report-page field. Change documented return value of exit-error. * gnu/installer/newt.scm (exit-error): Change arguments to be a string containing the error. Let the user choose between exiting and initiating a dump. (report-page): Add new variable. * gnu/installer/newt/page.scm (run-dump-page): New variable. * gnu/installer/newt/dump.scm: Delete it. Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
		
			
				
	
	
		
			118 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
;;; GNU Guix --- Functional package management for GNU
 | 
						|
;;; Copyright © 2021 Mathieu Othacehe <othacehe@gnu.org>
 | 
						|
;;;
 | 
						|
;;; This file is part of GNU Guix.
 | 
						|
;;;
 | 
						|
;;; GNU Guix is free software; you can redistribute it and/or modify it
 | 
						|
;;; under the terms of the GNU General Public License as published by
 | 
						|
;;; the Free Software Foundation; either version 3 of the License, or (at
 | 
						|
;;; your option) any later version.
 | 
						|
;;;
 | 
						|
;;; GNU Guix is distributed in the hope that it will be useful, but
 | 
						|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
;;; GNU General Public License for more details.
 | 
						|
;;;
 | 
						|
;;; You should have received a copy of the GNU General Public License
 | 
						|
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
(define-module (gnu installer dump)
 | 
						|
  #:use-module (gnu installer utils)
 | 
						|
  #:use-module (guix build utils)
 | 
						|
  #:use-module (srfi srfi-11)
 | 
						|
  #:use-module (ice-9 iconv)
 | 
						|
  #:use-module (ice-9 match)
 | 
						|
  #:use-module (ice-9 popen)
 | 
						|
  #:use-module (ice-9 textual-ports)
 | 
						|
  #:use-module (web client)
 | 
						|
  #:use-module (web http)
 | 
						|
  #:use-module (web response)
 | 
						|
  #:use-module (webutils multipart)
 | 
						|
  #:export (prepare-dump
 | 
						|
            make-dump
 | 
						|
            send-dump-report))
 | 
						|
 | 
						|
;; The installer crash dump type.
 | 
						|
(define %dump-type "installer-dump")
 | 
						|
 | 
						|
(define (result->list result)
 | 
						|
  "Return the alist for the given RESULT."
 | 
						|
  (hash-map->list (lambda (k v)
 | 
						|
                    (cons k v))
 | 
						|
                  result))
 | 
						|
 | 
						|
(define* (prepare-dump key args #:key result)
 | 
						|
  "Create a crash dump directory.  KEY and ARGS represent the thrown error.
 | 
						|
RESULT is the installer result hash table.  Returns the created directory path."
 | 
						|
  (define now (localtime (current-time)))
 | 
						|
  (define dump-dir
 | 
						|
    (format #f "/tmp/dump.~a"
 | 
						|
            (strftime "%F.%H.%M.%S" now)))
 | 
						|
  (mkdir-p dump-dir)
 | 
						|
  (with-directory-excursion dump-dir
 | 
						|
    ;; backtrace
 | 
						|
    (call-with-output-file "installer-backtrace"
 | 
						|
      (lambda (port)
 | 
						|
        (display-backtrace (make-stack #t) port)
 | 
						|
        (print-exception port
 | 
						|
                         (stack-ref (make-stack #t) 1)
 | 
						|
                         key args)))
 | 
						|
 | 
						|
    ;; installer result
 | 
						|
    (call-with-output-file "installer-result"
 | 
						|
      (lambda (port)
 | 
						|
        (write (result->list result) port)))
 | 
						|
 | 
						|
    ;; syslog
 | 
						|
    (copy-file "/var/log/messages" "syslog")
 | 
						|
 | 
						|
    ;; dmesg
 | 
						|
    (let ((pipe (open-pipe* OPEN_READ "dmesg")))
 | 
						|
      (call-with-output-file "dmesg"
 | 
						|
        (lambda (port)
 | 
						|
          (dump-port pipe port)
 | 
						|
          (close-pipe pipe)))))
 | 
						|
  dump-dir)
 | 
						|
 | 
						|
(define* (make-dump dump-dir file-choices)
 | 
						|
  "Create a crash dump archive from DUMP-DIR containing FILE-CHOICES.
 | 
						|
Returns the archive path."
 | 
						|
  (define output (string-append (basename dump-dir) ".tar.gz"))
 | 
						|
  (with-directory-excursion (dirname dump-dir)
 | 
						|
    (apply system* "tar" "-zcf" output
 | 
						|
           (map (lambda (f)
 | 
						|
                  (string-append (basename dump-dir) "/" f))
 | 
						|
                file-choices)))
 | 
						|
  (canonicalize-path (string-append (dirname dump-dir) "/" output)))
 | 
						|
 | 
						|
(define* (send-dump-report dump
 | 
						|
                           #:key
 | 
						|
                           (url "https://dump.guix.gnu.org"))
 | 
						|
  "Turn the DUMP archive into a multipart body and send it to the Guix crash
 | 
						|
dump server at URL."
 | 
						|
  (define (match-boundary kont)
 | 
						|
    (match-lambda
 | 
						|
      (('boundary . (? string? b))
 | 
						|
       (kont b))
 | 
						|
      (x #f)))
 | 
						|
 | 
						|
  (define (response->string response)
 | 
						|
    (bytevector->string
 | 
						|
     (read-response-body response)
 | 
						|
     "UTF-8"))
 | 
						|
 | 
						|
  (let-values (((body boundary)
 | 
						|
                (call-with-input-file dump
 | 
						|
                  (lambda (port)
 | 
						|
                    (format-multipart-body
 | 
						|
                     `((,%dump-type . ,port)))))))
 | 
						|
    (false-if-exception
 | 
						|
     (response->string
 | 
						|
      (http-post
 | 
						|
       (string-append url "/upload")
 | 
						|
       #:keep-alive? #t
 | 
						|
       #:streaming? #t
 | 
						|
       #:headers `((content-type
 | 
						|
                    . (multipart/form-data
 | 
						|
                       (boundary . ,boundary))))
 | 
						|
       #:body body)))))
 |