vm: Make UUID computation really deterministic.
Fixes <https://bugs.gnu.org/32652>. * gnu/system/vm.scm (operating-system-uuid)[service-name, file-system-digest]: New procedures. Map these over services and file systems and hash the result. * tests/guix-system.sh: Add test.
This commit is contained in:
parent
0012e0dd56
commit
1540075c79
|
@ -529,17 +529,42 @@ should set REGISTER-CLOSURES? to #f."
|
||||||
(define* (operating-system-uuid os #:optional (type 'dce))
|
(define* (operating-system-uuid os #:optional (type 'dce))
|
||||||
"Compute UUID object with a deterministic \"UUID\" for OS, of the given
|
"Compute UUID object with a deterministic \"UUID\" for OS, of the given
|
||||||
TYPE (one of 'iso9660 or 'dce). Return a UUID object."
|
TYPE (one of 'iso9660 or 'dce). Return a UUID object."
|
||||||
|
;; Note: For this to be deterministic, we must not hash things that contains
|
||||||
|
;; (directly or indirectly) procedures, for example. That rules out
|
||||||
|
;; anything that contains gexps, thunk or delayed record fields, etc.
|
||||||
|
|
||||||
|
(define service-name
|
||||||
|
(compose service-type-name service-kind))
|
||||||
|
|
||||||
|
(define (file-system-digest fs)
|
||||||
|
;; Return a hashable digest that does not contain 'dependencies' since
|
||||||
|
;; this field can contain procedures.
|
||||||
|
(let ((device (file-system-device fs)))
|
||||||
|
(list (file-system-mount-point fs)
|
||||||
|
(file-system-type fs)
|
||||||
|
(cond ((file-system-label? device)
|
||||||
|
(file-system-label->string device))
|
||||||
|
((uuid? device)
|
||||||
|
(uuid->string device))
|
||||||
|
((string? device)
|
||||||
|
device)
|
||||||
|
(else #f))
|
||||||
|
(file-system-options fs))))
|
||||||
|
|
||||||
(if (eq? type 'iso9660)
|
(if (eq? type 'iso9660)
|
||||||
(let ((pad (compose (cut string-pad <> 2 #\0)
|
(let ((pad (compose (cut string-pad <> 2 #\0)
|
||||||
number->string))
|
number->string))
|
||||||
(h (hash (operating-system-services os) 3600)))
|
(h (hash (map service-name (operating-system-services os))
|
||||||
|
3600)))
|
||||||
(bytevector->uuid
|
(bytevector->uuid
|
||||||
(string->iso9660-uuid
|
(string->iso9660-uuid
|
||||||
(string-append "1970-01-01-"
|
(string-append "1970-01-01-"
|
||||||
(pad (hash (operating-system-host-name os) 24)) "-"
|
(pad (hash (operating-system-host-name os) 24)) "-"
|
||||||
(pad (quotient h 60)) "-"
|
(pad (quotient h 60)) "-"
|
||||||
(pad (modulo h 60)) "-"
|
(pad (modulo h 60)) "-"
|
||||||
(pad (hash (operating-system-file-systems os) 100))))
|
(pad (hash (map file-system-digest
|
||||||
|
(operating-system-file-systems os))
|
||||||
|
100))))
|
||||||
'iso9660))
|
'iso9660))
|
||||||
(bytevector->uuid
|
(bytevector->uuid
|
||||||
(uint-list->bytevector
|
(uint-list->bytevector
|
||||||
|
@ -547,9 +572,9 @@ TYPE (one of 'iso9660 or 'dce). Return a UUID object."
|
||||||
(- (expt 2 32) 1))
|
(- (expt 2 32) 1))
|
||||||
(hash (operating-system-host-name os)
|
(hash (operating-system-host-name os)
|
||||||
(- (expt 2 32) 1))
|
(- (expt 2 32) 1))
|
||||||
(hash (operating-system-services os)
|
(hash (map service-name (operating-system-services os))
|
||||||
(- (expt 2 32) 1))
|
(- (expt 2 32) 1))
|
||||||
(hash (operating-system-file-systems os)
|
(hash (map file-system-digest (operating-system-file-systems os))
|
||||||
(- (expt 2 32) 1)))
|
(- (expt 2 32) 1)))
|
||||||
(endianness little)
|
(endianness little)
|
||||||
4)
|
4)
|
||||||
|
|
|
@ -232,6 +232,14 @@ guix system build "$tmpfile" -d | grep '\.drv$'
|
||||||
guix system vm "$tmpfile" -d # succeeds
|
guix system vm "$tmpfile" -d # succeeds
|
||||||
guix system vm "$tmpfile" -d | grep '\.drv$'
|
guix system vm "$tmpfile" -d | grep '\.drv$'
|
||||||
|
|
||||||
|
# Make sure the behavior is deterministic (<https://bugs.gnu.org/32652>).
|
||||||
|
drv1="`guix system vm "$tmpfile" -d`"
|
||||||
|
drv2="`guix system vm "$tmpfile" -d`"
|
||||||
|
test "$drv1" = "$drv2"
|
||||||
|
drv1="`guix system disk-image --file-system-type=iso9660 "$tmpfile" -d`"
|
||||||
|
drv2="`guix system disk-image --file-system-type=iso9660 "$tmpfile" -d`"
|
||||||
|
test "$drv1" = "$drv2"
|
||||||
|
|
||||||
make_user_config "group-that-does-not-exist" "users"
|
make_user_config "group-that-does-not-exist" "users"
|
||||||
if guix system build "$tmpfile" -n 2> "$errorfile"
|
if guix system build "$tmpfile" -n 2> "$errorfile"
|
||||||
then false
|
then false
|
||||||
|
|
Loading…
Reference in New Issue