aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-04-12 17:15:47 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-04-12 19:06:18 -0700
commit70e150fbbb648bf8d459380304a77a84ab5b0353 (patch)
tree82f52d8e154c5aa213a85a638e6c725cb68c6332
parentdbf8a92e10e85e92932a59a10b0b37793d520724 (diff)
downloadconsfigurator-70e150fbbb648bf8d459380304a77a84ab5b0353.tar.gz
implement operations for instances of PARTITIONED-VOLUME
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
-rw-r--r--src/property/disk.lisp59
1 files changed, 54 insertions, 5 deletions
diff --git a/src/property/disk.lisp b/src/property/disk.lisp
index dd7aedb..b568551 100644
--- a/src/property/disk.lisp
+++ b/src/property/disk.lisp
@@ -200,13 +200,62 @@ directly writing out with dd(1)."))
:documentation "A list of partitions."))
(:documentation "A device with a GPT partition table and partitions."))
-(defclass partition (volume) ()
+(defclass partition (volume)
+ ((partition-typecode
+ :initform #x8300
+ :initarg :partition-typecode
+ :accessor partition-typecode
+ :documentation
+ "The type code for the partition; see the --typecode option to sgdisk(1).
+Either a two-byte hexadecimal number, or a string specifying the GUID.
+
+On GNU/Linux systems, you typically only need to set this to a non-default
+value in the case of EFI system partitions, in which case use #xEF00."))
(:documentation "A GPT partition."))
-(defmethod open-volume-contents ((volume partitioned-volume) (file null))
- ;; open with kpartx, make an instance of OPENED-VOLUME for *each partition*
- ;; (not for VOLUME) with the relevant loop device as its DEVICE-FILE slot
- )
+(defmethod volume-contents-minimum-size ((volume partitioned-volume))
+ "Add one mebibyte for the GPT metadata."
+ (1+ (call-next-method)))
+
+(defmethod open-volume-contents ((volume partitioned-volume) (file pathname))
+ (let ((loopdevs (mapcar
+ (lambda (line)
+ (destructuring-bind (add map loopdev &rest ignore)
+ (split-string line)
+ (declare (ignore ignore))
+ (unless (and (string= add "add") (string= map "map"))
+ (failed-change
+ "Unexpected kpartx output ~A" line))
+ (ensure-pathname (strcat "/dev/mapper/" loopdev))))
+ (runlines "kpartx" "-avs" file))))
+ (unless (= (length loopdevs) (length (volume-contents volume)))
+ (mrun "kpartx" "-d" file)
+ (failed-change
+ "kpartx(1) returned ~A loop devices, but volume has ~A partitions."
+ (length loopdevs) (length (volume-contents volume))))
+ (loop for loopdev in loopdevs and partition in (volume-contents volume)
+ collect (make-instance 'opened-volume
+ :opened-volume partition
+ :device-file loopdev))))
+
+(defmethod close-volume-contents ((volume partitioned-volume) (file pathname))
+ (mrun "kpartx" "-d" file))
+
+(defmethod create-volume ((volume partitioned-volume) (file pathname))
+ (mrun :inform "sgdisk" "--zap-all" file)
+ (mrun :inform "sgdisk"
+ (loop for partition in (volume-contents volume)
+ for code = (partition-typecode partition)
+ collect (strcat "--new=0:0:"
+ (if (eql (volume-size partition) :remaining)
+ "0"
+ (format nil "~DM"
+ (volume-minimum-size partition))))
+ collect (strcat "--typecode=0:"
+ (etypecase code
+ (string code)
+ (integer (format nil "~X" code)))))
+ file))
;;;; LVM