Skip to content

Commit

Permalink
feature(storage): config support for generating physical volumes (#1652)
Browse files Browse the repository at this point in the history
Add support to the storage config for using a *generate* section for
physical volumes.

~~~json
"physicalVolumes": [
  { "generate": ["first-disk", "second-disk"] }
]
~~~

~~~json
"physicalVolumes": [
  {
    "generate": {
      "targetDevices": ["first-disk"],
      "encryption": {
        "luks2": { "password": "12345" }
      }
    }
  }
]
~~~

The *generate* section allows to indicate the target devices in which to
automatically create physical volumes, if needed. Agama will try to
create physical volumes to allocate the defined logical volumes. If an
*encryption* section is provided by the *generate* section, then the new
physical volumes will be encrypted.

Notes:

* For now, *physicalVolumes* can contain either device aliases or a
*generate*. In the future it will allow both.
* If there is more than one *generate* in the list of physical volumes,
then only the first one will be considered (the rest ones are ignored).
Note that the schema does not complain.
  • Loading branch information
joseivanlopez authored Oct 9, 2024
2 parents 6cb7771 + 4bd5eac commit c48515c
Show file tree
Hide file tree
Showing 41 changed files with 3,754 additions and 1,650 deletions.
75 changes: 75 additions & 0 deletions doc/auto_storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,81 @@ The *mandatory* keyword can be used for only generating the mandatory partitions
}
```

### Generating Physical Volumes

Volume groups can be configured to explicitly use a set of devices as physical volumes. The aliases
of the devices to use are added to the list of physical volumes:

```json
"storage": {
"drives": [
{
"search": "/dev/vda",
"partitions": [
{ "alias": "pv2" },
{ "alias": "pv1" }
]
}
],
"volumeGroups": [
{
"physicalVolumes": ["pv1", "pv2"]
}
]
}
```

The physical volumes can be automatically generated too, by simply indicating the target devices in
which to create the partitions. For that, a *generate* section is added to the list of physical
volumes:

```json
"storage": {
"drives": [
{
"search": "/dev/vda",
"alias": "pvs-disk"
}
],
"volumeGroups": [
{
"physicalVolumes": [
{ "generate": ["pvs-disk"] }
]
}
]
}
```

If the auto-generated physical volumes have to be encrypted, then the encryption config is added to
the *generate* section:


```json
"storage": {
"drives": [
{
"search": "/dev/vda",
"alias": "pvs-disk"
}
],
"volumeGroups": [
{
"physicalVolumes": [
{
"generate": {
"targetDevices": ["pvs-disk"],
"encryption": {
"luks2": { "password": "12345" }
}
}
}
]
}
]
}
```

### Using the Automatic Proposal

On the first implementations, Agama can rely on the process known as Guided Proposal to calculate
Expand Down
48 changes: 48 additions & 0 deletions rust/agama-lib/share/examples/storage/generate_pvs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"storage": {
"drives": [
{
"alias": "first-disk"
},
{
"partitions": [
{
"alias": "pv1",
"id": "lvm",
"size": { "min": "10 GiB" }
}
]
}
],
"volumeGroups": [
{
"name": "system",
"physicalVolumes": ["pv1"],
"logicalVolumes": [
{
"filesystem": { "path": "/" }
}
]
},
{
"name": "logs",
"physicalVolumes": [
{ "generate": ["first-disk"] }
]
},
{
"name": "data",
"physicalVolumes": [
{
"generate": {
"targetDevices": ["first-disk"],
"encryption": {
"luks2": { "password": "12345" }
}
}
}
]
}
]
}
}
55 changes: 50 additions & 5 deletions rust/agama-lib/share/profile.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -529,11 +529,56 @@
"physicalVolumes": {
"title": "Physical volumes",
"description": "Devices to use as physical volumes.",
"type": "array",
"items": {
"title": "Device alias",
"type": "string"
}
"$comment": "In the future it would be possible to indicate both aliases and 'generate' items together.",
"anyOf": [
{
"type": "array",
"items": {
"title": "Device alias",
"type": "string"
}
},
{
"type": "array",
"items": {
"title": "Generate physical volumes",
"description": "Automatically creates the needed physical volumes in the indicated devices.",
"type": "object",
"additionalProperties": false,
"required": ["generate"],
"properties": {
"generate": {
"anyOf": [
{
"type": "array",
"items": {
"title": "Device alias",
"type": "string"
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["targetDevices"],
"properties": {
"targetDevices": {
"type": "array",
"items": {
"title": "Device alias",
"type": "string"
}
},
"encryption": {
"$ref": "#/$defs/encryption"
}
}
}
]
}
}
}
}
]
},
"logicalVolumes": {
"title": "Logical volumes",
Expand Down
23 changes: 23 additions & 0 deletions service/lib/agama/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,31 @@ def arch_elements_from(*keys, property: nil, default: [])
end.compact
end

# Default paths to be created for the product.
#
# @return [Array<String>]
def default_paths
data.dig("storage", "volumes") || []
end

# Mandatory paths to be created for the product.
#
# @return [Array<String>]
def mandatory_paths
default_paths.select { |p| mandatory_path?(p) }
end

private

def mandatory_path?(path)
templates = data.dig("storage", "volume_templates") || []
template = templates.find { |t| t["mount_path"] == path }

return false unless template

template.dig("outline", "required") || false
end

# Simple deep merge
#
# @param a_hash [Hash] Default values
Expand Down
10 changes: 0 additions & 10 deletions service/lib/agama/storage/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,6 @@ def initialize
@nfs_mounts = []
end

# Creates a config from JSON hash according to schema.
#
# @param config_json [Hash]
# @param product_config [Agama::Config]
#
# @return [Storage::Config]
def self.new_from_json(config_json, product_config:)
ConfigConversions::FromJSON.new(config_json, product_config: product_config).convert
end

# Name of the device that will presumably be used to boot the target system
#
# @return [String, nil] nil if there is no enough information to infer a possible boot disk
Expand Down
Loading

0 comments on commit c48515c

Please sign in to comment.