Skip to content

Commit

Permalink
schema: migrate James cc_disk_setup schema to static schema
Browse files Browse the repository at this point in the history
Migrate to static cloud-init-schema.json and add unittests
Needs more unittests for failure cases
  • Loading branch information
blackboxsw committed Jan 25, 2022
1 parent fb219cd commit 552e48b
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 87 deletions.
199 changes: 116 additions & 83 deletions cloudinit/config/cc_disk_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,31 @@
#
# This file is part of cloud-init. See LICENSE file for license information.

"""
Disk Setup
----------
**Summary:** configure partitions and filesystems
"""Disk Setup: Configure partitions and filesystems."""

import logging
import os
import shlex
from textwrap import dedent

from cloudinit import subp, util
from cloudinit.config.schema import get_meta_doc
from cloudinit.distros import ALL_DISTROS
from cloudinit.settings import PER_INSTANCE

# Define the commands to use
SFDISK_CMD = subp.which("sfdisk")
SGDISK_CMD = subp.which("sgdisk")
LSBLK_CMD = subp.which("lsblk")
BLKID_CMD = subp.which("blkid")
BLKDEV_CMD = subp.which("blockdev")
PARTPROBE_CMD = subp.which("partprobe")
WIPEFS_CMD = subp.which("wipefs")

LANG_C_ENV = {"LANG": "C"}
LOG = logging.getLogger(__name__)

MODULE_DESCRIPTION = """\
This module is able to configure simple partition tables and filesystems.
.. note::
Expand All @@ -25,30 +45,51 @@
Disk partitioning is done using the ``disk_setup`` directive. This config
directive accepts a dictionary where each key is either a path to a block
device or an alias specified in ``device_aliases``, and each value is the
configuration options for the device. The ``table_type`` option specifies the
partition table type, either ``mbr`` or ``gpt``. The ``layout`` option
specifies how partitions on the device are to be arranged. If ``layout`` is set
to ``true``, a single partition using all the space on the device will be
created. If set to ``false``, no partitions will be created. Partitions can be
specified by providing a list to ``layout``, where each entry in the list is
configuration options for the device. File system configuration is done using
the ``fs_setup`` directive. This config directive accepts a list of
filesystem configs.
"""

PROPERTY_DESCRIPTIONS = {
"alias_name": """\
Path to disk to be aliased by this name
""",
"table_type": """\
Specifies the partition table type, either ``mbr`` or ``gpt``.
Default: ``mbr``
""",
"layout": """\
If set to ``true``, a single partition using all the space on the device will
be created. If set to ``false``, no partitions will be created. Partitions can
be specified by providing a list to ``layout``, where each entry in the list is
either a size or a list containing a size and the numerical value for a
partition type. The size for partitions is specified in **percentage** of disk
space, not in bytes (e.g. a size of 33 would take up 1/3 of the disk space).
The ``overwrite`` option controls whether this module tries to be safe about
Default: ``false``
""",
"overwrite_disk": """\
Controls whether this module tries to be safe about
writing partition tables or not. If ``overwrite: false`` is set, the device
will be checked for a partition table and for a file system and if either is
found, the operation will be skipped. If ``overwrite: true`` is set, no checks
will be performed.
.. note::
Using ``overwrite: true`` is dangerous and can lead to data loss, so double
check that the correct device has been specified if using this option.
File system configuration is done using the ``fs_setup`` directive. This config
directive accepts a list of filesystem configs. The device to create the
filesystem on may be specified either as a path or as an alias in the format
``<alias name>.<y>`` where ``<y>`` denotes the partition number on the device.
The partition can also be specified by setting ``partition`` to the desired
will be performed. Using ``overwrite: true`` is **dangerous** and can lead to
data loss, so double check that the correct device has been specified if
using this option. Default: ``false``
""",
"label": """\
Label for the filesystem.
""",
"filesystem": """\
Filesystem type to create. E.g., ``ext4`` or ``btrfs``
""",
"device": """\
Specified either as a path or as an alias in the format ``<alias name>.<y>``
where ``<y>`` denotes the partition number on the device. If specifying
device using the ``<device name>.<partition number>`` format, the value
of ``partition`` will be overwritten.
""",
"partition": """\
The partition can be specified by setting ``partition`` to the desired
partition number. The ``partition`` option may also be set to ``auto``, in
which this module will search for the existence of a filesystem matching the
``label``, ``type`` and ``device`` of the ``fs_setup`` entry and will skip
Expand All @@ -59,68 +100,60 @@
filesystem directly to a device, use ``partition: none``. ``partition: none``
will **always** write the filesystem, even when the ``label`` and
``filesystem`` are matched, and ``overwrite`` is ``false``.
""",
"overwrite_fs": """\
If ``true``, overwrite any existing filesystem. Using ``overwrite: true``
for filesystems is **dangerous** and can lead to data loss, so double check
the entry in ``fs_setup``. Default: ``false``
""",
"replace_fs": """\
Ignored unless ``partition`` is ``auto`` or ``any``. Default ``false``.
""",
"extra_opts": """\
Optional options to pass to the filesystem creation command.
Ignored if you using ``cmd`` directly.
""",
"cmd": """\
Optional command to run to create the filesystem.
Can include string substitutions of the other ``fs_setup`` config keys.
This is only necessary if you need to override the default command.
""",
}

meta = {
"id": "cc_disk_setup",
"name": "Disk Setup",
"title": "Configure partitions and filesystems",
"description": MODULE_DESCRIPTION,
"distros": [ALL_DISTROS],
"frequency": PER_INSTANCE,
"examples": [
dedent(
"""\
device_aliases:
my_alias: /dev/sdb
disk_setup:
my_alias:
table_type: gpt
layout: [50, 50]
overwrite: True
fs_setup:
- label: fs1
filesystem: ext4
device: my_alias.1
cmd: mkfs -t %(filesystem)s -L %(label)s %(device)s
- label: fs2
device: my_alias.2
filesystem: ext4
mounts:
- ["my_alias.1", "/mnt1"]
- ["my_alias.2", "/mnt2"]
"""
)
],
}

A label can be specified for the filesystem using
``label``, and the filesystem type can be specified using ``filesystem``.
.. note::
If specifying device using the ``<device name>.<partition number>`` format,
the value of ``partition`` will be overwritten.
.. note::
Using ``overwrite: true`` for filesystems is dangerous and can lead to data
loss, so double check the entry in ``fs_setup``.
.. note::
``replace_fs`` is ignored unless ``partition`` is ``auto`` or ``any``.
**Internal name:** ``cc_disk_setup``
**Module frequency:** per instance
**Supported distros:** all
**Config keys**::
device_aliases:
<alias name>: <device path>
disk_setup:
<alias name/path>:
table_type: <'mbr'/'gpt'>
layout:
- [33,82]
- 66
overwrite: <true/false>
fs_setup:
- label: <label>
filesystem: <filesystem type>
device: <device>
partition: <"auto"/"any"/"none"/<partition number>>
overwrite: <true/false>
replace_fs: <filesystem type>
"""

