diff --git a/doc/auto_storage.md b/doc/auto_storage.md index e7cd92ebea..686f109c5e 100644 --- a/doc/auto_storage.md +++ b/doc/auto_storage.md @@ -15,7 +15,7 @@ JSON validation will be performed for it. ### Implementation Considerations for AutoYaST Specification In principle, implementing the legacy AutoYaST module is as simple as converting the corresponding -section of the profile into a `Y2Storage::PartitioningSection` object and use +section of the profile into a `Y2Storage::PartitioningSection` object and use `Y2Storage::AutoInstProposal` to calculate the result. But there are some special cases in which AutoYaST fallbacks to read some settings from the YaST @@ -37,14 +37,14 @@ Storage volumeGroups mdRaids btrfsRaids - bcacheDevices nfsMounts - guided + boot [BootSettings] + encryption [EncryptionSettings] ``` Thus, a `storage` section can contain several entries describing how to configure the corresponding -storage devices and an extra entry used to execute the Guided Proposal in top of the scenario -described by the device entries. +storage devices and a couple of extra entries to setup some general aspects that influence the final +layout. Each volume group, RAID, bcache device or NFS share can represent a new logical device to be created or an existing device from the system to be processed. Entries below `drives` represent devices @@ -55,22 +55,33 @@ found at the system, since Agama cannot create that kind of devices. In fact, a single entry can represent several devices from the system. That is explained in depth at the section "searching existing devices" of this document. +On the first versions of Agama, an alternative syntax will be accepted including only one `guided` +entry. + +``` +Storage + guided +``` + +That allows to rely on the YaST component known as `GuidedProposal`. That alternative will be +removed as soon as all the capabilities of that `GuidedProposal` could be expressed in terms of a +regular storage configuration like the one explained above. + ## Entries for Describing the Devices The formal specification of the previous section can be extended as we dive into the structure. ``` Drive - search: [] + search [] alias [] - encrypt [] - format [] - mount [] + encryption [] + filesystem [] ptableType [] partitions [] VolumeGroup - search: [] + search [] alias [] name [] peSize [] @@ -79,21 +90,20 @@ VolumeGroup delete [] MdRaid - search: [] + search [] alias [] name level [] chunkSize [] devices [<[]>] - encrypt [] - format [] - mount [] + encryption [] + filesystem [Filesystem] ptableType [] partitions [] delete [] BtrfsRaid - search: [] + search [] alias [] dataRaidLevel metadataRaidLevel @@ -109,15 +119,14 @@ NFS mount [] Partition - search: [] + search [] alias [] id [] - type [] size [] - encrypt [EncryptAction] - format [] - mount [] + encryption [Encryption] + filesystem [] delete [] + deleteIfNeeded [] LogicalVolume search [] @@ -128,25 +137,36 @@ LogicalVolume usedPool [] stripes [] stripSize [] - encrypt [] - format [] - mount [] + encryption [Encryption] + filesystem [] delete [] + deleteIfNeeded [] +Encryption + reuse + type -EncryptAction - method - key [] - pdkdf [] - label [] +EncryptionType + +EncryptionLUKS1 + password + keySize [] cipher [] + +EncryptionLUKS2 + password keySize [] + cipher [] + pdkdf [] + label [] + +EncryptionPervasiveLUKS2 + password -FormatAction - filesystem +Filesystem + reuse + type label [] mkfsOptions [] - -MountAction path mountOptions [] mountBy [] @@ -162,6 +182,17 @@ Size <'default'|string|SizeRange> SizeRange min max + +BootSettings + configure + device + +EncryptionSettings + method + key [] + pdkdf [] + cipher [] + keySize [] ``` To illustrate how all that fits together, let's see the following example in which the first disk of @@ -173,13 +204,12 @@ it) to allocate two file systems. "drives": [ { "partitions": [ - { + { "alias": "pv", "id": "lvm", "size": { "min": "12 GiB" }, - "encrypt": { - "method": "luks2", - "key": "my secret passphrase" + "encryption": { + "luks2": { "password": "my secret passphrase" } } } ] @@ -192,13 +222,11 @@ it) to allocate two file systems. "logicalVolumes": [ { "size": { "min": "10 GiB" }, - "format": { "filesystem": "btrfs" }, - "mount": { "path": "/" } + "filesystem": { "path": "/", "type": "btrfs" } }, { "size": "2 GiB", - "format": { "filesystem": "swap" }, - "mount": { "path": "swap" } + "filesystem": { "path": "swap", "type": "swap" } } ] } @@ -228,6 +256,10 @@ into the following: - If the product does not specify a default volume, the behavior is still not defined (there are several reasonable options). +It is also possible to specify "current" as a size value for partitions and logical volumes that +already exist in the system. The usage of "current" and how it affects resizing the corresponding +devices is explained at a separate section below. + ### Under Discussion As explained, it should be possible to specify the sizes as "default", as a range or as a fixed @@ -237,6 +269,12 @@ represent a size. The following two possibilities are also under consideration. - `{ "gib": 40 }` - `{ "value": 40, "units": "gib" }` +## Partitions Needed for Booting + +Using a `boot` entry makes it possible to configure whether (and where, using an alias) Agama +should calculate and create the extra partitions needed for booting. If the device is not +specified, Agama will take the location of the root file system as a reference. + ## Searching Existing Devices Many sections in the profile are used to describe how some devices must be created, modified or even @@ -304,7 +342,7 @@ within them and create new partitions of type RAID. }, "delete": true }, - { + { "alias": "newRaidPart", "id": "raid", "size": { "min": "1 GiB" } @@ -516,23 +554,153 @@ system (so the same conditions can be matched by a disk, a partition, an LVM dev } ``` -## Partitions needed for Booting +## Keeping an Existing File System or Encryption Layer -When relying on the Agama proposal (see below), there are some options to configure whether (and -where) Agama should calculate and create the extra partitions needed for booting. +The entries for both `encryption` and `filesystem` contain a flag `reuse` with a default value of +false. It can be used in combination with `search` to specify the device must not be re-encrypted +or re-formatted. -If the proposal is not used, Agama will always try to calculate and create those partitions taking -the location of the root file system as a reference. That's the same approach that AutoYaST has -followed for years. +## Deleting and Shrinking Existing Devices -## Using the Automatic Proposal +The storage proposal must make possible to define what to do with existing partitions and logical +volumes. Even with existing MD RAIDs or LVM volume groups. + +A `search` section allows to match the definition of a partition or an LVM logical volume with one +(or several) devices existing in the system. In order to provide the same capabilities than the +Guided proposal (see below) it must be possible to specify that a given partition or volume must be: + + - Deleted if needed to make space for the newly defined devices + - Deleted in all cases + - Shrunk to the necessary size to make space for new devices + - Shrunk or extended to a given size, maybe a range (not really possible in the current Guided + Proposal) + +It is even possible to express some combinations of the above, like "try to shrink it to make space +but proceed to delete it if shrinking it is not enough". + +Deletion can be achieved with the corresponding `delete` flag or the alternative `deleteIfNeeded`. +If any of those flags are active for a partition, it makes no sense to specify any other usage +(like declaring a file system on it). + +The following example deletes the partition with the label "root" in all cases and, if needed, keeps +deleting other partitions as needed to make space for the new partition of 30 GiB. + +```json +"storage": { + "drives": [ + { + "partitions": [ + { + "search": { + "condition": { "property": "fsLabel", "value": "root" } + }, + "delete": true + }, + { "search": {}, "deleteIfNeeded": true }, + { "size": "30 GiB" } + ] + } + ] +} +``` + +Often some partitions or logical volumes are shrunk only to make space for the declared devices. But +since resizing is not a destructive operation, it can also make sense to declare a given partition +must be resized (shrunk or extended) and then formatted and/or mounted. -Agama can rely on the process known as Guided Proposal to calculate all the needed partitions, LVM -devices and file systems based on some general product settings and some user preferences. That -mechanism can also be used as part of the profile and will be executed as a last step, after -processing all the explicit sections that describe devices. +In any case, note that resizing a partition can be limited depending on its content, the filesystem +type, etc. -The `guided` section conforms to the following specification. +Combining `search` and `resize` is enough to indicate Agama is expected to resize a given partition +if possible. The keyword "current" can be used eveywhere a size is expected and it is always +equivalent to the exact original size of the device. The simplest way to use "current" is to just +specify that the matched device should keep its original size. That's the default for searched (and +found) devices if `size` is completely omitted. + +```json +"storage": { + "drives": [ + { + "partitions": [ + { + "search": { + "condition": { "property": "fsLabel", "value": "reuse" } + }, + "size": "current" + } + ] + } + ] +} +``` + +Using "current" for the min and max values of a size allows to specify how a device could be resized +if possible. See the following examples with explanatory filesystem labels. + +```json +"storage": { + "drives": [ + { + "partitions": [ + { + "search": { + "condition": { "property": "fsLabel", "value": "shrinkIfNeeded" } + }, + "size": { "min": 0, "max": "current" } + }, + { + "search": { + "condition": { "property": "fsLabel", "value": "resizeToFixedSize" } + }, + "size": "15 GiB" + }, + { + "search": { + "condition": { "property": "fsLabel", "value": "resizeByRange" } + }, + "size": { "min": "10 GiB", "max": "50 GiB" } + }, + { + "search": { + "condition": { "property": "fsLabel", "value": "growAsMuchAsPossible" } + }, + "size": { "min": "current" } + }, + ] + } + ] +} +``` + +Of course, when the size limits are specified as a combination of "current" and a fixed value, the +user must still make sure that the resulting min is not bigger than the resulting max. + +Both `deleteIfNeeded` and a size range can be combined to indicate that Agama should try to make +space first by shrinking the partitions and deleting them only if shrinking is not enough. + +```json +"storage": { + "drives": [ + { + "partitions": [ + { + "search": {}, + "size": { "min": 0, "max": "current" }, + "deleteIfNeeded": true + } + ] + } + ] +} +``` + +## Using the Automatic Proposal + +On the first implementations, Agama can rely on the process known as Guided Proposal to calculate +all the needed partitions, LVM devices and file systems based on some general product settings and +some user preferences. That mechanism is offered as a temporary alternative to the more descriptive +syntax explained at previous sections of this document and it's implemented via a `guided` section +that conforms to the following specification. ``` Guided @@ -545,22 +713,13 @@ Guided TargetDevice TargetDisk - disk - + disk + TargetNewLvm - newLvmVg <[]> + newLvmVg TargetReusedLvm - reusedLvmVg - -BootSettings - configure - device - -EncryptionSettings - password - method - pbkdFunction + reusedLvmVg Volume mountPath @@ -575,16 +734,16 @@ Volume VolumeTarget <'default'|NewPartition|NewVg|UseDevice|UseFilesystem> NewPartition - newPartition - + newPartition + NewVg - newVg - + newVg + UseDevice - device + device UseFilesystem - filesystem + filesystem ``` The `device` can be specified in several ways. The simplest one is using one of the strings "disk" @@ -606,16 +765,13 @@ And this will do the same, but creating a new LVM volume group on that first can } ``` -It's also possible to use an alias to specify a concrete disk... +It's also possible to use a device name to specify a concrete disk... ```json "storage": { - "drives": [ - { "alias": "target" } - ], "guided": { "device": { - "disk": "target" + "disk": "/dev/sda" } } } @@ -625,39 +781,16 @@ or to specify the set of disks where the LVM physical volumes can be created. ```json "storage": { - "drives": [ - { - "alias": "nvme", - "search": { "condition": { "property": "driver", "value": "nvme" } } - } - ], "guided": { "device": { - "newLvmVg": ["nvme"] + "newLvmVg": ["/dev/vda", "/dev/vdb"] } } } ``` -The alias can correspond to devices that are created by Agama itself. - -```json -"storage": { - "mdRaids": [ - { - "alias": "newMd" - "devices": [ "..." ], - "level": "raid1" - } - ], - "guided": { - "device": { "disk": "newMd" } - } -} -``` - -Apart from specifying the main target device, aliases can be used wherever a device is expected, eg. -when indicating a special target for a given volume. +Apart from specifying the main target device, device names must be used wherever a device is +expected, eg. when indicating a special target for a given volume. In principle, the list of volumes will have the same format than the existing HTTP API used by the UI for calculating the storage proposal. That is, if the list is not provided the default @@ -666,37 +799,9 @@ with default values. In the future we may consider more advanced mechanisms to i some given volumes or to customize a single volume without having to provide the full list of volume mount paths. -Combining the `guided` section with other possible sections in the profile makes it possible to -achieve the same results than using the Agama user interface with only one exception. The Agama UI -allows to indicate that a given set of partitions can be resized if needed to allocate the volumes, -without actually indicating how much those partitions should be resized. The Guided Proposal -algorithm decides whether to resize and how much based on the other settings. Currently there is no -way to express that in the auto-installation profile. - -### Under Discussion - -It could also be possible to accept a `search` element in all places in which an alias can be used. - -```json -"storage": { - "guided": { - "device": { - "newLvmVg": [ - { "search": { "condition": { "property": "driver", "value": "nvme" } } } - ] - } - } -} -``` - -Even combining that with the string-based syntax suggested for `search`. - -```json -"storage": { - "guided": { - "device": { - "disk": { "search": "/dev/sda" } - } - } -} -``` +The `guided` section makes it possible to achieve the same results than using the Agama user +interface with only one exception. The Agama UI allows to indicate that a given set of partitions +can be resized if needed to allocate the volumes, without actually indicating how much those +partitions should be resized. The Guided Proposal algorithm decides whether to resize and how much +based on the other settings. Currently there is no way to express that in the auto-installation +profile. diff --git a/rust/agama-lib/share/examples/autoyast.json b/rust/agama-lib/share/examples/autoyast.json new file mode 100644 index 0000000000..4eb5099b8f --- /dev/null +++ b/rust/agama-lib/share/examples/autoyast.json @@ -0,0 +1,8 @@ +{ + "legacyAutoyastStorage": [ + { + "device": "/dev/vdc", + "use": "all" + } + ] +} diff --git a/rust/agama-lib/share/examples/profile_tw.json b/rust/agama-lib/share/examples/profile_tw.json index ab3f5d564f..c783a9972d 100644 --- a/rust/agama-lib/share/examples/profile_tw.json +++ b/rust/agama-lib/share/examples/profile_tw.json @@ -26,7 +26,7 @@ }, "root": { "password": "nots3cr3t", - "sshKey": "..." + "sshPublicKey": "..." }, "network": { "connections": [ diff --git a/rust/agama-lib/share/examples/storage-guided.json b/rust/agama-lib/share/examples/storage-guided.json new file mode 100644 index 0000000000..573aed64d2 --- /dev/null +++ b/rust/agama-lib/share/examples/storage-guided.json @@ -0,0 +1,63 @@ +{ + "storage": { + "guided": { + "target": { + "disk": "/dev/vdc" + }, + "boot": { + "configure": true, + "device": "/dev/vda" + }, + "encryption": { + "password": "notsecret", + "method": "luks2", + "pbkdFunction": "argon2i" + }, + "space": { + "policy": "custom", + "actions": [ + { "resize": "/dev/vda" }, + { "forceDelete": "/dev/vdb1" } + ] + }, + "volumes": [ + { + "mount": { + "path": "/", + "options": ["ro"] + }, + "filesystem": { + "btrfs": { + "snapshots": true + } + }, + "size": [1024, "5 Gib"], + "target": "default" + }, + { + "mount": { + "path": "/home" + }, + "filesystem": "xfs", + "size": { + "min": "5 GiB", + "max": "20 GiB" + }, + "target": { + "newVg": "/dev/vda" + } + }, + { + "mount": { + "path": "swap" + }, + "filesystem": "swap", + "size": "8 GiB", + "target": { + "newPartition": "/dev/vda" + } + } + ] + } + } +} diff --git a/rust/agama-lib/share/examples/storage.json b/rust/agama-lib/share/examples/storage.json index 573aed64d2..3c80bc5e76 100644 --- a/rust/agama-lib/share/examples/storage.json +++ b/rust/agama-lib/share/examples/storage.json @@ -1,63 +1,68 @@ { "storage": { - "guided": { - "target": { - "disk": "/dev/vdc" - }, - "boot": { - "configure": true, - "device": "/dev/vda" - }, - "encryption": { - "password": "notsecret", - "method": "luks2", - "pbkdFunction": "argon2i" - }, - "space": { - "policy": "custom", - "actions": [ - { "resize": "/dev/vda" }, - { "forceDelete": "/dev/vdb1" } - ] - }, - "volumes": [ - { - "mount": { - "path": "/", - "options": ["ro"] - }, - "filesystem": { - "btrfs": { - "snapshots": true - } - }, - "size": [1024, "5 Gib"], - "target": "default" + "boot": { + "configure": true, + "device": "/dev/vda" + }, + "drives": [ + { + "search": { + "name": "/dev/vda" }, - { - "mount": { - "path": "/home" + "ptableType": "gpt", + "partitions": [ + { + "search": { "name": "/dev/vda2" }, + "encryption": { + "luks1": { + "password": "notsecret" + } + }, + "filesystem": { + "reuse": false, + "type": { + "btrfs": { + "snapshots": true + } + }, + "path": "/", + "mountBy": "uuid", + "mountOptions": ["ro"] + } }, - "filesystem": "xfs", - "size": { - "min": "5 GiB", - "max": "20 GiB" + { + "id": "linux", + "size": "10 GiB", + "encryption": { + "luks2": { + "password": "notsecret", + "label": "data" + } + }, + "filesystem": { + "type": "xfs", + "path": "/home" + } }, - "target": { - "newVg": "/dev/vda" + { + "size": "2 GiB", + "encryption": "random_swap", + "filesystem": { + "type": "swap", + "path": "swap" + } } + ] + }, + { + "search": { + "name": "/dev/vdb" }, - { - "mount": { - "path": "swap" - }, - "filesystem": "swap", - "size": "8 GiB", - "target": { - "newPartition": "/dev/vda" - } + "filesystem": { + "type": "ext4", + "path": "/var/log" } - ] - } + } + ] } } diff --git a/rust/agama-lib/share/profile.schema.json b/rust/agama-lib/share/profile.schema.json index 11381e2da1..d61873f068 100644 --- a/rust/agama-lib/share/profile.schema.json +++ b/rust/agama-lib/share/profile.schema.json @@ -303,41 +303,95 @@ "type": "object", "additionalProperties": false, "properties": { + "boot": { + "$ref": "#/$defs/boot" + }, + "drives": { + "title": "Drive devices", + "description": "Section describing drives (disks, BIOS RAIDs and multipath devices).", + "type": "array", + "items": { + "anyOf": [ + { + "title": "Unpartitioned drive", + "description": "Drive without a partition table (e.g., directly formatted).", + "type": "object", + "additionalProperties": false, + "properties": { + "search": { + "description": "The search is limited to drives scope.", + "$ref": "#/$defs/search" + }, + "encryption": { + "$ref": "#/$defs/encryption" + }, + "filesystem": { + "description": "The partition table (if any) is deleted.", + "$ref": "#/$defs/filesystem" + } + } + }, + { + "title": "Partitioned drive", + "type": "object", + "additionalProperties": false, + "properties": { + "search": { + "description": "The search is limited to drives scope.", + "$ref": "#/$defs/search" + }, + "ptableType": { + "title": "Partition table type", + "description": "The partition table is created only if all the current partitions are deleted.", + "enum": ["gpt", "msdos", "dasd"] + }, + "partitions": { + "$ref": "#/$defs/partitions" + } + } + } + ] + } + }, "guided": { - "title": "Settings to execute a Guided Proposal", + "title": "Guided proposal settings", + "$comment": "This guided section will be extracted to a separate schema. Only storage and legacyAutoyastStorage will be offered as valid schemas for the storage config.", "type": "object", "additionalProperties": false, "properties": { "target": { - "title": "Target device", "anyOf": [ { + "title": "Target for installing", + "description": "Indicates whether to install in a disk or a new LVM.", "enum": ["disk", "newLvmVg"] }, { - "title": "Disk device for installing", + "title": "Target disk", + "description": "Indicates to install in a specific disk device.", "type": "object", "additionalProperties": false, "required": ["disk"], "properties": { "disk": { - "title": "Disk device name", + "title": "Device name", "type": "string", "examples": ["/dev/vda"] } } }, { - "title": "New LVM for installing", + "title": "New LVM", + "description": "Indicates to install in a new LVM created over some specific devices.", "type": "object", "additionalProperties": false, "required": ["newLvmVg"], "properties": { "newLvmVg": { - "title": "Devices in which to create the physical volumes", + "description": "List of devices in which to create the physical volumes.", "type": "array", "items": { - "title": "Disk device name", + "title": "Device name", "type": "string", "examples": ["/dev/vda"] } @@ -347,45 +401,31 @@ ] }, "boot": { - "title": "Configuration of the boot settings", - "type": "object", - "additionalProperties": false, - "required": ["configure"], - "properties": { - "configure": { - "title": "Whether to configure partitions for booting", - "type": "boolean" - }, - "device": { - "title": "Device to use for booting", - "description": "The installation device is used by default for booting", - "type": "string", - "examples": ["/dev/vda"] - } - } + "$ref": "#/$defs/boot" }, "encryption": { - "title": "Encryption settings", + "title": "Encryption", + "description": "Indicates the options for encrypting the new partitions.", "type": "object", "additionalProperties": false, "required": ["password"], "properties": { "password": { - "title": "Passphrase to use when creating new encryption devices", - "type": "string" + "$ref": "#/$defs/encryptionPassword" }, "method": { - "title": "Method used to create the encryption devices", + "title": "Encryption method", + "description": "Method used to encrypt the devices.", "enum": ["luks2", "tpm_fde"] }, "pbkdFunction": { - "title": "Password-based key derivation function to use for LUKS2", - "enum": ["pbkdf2", "argon2i", "argon2id"] + "$ref": "#/$defs/encryptionPbkdFunction" } } }, "space": { - "title": "Policy to find space for the new partitions", + "title": "Space policy", + "description": "Indicates how to find space for the new partitions.", "type": "object", "additionalProperties": false, "properties": { @@ -405,19 +445,20 @@ "required": ["policy", "actions"], "properties": { "actions": { - "title": "Actions to find space if policy is 'custom'", + "title": "Custom actions", + "description": "Indicates what to do with specific devices.", "type": "array", "items": { "anyOf": [ { - "title": "Delete device", - "description": "Force device deletion", + "title": "Force delete", + "description": "Indicates to delete a specific device.", "type": "object", "required": ["forceDelete"], "additionalProperties": false, "properties": { "forceDelete": { - "title": "Device to delete", + "description": "Name of the device to delete.", "type": "string", "examples": ["/dev/vda"] } @@ -425,13 +466,13 @@ }, { "title": "Allow shinking", - "description": "Indicate the device can be shrunk in needed", + "description": "Indicates whether a specific device can be shrunk if needed.", "type": "object", "required": ["resize"], "additionalProperties": false, "properties": { "resize": { - "title": "Device to allow resizing", + "description": "Name of the shrinkable device.", "type": "string", "examples": ["/dev/vda"] } @@ -453,7 +494,8 @@ } }, "volumes": { - "title": "Set of volumes (file systems) to create", + "title": "System volumes", + "description": "List of volumes (file systems) to create.", "type": "array", "items": { "type": "object", @@ -461,126 +503,64 @@ "required": ["mount"], "properties": { "mount": { - "title": "Mount point", + "title": "Mount properties", "type": "object", "additionalProperties": false, "required": ["path"], "properties": { "path": { "title": "Mount path", - "type": "string" + "type": "string", + "examples": ["/dev/vda"] }, "options": { - "title": "Options to add to the fourth field of fstab", + "title": "Mount options", + "description": "Options to add to the fourth field of fstab.", "type": "array", - "items": { "type": "string" } + "items": { + "type": "string" + } } } }, "filesystem": { - "title": "File system of the volume", - "anyOf": [ - { - "title": "File system type", - "enum": [ - "bcachefs", "btrfs", "exfat", "ext2", "ext3", "ext4", "f2fs", "jfs", - "nfs", "nilfs2", "ntfs", "reiserfs", "swap", "tmpfs", "vfat", "xfs" - ] - }, - { - "title": "Btrfs file system", - "description": "Indicates properties of the Btrfs file system", - "type": "object", - "additionalProperties": false, - "required": ["btrfs"], - "properties": { - "btrfs": { - "title": "Specification of a Btrfs file system", - "type": "object", - "additionalProperties": false, - "properties": { - "snapshots": { - "title": "Whether Btrfs snapshots should be configured", - "type": "boolean" - } - } - } - } - } - ] + "$ref": "#/$defs/filesystemType" }, "size": { - "title": "Size limits", - "description": "Options to indicate the size of a device", - "anyOf": [ - { - "title": "Automatic size", - "description": "The size is auto calculated according to the product", - "const": "auto" - }, - { - "title": "Size unit", - "$ref": "#/$defs/sizeValue" - }, - { - "title": "Size range (e.g., [1024, '2 GiB'])", - "description": "Lower size limit and optionally upper size limit", - "type": "array", - "items": { - "$ref": "#/$defs/sizeValue" - }, - "minItems": 1, - "maxItems": 2, - "examples": [[1024, "2 GiB"]] - }, - { - "title": "Size range", - "type": "object", - "additionalProperties": false, - "properties": { - "min": { - "title": "Mandatory lower size limit", - "$ref": "#/$defs/sizeValue" - }, - "max": { - "title": "Optional upper size limit", - "$ref": "#/$defs/sizeValue" - } - }, - "required": ["min"] - } - ] + "$ref": "#/$defs/size" }, "target": { - "title": "Location of the file system", - "description": "Options to indicate the location of a file system", + "title": "Volume target", + "description": "Options to indicate the location of a volume.", "anyOf": [ { + "title": "Default target", + "description": "The volume is created in the target device for installing.", "const": "default" }, { "title": "New partition", - "description": "The file system is created over a new partition", + "description": "The volume is created over a new partition in a specific disk.", "type": "object", "required": ["newPartition"], "additionalProperties": false, "properties": { "newPartition": { - "title": "Name of a disk device", + "description": "Name of a disk device.", "type": "string", "examples": ["/dev/vda"] - } + } } }, { "title": "Dedicated LVM volume group", - "description": "The file system is created over a dedicated LVM", + "description": "The volume is created over a new dedicated LVM.", "type": "object", "additionalProperties": false, "required": ["newVg"], "properties": { "newVg": { - "title": "Name of a disk device", + "description": "Name of a disk device.", "type": "string", "examples": ["/dev/vda"] } @@ -588,13 +568,13 @@ }, { "title": "Re-used existing device", - "description": "The file system is created over an existing device", + "description": "The volume is created over an existing device.", "type": "object", "additionalProperties": false, "required": ["device"], "properties": { "device": { - "title": "Name of a device", + "description": "Name of a device.", "type": "string", "examples": ["/dev/vda1"] } @@ -602,13 +582,13 @@ }, { "title": "Re-used existing file system", - "description": "An existing file system is reused (without formatting)", + "description": "An existing file system is reused (without formatting).", "type": "object", "additionalProperties": false, "required": ["filesystem"], "properties": { "filesystem": { - "title": "Name of a device containing the file system", + "description": "Name of a device containing the file system.", "type": "string", "examples": ["/dev/vda1"] } @@ -625,13 +605,16 @@ }, "legacyAutoyastStorage": { "title": "Legacy AutoYaST storage settings", - "description": "Accepts all options of the AutoYaST profile (XML to JSON)", - "type": "object" + "description": "Accepts all options of the AutoYaST partitioning section (i.e., XML to JSON)", + "type": "array", + "items": { + "type": "object" + } } }, "$defs": { "sizeString": { - "title": "Human readable size (e.g., '2 GiB')", + "title": "Human readable size", "type": "string", "pattern": "^[0-9]+(\\.[0-9]+)?(\\s*([KkMmGgTtPpEeZzYy][iI]?)?[Bb])?$", "examples": ["2 GiB", "1.5 TB", "1TIB", "1073741824 b", "1073741824"] @@ -639,13 +622,294 @@ "sizeInteger": { "title": "Size in bytes", "type": "integer", - "minimum": 0 + "minimum": 0, + "examples": [1024, 2048] }, "sizeValue": { "anyOf": [ { "$ref": "#/$defs/sizeString" }, { "$ref": "#/$defs/sizeInteger" } ] + }, + "size": { + "title": "Size options", + "anyOf": [ + { + "title": "Automatic size", + "description": "The size is auto calculated according to the product.", + "const": "auto" + }, + { + "$ref": "#/$defs/sizeValue" + }, + { + "title": "Size range (tuple syntax)", + "description": "Lower size limit and optionally upper size limit.", + "type": "array", + "items": { + "$ref": "#/$defs/sizeValue" + }, + "minItems": 1, + "maxItems": 2, + "examples": [[1024, 2048], ["1 GiB", "5 GiB"], [1024, "2 GiB"], ["2 GiB"]] + }, + { + "title": "Size range", + "type": "object", + "additionalProperties": false, + "required": ["min"], + "properties": { + "min": { + "title": "Mandatory lower size limit", + "$ref": "#/$defs/sizeValue" + }, + "max": { + "title": "Optional upper size limit", + "$ref": "#/$defs/sizeValue" + } + } + } + ] + }, + "search": { + "title": "Search options", + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { + "title": "Device name", + "type": "string", + "examples": ["/dev/vda"] + } + } + }, + "boot": { + "title": "Boot options", + "description": "Allows configuring boot partitions automatically.", + "type": "object", + "additionalProperties": false, + "required": ["configure"], + "properties": { + "configure": { + "title": "Configure boot", + "description": "Whether to configure partitions for booting.", + "type": "boolean" + }, + "device": { + "title": "Boot device", + "description": "The target installation device is used by default.", + "type": "string", + "examples": ["/dev/vda"] + } + } + }, + "encryptionPassword": { + "title": "Encryption password", + "description": "Password to use when creating a new encryption device.", + "type": "string" + }, + "encryptionCipher": { + "title": "LUKS cipher", + "description": "The value must be compatible with the --cipher argument of the command cryptsetup.", + "type": "string" + }, + "encryptionKeySize": { + "title": "LUKS key size", + "description": "The value (in bits) has to be a multiple of 8. The possible key sizes are limited by the used cipher.", + "type": "integer" + }, + "encryptionPbkdFunction": { + "title": "LUKS2 password-based key derivation", + "enum": ["pbkdf2", "argon2i", "argon2id"] + }, + "encryptionLUKS1": { + "title": "LUKS1 encryption", + "type": "object", + "additionalProperties": false, + "required": ["luks1"], + "properties": { + "luks1": { + "type": "object", + "additionalProperties": false, + "required": ["password"], + "properties": { + "password": { + "$ref": "#/$defs/encryptionPassword" + }, + "cipher": { + "$ref": "#/$defs/encryptionCipher" + }, + "keySize": { + "$ref": "#/$defs/encryptionKeySize" + } + } + } + } + }, + "encryptionLUKS2": { + "title": "LUKS2 encryption", + "type": "object", + "additionalProperties": false, + "required": ["luks2"], + "properties": { + "luks2": { + "type": "object", + "additionalProperties": false, + "required": ["password"], + "properties": { + "password": { + "$ref": "#/$defs/encryptionPassword" + }, + "cipher": { + "$ref": "#/$defs/encryptionCipher" + }, + "keySize": { + "$ref": "#/$defs/encryptionKeySize" + }, + "pbkdFunction": { + "$ref": "#/$defs/encryptionPbkdFunction" + }, + "label": { + "title": "LUKS2 label", + "type": "string" + } + } + } + } + }, + "encryptionPervasiveLUKS2": { + "title": "LUKS2 pervasive encryption", + "type": "object", + "additionalProperties": false, + "required": ["pervasiveLuks2"], + "properties": { + "pervasiveLuks2": { + "type": "object", + "additionalProperties": false, + "required": ["password"], + "properties": { + "password": { + "$ref": "#/$defs/encryptionPassword" + } + } + } + } + }, + "encryptionSwap": { + "title": "Swap encryptions", + "enum": ["protected_swap", "secure_swap", "random_swap"] + }, + "encryption": { + "anyOf": [ + { "$ref": "#/$defs/encryptionLUKS1" }, + { "$ref": "#/$defs/encryptionLUKS2" }, + { "$ref": "#/$defs/encryptionPervasiveLUKS2" }, + { "$ref": "#/$defs/encryptionSwap" } + ] + }, + "filesystemType": { + "anyOf": [ + { + "title": "File system type", + "enum": [ + "bcachefs", "btrfs", "exfat", "ext2", "ext3", "ext4", "f2fs", "jfs", + "nfs", "nilfs2", "ntfs", "reiserfs", "swap", "tmpfs", "vfat", "xfs" + ] + }, + { + "title": "Btrfs file system", + "type": "object", + "additionalProperties": false, + "required": ["btrfs"], + "properties": { + "btrfs": { + "type": "object", + "additionalProperties": false, + "properties": { + "snapshots": { + "title": "Btrfs snapshots", + "description": "Whether to configrue Btrfs snapshots.", + "type": "boolean" + } + } + } + } + } + ] + }, + "filesystem": { + "title": "File system options", + "type": "object", + "additionalProperties": false, + "properties": { + "reuse": { + "title": "Reuse file system", + "description": "Whether to reuse the existing file system (if any).", + "type": "boolean", + "default": false + }, + "type": { + "$ref": "#/$defs/filesystemType" + }, + "label": { + "title": "File system label", + "type": "string" + }, + "path": { + "title": "Mount path", + "type": "string", + "examples": ["/dev/vda"] + }, + "mountBy": { + "title": "How to mount the device", + "enum": ["device", "id", "label", "path", "uuid"] + }, + "mkfsOptions": { + "title": "mkfs options", + "description": "Options for creating the file system.", + "type": "array", + "items": { + "type": "string" + } + }, + "mountOptions": { + "title": "Mount options", + "description": "Options to add to the fourth field of fstab.", + "type": "array", + "items": { "type": "string" } + } + } + }, + "partitions": { + "title": "Partitions", + "description": "Partitions to create, reuse or delete.", + "type": "array", + "items": { + "title": "Partition options", + "type": "object", + "additionalProperties": false, + "properties": { + "search": { + "description": "The search is limited to the partitions of the selected device scope.", + "$ref": "#/$defs/search" + }, + "id": { + "title": "Partition ID", + "enum": ["linux", "swap", "lvm", "raid", "esp", "prep", "bios_boot"] + }, + "size": { + "title": "Partition size", + "$ref": "#/$defs/sizeValue" + }, + "encryption": { + "$ref": "#/$defs/encryption" + }, + "filesystem": { + "$ref": "#/$defs/filesystem" + } + } + } } } } diff --git a/rust/package/agama.changes b/rust/package/agama.changes index a3bcd66804..b2f5eefe21 100644 --- a/rust/package/agama.changes +++ b/rust/package/agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Aug 27 13:57:35 UTC 2024 - José Iván López González + +- Schema definition for basic storage settings + (gh#openSUSE/agama#1455). + ------------------------------------------------------------------- Mon Aug 26 11:19:27 UTC 2024 - Martin Vidner @@ -190,7 +196,7 @@ Fri Jun 7 05:58:48 UTC 2024 - Michal Filka - self-signed certificate contains hostname - self-signed certificate is stored into default location - before creating new self-signed certificate a default location - (/etc/agama.d/ssl) is checked for a certificate + (/etc/agama.d/ssl) is checked for a certificate - gh#openSUSE/agama#1228 -------------------------------------------------------------------