import logging
import os
import shlex

from cloudinit import subp, util
from cloudinit.settings import PER_INSTANCE

frequency = PER_INSTANCE

# Define the commands to use
SFDISK_CMD = subp.which("sfdisk")
SGDISK_CMD = subp.which("sgdisk")
LSBLK_CMD = subp.which("lsblk")
BLKID_CMD = subp.which("blkid")
BLKDEV_CMD = subp.which("blockdev")
PARTPROBE_CMD = subp.which("partprobe")
WIPEFS_CMD = subp.which("wipefs")

LANG_C_ENV = {"LANG": "C"}

LOG = logging.getLogger(__name__)
__doc__ = get_meta_doc(meta)


def handle(_name, cfg, cloud, log, _args):
Expand Down
109 changes: 108 additions & 1 deletion cloudinit/config/cloud-init-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,112 @@
"type": "boolean"
}
}
},
"cc_disk_setup": {
"type": "object",
"properties": {
"device_aliases": {
"type": "object",
"patternProperties": {
"^.+$": {
"label": "<alias_name>",
"type": "string",
"description": "Path to disk to be aliased by this name."
}
}
},
"disk_setup": {
"type": "object",
"patternProperties": {
"^.+$": {
"label": "<alias name/path>",
"type": "object",
"additionalProperties": false,
"properties": {
"table_type": {
"type": "string",
"enum": ["mbr", "gpt"],
"description": "Specifies the partition table type, either ``mbr`` or ``gpt``. Default: ``mbr``."
},
"layout": {
"type": ["string", "boolean", "array"],
"oneOf": [
{"type": "string", "enum": ["auto", "remove"]},
{"type": "boolean"},
{
"type": "array",
"items": {
"oneOf": [
{"type": "integer"},
{
"type": "array",
"items": {"type": "integer"}
}
]
}
}
],
"description": "If set to ``true``, a single partition using all the space on the device will be created. If set to ``false``, no partitions will be created. Partitions can be specified by providing a list to ``layout``, where each entry in the list is either a size or a list containing a size and the numerical value for a partition type. The size for partitions is specified in **percentage** of disk space, not in bytes (e.g. a size of 33 would take up 1/3 of the disk space). Default: ``false``."
},
"overwrite": {
"type": "boolean",
"description": "Controls whether this module tries to be safe about writing partition tables or not. If ``overwrite: false`` is set, the device will be checked for a partition table and for a file system and if either is found, the operation will be skipped. If ``overwrite: true`` is set, no checks will be performed. Using ``overwrite: true`` is **dangerous** and can lead to data loss, so double check that the correct device has been specified if using this option. Default: ``false``"
}
}
}
}
},
"fs_setup": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"label": {
"type": "string",
"description": "Label for the filesystem."
},
"filesystem": {
"type": "string",
"description": "Filesystem type to create. E.g., ``ext4`` or ``btrfs``"
},
"device": {
"type": "string",
"description": "Specified either as a path or as an alias in the format ``<alias name>.<y>`` where ``<y>`` denotes the partition number on the device. If specifying device using the ``<device name>.<partition number>`` format, the value of ``partition`` will be overwritten."
},
"partition": {
"type": ["string", "integer"],
"oneOf": [
{
"type": "string",
"enum": ["auto", "any", "none"]
},
{"type": "integer"}
],
"description": "The partition can be specified by setting ``partition`` to the desired partition number. The ``partition`` option may also be set to ``auto``, in which this module will search for the existence of a filesystem matching the ``label``, ``type`` and ``device`` of the ``fs_setup`` entry and will skip creating the filesystem if one is found. The ``partition`` option may also be set to ``any``, in which case any file system that matches ``type`` and ``device`` will cause this module to skip filesystem creation for the ``fs_setup`` entry, regardless of ``label`` matching or not. To write a filesystem directly to a device, use ``partition: none``. ``partition: none`` will **always** write the filesystem, even when the ``label`` and ``filesystem`` are matched, and ``overwrite`` is ``false``."
},
"overwrite": {
"type": "boolean",
"description": "If ``true``, overwrite any existing filesystem. Using ``overwrite: true`` for filesystems is **dangerous** and can lead to data loss, so double check the entry in ``fs_setup``. Default: ``false``"
},
"replace_fs": {
"type": "string",
"description": "Ignored unless ``partition`` is ``auto`` or ``any``. Default ``false``."
},
"extra_opts": {
"type": ["array", "string"],
"items": {"type": "string"},
"description": "Optional options to pass to the filesystem creation command. Ignored if you using ``cmd`` directly."
},
"cmd": {
"type": ["array", "string"],
"items": {"type": "string"},
"description": "Optional command to run to create the filesystem. Can include string substitutions of the other ``fs_setup`` config keys. This is only necessary if you need to override the default command."
}
}
}
}
}
}
},
"allOf": [
Expand All @@ -433,6 +539,7 @@
{ "$ref": "#/$defs/cc_ca_certs" },
{ "$ref": "#/$defs/cc_chef" },
{ "$ref": "#/$defs/cc_debug" },
{ "$ref": "#/$defs/cc_disable_ec2_metadata" }
{ "$ref": "#/$defs/cc_disable_ec2_metadata" },
{ "$ref": "#/$defs/cc_disk_setup" }
]
}
Loading

0 comments on commit 552e48b

Please sign in to comment.