summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authors-makin <sally.makin@canonical.com>2023-01-10 19:06:30 +0000
committerGitHub <noreply@github.com>2023-01-10 12:06:30 -0700
commiteb22a2426d4df1d1870dbef04f5edf7f58356ee1 (patch)
treedccd36968f27d60f08c4dc023e7950fc7af75a6f /doc
parentcb128dc1b76bf0a48783ecb815e02ecbc0f1a41f (diff)
downloadcloud-init-git-eb22a2426d4df1d1870dbef04f5edf7f58356ee1.tar.gz
docs: Diataxis overhaul (#1933)
Diataxis overhaul and style review Introduces the Diataxis[1] framework including: - Created Diataxis folders - Moved all content to correct folders - Updated index page with Diataxis sections - Brought LHS nav bar into line with Diataxis - Brought all docs in line with Ubuntu style guide Additional minor/housekeeping changes: - Added anchor tags/updated others - Moved how-to content out of FAQ page (created new pages) - Decorated various elements with tags (see below) - Acronyms capitalised (and expanded on first showing if poss) - All headings now sentence case - Styling on all pages now self-consistent with each other - Some minor edits to language, mostly for clarity - Lists presented with headings in boldface changed to subheadings - (to make use of RHS navigation bar for user convenience) I also addressed inconsistencies in formatting and language. I'm aware that some of these changes may need to be reverted or changed to something else, so if I've made any errors in judgement through lack of knowledge, please lmk (or if there are overdue changes you want to make now while I'm doing it). I have decorated files/paths with the :file: rST tag, obvious commands with :command:, keyboard shortcuts with :kbd: and references to UI elements with :guilabel: - the default styling may not be ideal, but with the tags in place it can be edited en-masse through the style files so the text elements display as expected. There is an :abbr: tag that theoretically works like the hoverxref package, but the default styling makes it hard to read the text so I have not used it. There are similar tags for Python elements but I haven't used them either, due to unfamiliarity with the base code. [1] https://diataxis.fr/
Diffstat (limited to 'doc')
-rw-r--r--doc/rtd/development/analyze.rst (renamed from doc/rtd/topics/analyze.rst)127
-rw-r--r--doc/rtd/development/code_review.rst (renamed from doc/rtd/topics/code_review.rst)204
-rw-r--r--doc/rtd/development/contributing.rst (renamed from doc/rtd/topics/contributing.rst)1
-rw-r--r--doc/rtd/development/debugging.rst (renamed from doc/rtd/topics/debugging.rst)179
-rw-r--r--doc/rtd/development/dir_layout.rst (renamed from doc/rtd/topics/dir_layout.rst)34
-rw-r--r--doc/rtd/development/docs.rst136
-rw-r--r--doc/rtd/development/index.rst49
-rw-r--r--doc/rtd/development/integration_tests.rst214
-rw-r--r--doc/rtd/development/logging.rst278
-rw-r--r--doc/rtd/development/module_creation.rst (renamed from doc/rtd/topics/module_creation.rst)30
-rw-r--r--doc/rtd/development/security.rst (renamed from doc/rtd/topics/security.rst)4
-rw-r--r--doc/rtd/development/testing.rst (renamed from doc/rtd/topics/testing.rst)131
-rw-r--r--doc/rtd/explanation/boot.rst263
-rw-r--r--doc/rtd/explanation/configuration.rst81
-rw-r--r--doc/rtd/explanation/events.rst95
-rw-r--r--doc/rtd/explanation/format.rst (renamed from doc/rtd/topics/format.rst)135
-rw-r--r--doc/rtd/explanation/index.rst18
-rw-r--r--doc/rtd/explanation/instancedata.rst (renamed from doc/rtd/topics/instancedata.rst)509
-rw-r--r--doc/rtd/explanation/kernel-cmdline.rst69
-rw-r--r--doc/rtd/explanation/vendordata.rst71
-rw-r--r--doc/rtd/howto/bugs.rst (renamed from doc/rtd/topics/bugs.rst)72
-rw-r--r--doc/rtd/howto/index.rst23
-rw-r--r--doc/rtd/howto/module_run_frequency.rst40
-rw-r--r--doc/rtd/howto/predeploy_testing.rst141
-rw-r--r--doc/rtd/index.rst135
-rw-r--r--doc/rtd/reference/availability.rst (renamed from doc/rtd/topics/availability.rst)16
-rw-r--r--doc/rtd/reference/base_config_reference.rst (renamed from doc/rtd/topics/base_config_reference.rst)232
-rw-r--r--doc/rtd/reference/cli.rst414
-rw-r--r--doc/rtd/reference/datasources.rst134
-rw-r--r--doc/rtd/reference/datasources/aliyun.rst (renamed from doc/rtd/topics/datasources/aliyun.rst)49
-rw-r--r--doc/rtd/reference/datasources/altcloud.rst (renamed from doc/rtd/topics/datasources/altcloud.rst)53
-rw-r--r--doc/rtd/reference/datasources/azure.rst133
-rw-r--r--doc/rtd/reference/datasources/cloudsigma.rst39
-rw-r--r--doc/rtd/reference/datasources/cloudstack.rst66
-rw-r--r--doc/rtd/reference/datasources/configdrive.rst141
-rw-r--r--doc/rtd/reference/datasources/digitalocean.rst32
-rw-r--r--doc/rtd/reference/datasources/e24cloud.rst10
-rw-r--r--doc/rtd/reference/datasources/ec2.rst153
-rw-r--r--doc/rtd/reference/datasources/exoscale.rst83
-rw-r--r--doc/rtd/reference/datasources/fallback.rst19
-rw-r--r--doc/rtd/reference/datasources/gce.rst (renamed from doc/rtd/topics/datasources/gce.rst)36
-rw-r--r--doc/rtd/reference/datasources/lxd.rst (renamed from doc/rtd/topics/datasources/lxd.rst)92
-rw-r--r--doc/rtd/reference/datasources/maas.rst (renamed from doc/rtd/topics/datasources/maas.rst)0
-rw-r--r--doc/rtd/reference/datasources/nocloud.rst221
-rw-r--r--doc/rtd/reference/datasources/nwcs.rst28
-rw-r--r--doc/rtd/reference/datasources/opennebula.rst (renamed from doc/rtd/topics/datasources/opennebula.rst)77
-rw-r--r--doc/rtd/reference/datasources/openstack.rst128
-rw-r--r--doc/rtd/reference/datasources/oracle.rst53
-rw-r--r--doc/rtd/reference/datasources/ovf.rst12
-rw-r--r--doc/rtd/reference/datasources/rbxcloud.rst23
-rw-r--r--doc/rtd/reference/datasources/smartos.rst181
-rw-r--r--doc/rtd/reference/datasources/upcloud.rst22
-rw-r--r--doc/rtd/reference/datasources/vmware.rst451
-rw-r--r--doc/rtd/reference/datasources/vultr.rst32
-rw-r--r--doc/rtd/reference/datasources/zstack.rst36
-rw-r--r--doc/rtd/reference/examples.rst (renamed from doc/rtd/topics/examples.rst)15
-rw-r--r--doc/rtd/reference/faq.rst288
-rw-r--r--doc/rtd/reference/index.rst21
-rw-r--r--doc/rtd/reference/merging.rst292
-rw-r--r--doc/rtd/reference/modules.rst (renamed from doc/rtd/topics/modules.rst)16
-rw-r--r--doc/rtd/reference/network-config-format-eni.rst (renamed from doc/rtd/topics/network-config-format-eni.rst)15
-rw-r--r--doc/rtd/reference/network-config-format-v1.rst647
-rw-r--r--doc/rtd/reference/network-config-format-v2.rst (renamed from doc/rtd/topics/network-config-format-v2.rst)389
-rw-r--r--doc/rtd/reference/network-config.rst317
-rw-r--r--doc/rtd/topics/boot.rst246
-rw-r--r--doc/rtd/topics/cli.rst405
-rw-r--r--doc/rtd/topics/configuration.rst79
-rw-r--r--doc/rtd/topics/datasources.rst114
-rw-r--r--doc/rtd/topics/datasources/azure.rst125
-rw-r--r--doc/rtd/topics/datasources/cloudsigma.rst42
-rw-r--r--doc/rtd/topics/datasources/cloudstack.rst54
-rw-r--r--doc/rtd/topics/datasources/configdrive.rst133
-rw-r--r--doc/rtd/topics/datasources/digitalocean.rst32
-rw-r--r--doc/rtd/topics/datasources/e24cloud.rst9
-rw-r--r--doc/rtd/topics/datasources/ec2.rst141
-rw-r--r--doc/rtd/topics/datasources/exoscale.rst69
-rw-r--r--doc/rtd/topics/datasources/fallback.rst18
-rw-r--r--doc/rtd/topics/datasources/nocloud.rst191
-rw-r--r--doc/rtd/topics/datasources/nwcs.rst30
-rw-r--r--doc/rtd/topics/datasources/openstack.rst93
-rw-r--r--doc/rtd/topics/datasources/oracle.rst49
-rw-r--r--doc/rtd/topics/datasources/ovf.rst14
-rw-r--r--doc/rtd/topics/datasources/rbxcloud.rst23
-rw-r--r--doc/rtd/topics/datasources/smartos.rst170
-rw-r--r--doc/rtd/topics/datasources/upcloud.rst24
-rw-r--r--doc/rtd/topics/datasources/vmware.rst434
-rw-r--r--doc/rtd/topics/datasources/vultr.rst35
-rw-r--r--doc/rtd/topics/datasources/zstack.rst37
-rw-r--r--doc/rtd/topics/docs.rst76
-rw-r--r--doc/rtd/topics/events.rst95
-rw-r--r--doc/rtd/topics/faq.rst450
-rw-r--r--doc/rtd/topics/integration_tests.rst208
-rw-r--r--doc/rtd/topics/kernel-cmdline.rst71
-rw-r--r--doc/rtd/topics/logging.rst267
-rw-r--r--doc/rtd/topics/merging.rst288
-rw-r--r--doc/rtd/topics/network-config-format-v1.rst625
-rw-r--r--doc/rtd/topics/network-config.rst321
-rw-r--r--doc/rtd/topics/tutorials/lxd.rst165
-rw-r--r--doc/rtd/topics/tutorials/qemu-debugging.rst41
-rw-r--r--doc/rtd/topics/tutorials/qemu.rst295
-rw-r--r--doc/rtd/topics/vendordata.rst73
-rw-r--r--doc/rtd/tutorial/index.rst37
-rw-r--r--doc/rtd/tutorial/lxd.rst175
-rw-r--r--doc/rtd/tutorial/qemu-debugging.rst41
-rwxr-xr-xdoc/rtd/tutorial/qemu-script.sh (renamed from doc/rtd/topics/tutorials/qemu-script.sh)0
-rw-r--r--doc/rtd/tutorial/qemu.rst292
106 files changed, 7341 insertions, 6751 deletions
diff --git a/doc/rtd/topics/analyze.rst b/doc/rtd/development/analyze.rst
index 33ab911b..93961928 100644
--- a/doc/rtd/topics/analyze.rst
+++ b/doc/rtd/development/analyze.rst
@@ -3,19 +3,19 @@
Performance
***********
-The ``analyze`` subcommand was added to cloud-init to help analyze
-cloud-init boot time performance. It is loosely based on systemd-analyze where
-there are four subcommands:
+The :command:`analyze` subcommand was added to ``cloud-init`` to help analyze
+``cloud-init`` boot time performance. It is loosely based on
+``systemd-analyze``, where there are four subcommands:
-- blame
-- show
-- dump
-- boot
+- :command:`blame`
+- :command:`show`
+- :command:`dump`
+- :command:`boot`
Usage
=====
-The analyze command requires one of the four subcommands:
+The :command:`analyze` command requires one of the four subcommands:
.. code-block:: shell-session
@@ -27,19 +27,19 @@ The analyze command requires one of the four subcommands:
Availability
============
-The ``analyze`` subcommand is generally available across all distributions,
-with the exception of Gentoo and FreeBSD.
+The :command:`analyze` subcommand is generally available across all
+distributions, with the exception of Gentoo and FreeBSD.
Subcommands
===========
-Blame
------
+:command:`Blame`
+----------------
-The ``blame`` action matches ``systemd-analyze blame`` where it prints, in
-descending order, the units that took the longest to run. This output is
-highly useful for examining where cloud-init is spending its time during
-execution.
+The :command:`blame` subcommand matches :command:`systemd-analyze blame` where
+it prints, in descending order, the units that took the longest time to run.
+This output is highly useful for examining where ``cloud-init`` is spending
+its time.
.. code-block:: shell-session
@@ -110,17 +110,17 @@ Example output:
1 boot records analyzed
-Show
-----
+:command:`Show`
+---------------
-The ``show`` action is similar to ``systemd-analyze critical-chain`` which
-prints a list of units, the time they started and how long they took.
-Cloud-init has four :ref:`boot stages<boot_stages>`, and within each stage a
-number of modules may run depending on configuration.
-``cloudinit-analyze show`` will, for each boot, print this information and a
-summary of the total time.
+The :command:`show` subcommand is similar to
+:command:`systemd-analyze critical-chain` which prints a list of units, the
+time they started and how long they took. ``Cloud-init`` has five
+:ref:`boot stages<boot_stages>`, and within each stage a number of modules may
+run depending on configuration. :command:`cloudinit-analyze show` will, for
+each boot, print this information and a summary of the total time.
-The following is an abbreviated example of the show output:
+The following is an abbreviated example of the :command:`show` subcommand:
.. code-block:: shell-session
@@ -169,12 +169,13 @@ Example output:
If additional boot records are detected then they are printed out from oldest
to newest.
-Dump
-----
+:command:`Dump`
+---------------
-The ``dump`` action simply dumps the cloud-init logs that the analyze module
-is performing the analysis on and returns a list of dictionaries that can be
-consumed for other reporting needs. Each element in the list is a boot entry.
+The :command:`dump` subcommand simply dumps the ``cloud-init`` logs that the
+:command:`analyze` module is performing its analysis on, and returns a list of
+dictionaries that can be consumed for other reporting needs. Each element in
+the list is a boot entry.
.. code-block:: shell-session
@@ -264,20 +265,20 @@ Example output:
]
-Boot
-----
+:command:`Boot`
+---------------
-The ``boot`` action prints out kernel related timestamps that are not included
-in any of the cloud-init logs. There are three different timestamps that are
-presented to the user:
+The :command:`boot` subcommand prints out kernel-related timestamps that are
+not included in any of the ``cloud-init`` logs. There are three different
+timestamps that are presented to the user:
-- kernel start
-- kernel finish boot
-- cloud-init start
+- ``kernel start``
+- ``kernel finish boot``
+- ``cloud-init start``
-This was added for additional clarity into the boot process that cloud-init
-does not have control over, to aid in debugging of performance issues related
-to cloud-init startup, and tracking regression.
+This was added for additional clarity into the boot process that
+``cloud-init`` does not have control over, to aid in debugging performance
+issues related to ``cloud-init`` startup, and tracking regression.
.. code-block:: shell-session
@@ -296,20 +297,20 @@ Example output:
Cloud-init start: 2019-08-29 08:35:45.867000
successful
-Timestamp Gathering
-^^^^^^^^^^^^^^^^^^^
+Timestamp gathering
+-------------------
-The following boot related timestamps are gathered on demand when cloud-init
-analyze boot runs:
+The following boot-related timestamps are gathered on demand when
+:command:`cloud-init analyze boot` runs:
-- Kernel startup gathered from system uptime
-- Kernel finishes initialization from systemd
- UserSpaceMonotonicTimestamp property
-- Cloud-init activation from the property InactiveExitTimestamp of the
- cloud-init local systemd unit
+ - Kernel startup gathered from system uptime
+ - Kernel finishes initialization from systemd
+ ``UserSpaceMonotonicTimestamp`` property
+ - ``Cloud-init`` activation from the property ``InactiveExitTimestamp``
+ of the ``cloud-init`` local systemd unit
In order to gather the necessary timestamps using systemd, running the
-following command will gather the UserspaceTimestamp:
+following command will gather the ``UserspaceTimestamp``:
.. code-block:: shell-session
@@ -321,10 +322,10 @@ Example output:
UserspaceTimestampMonotonic=989279
-The UserspaceTimestamp tracks when the init system starts, which is used as
-an indicator of kernel finishing initialization.
+The ``UserspaceTimestamp`` tracks when the init system starts, which is used
+as an indicator of the kernel finishing initialisation.
-Running the following command will gather the InactiveExitTimestamp:
+Running the following command will gather the ``InactiveExitTimestamp``:
.. code-block:: shell-session
@@ -336,18 +337,16 @@ Example output:
InactiveExitTimestampMonotonic=4493126
-The InactiveExitTimestamp tracks when a particular systemd unit transitions
-from the Inactive to Active state, which can be used to mark the beginning
-of systemd's activation of cloud-init.
+The ``InactiveExitTimestamp`` tracks when a particular systemd unit
+transitions from the `Inactive` to `Active` state, which can be used to mark
+the beginning of systemd's activation of ``cloud-init``.
Currently this only works for distros that use systemd as the init process.
We will be expanding support for other distros in the future and this document
will be updated accordingly.
-If systemd is not present on the system, dmesg is used to attempt to find an
-event that logs the beginning of the init system. However, with this method
-only the first two timestamps are able to be found; dmesg does not monitor
-userspace processes, so no cloud-init start timestamps are emitted like when
-using systemd.
-
-.. vi: textwidth=79
+If systemd is not present on the system, ``dmesg`` is used to attempt to find
+an event that logs the beginning of the init system. However, with this method
+only the first two timestamps are able to be found; ``dmesg`` does not monitor
+userspace processes, so no ``cloud-init`` start timestamps are emitted --
+unlike when using systemd.
diff --git a/doc/rtd/topics/code_review.rst b/doc/rtd/development/code_review.rst
index 2be78ed5..5684a509 100644
--- a/doc/rtd/topics/code_review.rst
+++ b/doc/rtd/development/code_review.rst
@@ -1,12 +1,13 @@
.. _code_review_process:
-Code Review Process
+Code review process
*******************
In order to manage incoming pull requests effectively, and provide
-timely feedback and/or acceptance this document serves as a guideline
-for the review process and outlines the expectations for those
+timely feedback and/or acceptance, this document serves as a guideline
+for the review process. It outlines the expectations for those
submitting code to the project as well as those reviewing the code.
+
Code is reviewed for acceptance by at least one core team member (later
referred to as committers), but comments and suggestions from others
are encouraged and welcome.
@@ -14,156 +15,154 @@ are encouraged and welcome.
The process is intended to provide timely and actionable feedback for
any submission.
-Asking For Help
+Asking for help
===============
-cloud-init contributors, potential contributors, community members and
-users are encouraged to ask for any help that they need. If you have
+``cloud-init`` contributors, potential contributors, community members and
+users are encouraged to ask for any help that they need. If you have
questions about the code review process, or at any point during the
code review process, these are the available avenues:
-* if you have an open Pull Request, comment on that pull request
-* join the ``#cloud-init`` channel on the Libera IRC network and ask
- away
-* send an email to the cloud-init mailing list,
- cloud-init@lists.launchpad.net
+* if you have an open Pull Request, comment on that pull request,
+* join the ``#cloud-init`` `channel on the Libera IRC`_ network,
+* send an email to the cloud-init mailing list: ::
+
+ cloud-init@lists.launchpad.net
-These are listed in rough order of preference, but use whichever of
-them you are most comfortable with.
+These are listed in order of preference, but please use whichever of them you
+are most comfortable with.
Goals
=====
This process has the following goals:
-* Ensure code reviews occur in a timely fashion and provide actionable
+* To ensure code reviews occur in a timely fashion and provide actionable
feedback if changes are desired.
-* Ensure the minimization of ancillary problems to increase the
- efficiency for those reviewing the submitted code
+* To ensure the minimisation of ancillary problems to increase the
+ efficiency for those reviewing the submitted code.
-Role Definitions
+Role definitions
================
-Any code review process will have (at least) two involved parties. For
+Any code review process will have (at least) two involved parties. For
our purposes, these parties are referred to as **Proposer** and
-**Reviewer**. (We also have the **Committer** role which is a special
-case of the **Reviewer** role.) The terms are defined here (and the
-use of the singular form is not meant to imply that they refer to a
-single person):
+**Reviewer**. We also have the **Committer** role which is a special
+case of the **Reviewer** role.
-Proposer
+The terms are defined here (and the use of the singular form is not meant to
+imply that they refer to a single person):
+
+**Proposer**
The person proposing a pull request (hereafter known as a PR).
-Reviewer
+**Reviewer**
A person who is reviewing a PR.
-Committer
- A cloud-init core developer (i.e. a person who has permission to
- merge PRs into **main**).
+**Committer**
+ A cloud-init core developer (i.e., a person who has permission to
+ merge PRs into ``main``).
-Prerequisites For Landing Pull Requests
+Prerequisites for landing pull requests
=======================================
-Before a PR can be landed into **main**, the following conditions *must*
+Before a PR can be landed into ``main``, the following conditions *must*
be met:
* the CLA has been signed by the **Proposer** (or is covered by an
- entity-level CLA signature)
-* all required status checks are passing
-* at least one "Approve" review from a **Committer**
-* no "Request changes" reviews from any **Committer**
+ entity-level CLA signature),
+* all required status checks are passing,
+* at least one "Approve" review has been received from a **Committer**, and
+* no "Request changes" reviews from any **Committer** are outstanding.
The following conditions *should* be met:
-* any Python functions/methods/classes have docstrings added/updated
-* any changes to config module behaviour are captured in the
- documentation of the config module
-* any Python code added has corresponding unit tests
-* no "Request changes" reviews from any **Reviewer**
+* any Python functions/methods/classes have docstrings added/updated,
+* any changes to config module behaviour are captured in the documentation of
+ the config module,
+* any Python code added has corresponding unit tests, and
+* no "Request changes" reviews from any **Reviewer** are outstanding.
These conditions can be relaxed at the discretion of the
-**Committers** on a case-by-case basis. Generally, for accountability,
+**Committers** on a case-by-case basis. Generally, for accountability,
this should not be the decision of a single **Committer**, and the
decision should be documented in comments on the PR.
(To take a specific example, the ``cc_phone_home`` module had no tests
-at the time `PR #237
-<https://github.com/canonical/cloud-init/pull/237>`_ was submitted, so
-the **Proposer** was not expected to write a full set of tests for
-their minor modification, but they were expected to update the config
-module docs.)
+at the time `PR #237`_ was submitted, so the **Proposer** was not expected to
+write a full set of tests for their minor modification, but they were expected
+to update the config module docs.)
-Non-Committer Reviews
+Non-Committer reviews
=====================
-Reviews from non-**Committers** are *always* welcome. Please feel
-empowered to review PRs and leave your thoughts and comments on any
-submitted PRs, regardless of the **Proposer**.
+Reviews from non-**Committers** are *always* welcome. Please feel empowered to
+review PRs and leave your thoughts and comments on any submitted PRs,
+regardless of the **Proposer**.
-Much of the below process is written in terms of the **Committers**.
-This is not intended to reflect that reviews should only come from that
-group, but acknowledges that we are ultimately responsible for
-maintaining the standards of the codebase. It would be entirely
-reasonable (and very welcome) for a **Reviewer** to only examine part
-of a PR, but it would not be appropriate for a **Committer** to merge a
-PR without full scrutiny.
+Much of the below process is written in terms of the **Committers**. This is
+not intended to reflect that reviews should only come from that group, but
+rather an acknowledgement that we are ultimately responsible for maintaining
+the standards of the codebase. It would be entirely reasonable (and very
+welcome) for a **Reviewer** to only examine part of a PR, but it would not be
+appropriate for a **Committer** to merge a PR without full scrutiny.
-Opening Phase
+Opening phase
=============
-In this phase, the **Proposer** is responsible for opening a pull
-request and meeting the prerequisites laid out above.
+In this phase, the **Proposer** is responsible for opening a pull request and
+meeting the prerequisites laid out above.
If they need help understanding the prerequisites, or help meeting the
-prerequisites, then they can (and should!) ask for help. See the
+prerequisites, then they can (and should!) ask for help. See the
`Asking For Help`_ section above for the ways to do that.
These are the steps that comprise the opening phase:
-1. The **Proposer** opens PR
+1. The **Proposer** opens a PR
-2. CI runs automatically, and if
+2. CI runs automatically, and if:
- CI fails
- The **Proposer** is expected to fix CI failures. If the
+ CI fails:
+ The **Proposer** is expected to fix CI failures. If the
**Proposer** doesn't understand the nature of the failures they
are seeing, they should comment in the PR to request assistance,
or use another way of `Asking For Help`_.
(Note that if assistance is not requested, the **Committers**
will assume that the **Proposer** is working on addressing the
- failures themselves. If you require assistance, please do ask
+ failures themselves. If you require assistance, please do ask
for help!)
- CI passes
- Move on to the `Review Phase`_.
+ CI passes:
+ Move on to the `Review phase`_.
-Review Phase
+Review phase
============
In this phase, the **Proposer** and the **Reviewers** will iterate
-together to, hopefully, get the PR merged into the cloud-init codebase.
+together to, hopefully, get the PR merged into the ``cloud-init`` codebase.
There are three potential outcomes: merged, rejected permanently, and
-temporarily closed. (The first two are covered in this section; see
-`Inactive Pull Requests`_ for details about temporary closure.)
+temporarily closed. The first two are covered in this section; see
+`Inactive Pull Requests`_ for details about temporary closure.
-(In the below, when the verbs "merge" or "squash merge" are used, they
+In this section, when the verbs "merge" or "squash merge" are used, they
should be understood to mean "squash merged using the GitHub UI", which
-is the only way that changes can land in cloud-init's **main** branch.)
+is the only way that changes can land in ``cloud-init``'s ``main`` branch.
These are the steps that comprise the review phase:
-1. **The Committers** assign a **Committer** to the PR
+1. **The Committers** assign a **Committer** to the PR:
- This **Committer** is expected to shepherd the PR to completion (and
- merge it, if that is the outcome reached). This means that they
+ This **Committer** is expected to shepherd the PR to completion (and to
+ merge it, if that is the outcome reached). This means that they
will perform an initial review, and monitor the PR to ensure that
- the **Proposer** is receiving any assistance that they require. The
+ the **Proposer** is receiving any assistance that they require. The
**Committers** will perform this assignment on a daily basis.
This assignment is intended to ensure that the **Proposer** has a
- clear point of contact with a cloud-init core developer, and that
- they get timely feedback after submitting a PR. It *is not*
+ clear point of contact with a ``cloud-init`` core developer, and that
+ they get timely feedback after submitting a PR. It *is not*
intended to preclude reviews from any other **Reviewers**, nor to
imply that the **Committer** has ownership over the review process.
@@ -171,33 +170,33 @@ These are the steps that comprise the review phase:
a PR to another **Reviewer** if they think that they would be better
suited.
- (Note that, in GitHub terms, this is setting an Assignee, not
+ (Note that, in GitHub terms, this is setting an `Assignee`, not
requesting a review.)
2. That **Committer** performs an initial review of the PR, resulting
in one of the following:
- Approve
+ Approve:
If the submitted PR meets all of the `Prerequisites for
Landing Pull Requests`_ and passes code review, then the
**Committer** will squash merge immediately.
There may be circumstances where a PR should not be merged
- immediately. The ``wip`` label will be applied to PRs for which
- this is true. Only **Committers** are able to apply labels to
+ immediately. The :guilabel:`wip` label will be applied to PRs for which
+ this is true. Only **Committers** are able to apply labels to
PRs, so anyone who believes that this label should be applied to a
PR should request its application in a comment on the PR.
The review process is **DONE**.
- Approve (with nits)
- If the **Proposer** submits their PR with "Allow edits from
- maintainer" enabled, and the only changes the **Committer**
+ Approve (with nits):
+ If the **Proposer** submits their PR with :guilabel:`"Allow edits from
+ maintainer"` enabled, and the only changes the **Committer**
requests are minor "nits", the **Committer** can push fixes for
- those nits and *immediately* squash merge. If the **Committer**
+ those nits and *immediately* squash merge. If the **Committer**
does not wish to fix these nits but believes they should block a
- straight-up Approve, then their review should be "Needs Changes"
- instead.
+ straightforward :guilabel:`Approve`, then their review should be "Needs
+ Changes" instead.
A nit is understood to be something like a minor style issue or a
spelling error, generally confined to a single line of code.
@@ -206,29 +205,30 @@ These are the steps that comprise the review phase:
is a nit, they should not treat it as a nit.
(If a **Proposer** wants to opt-out of this, then they should
- uncheck "Allow edits from maintainer" when submitting their PR.)
+ uncheck :guilabel:`"Allow edits from maintainer"` when submitting their
+ PR.)
The review process is **DONE**.
- Outright rejection
+ Outright rejection:
The **Committer** will close the PR, with useful messaging for the
**Proposer** as to why this has happened.
This is reserved for cases where the proposed change is completely
- unfit for landing, and there is no reasonable path forward. This
+ unfit for landing, and there is no reasonable path forward. This
should only be used sparingly, as there are very few cases where
proposals are completely unfit.
If a different approach to the same problem is planned, it should
- be submitted as a separate PR. The **Committer** should include
+ be submitted as a separate PR. The **Committer** should include
this information in their message when the PR is closed.
The review process is **DONE**.
- Needs Changes
+ Needs Changes:
The **Committer** will give the **Proposer** a clear idea of what
- is required for an Approve vote or, for more complex PRs, what the
- next steps towards an Approve vote are.
+ is required for an :guilabel:`Approve` vote or, for more complex PRs,
+ what the next steps towards an :guilabel:`Approve` vote are.
The **Proposer** will ask questions if they don't understand, or
disagree with, the **Committer**'s review comments.
@@ -237,21 +237,25 @@ These are the steps that comprise the review phase:
review comments.
Once the review comments are addressed (as well as, potentially,
- in the interim), CI will run. If CI fails, the **Proposer** is
- expected to fix CI failures. If CI passes, the **Proposer**
+ in the interim), CI will run. If CI fails, the **Proposer** is
+ expected to fix CI failures. If CI passes, the **Proposer**
should indicate that the PR is ready for re-review (by @ing the
assigned reviewer), effectively moving back to the start of this
section.
-Inactive Pull Requests
+Inactive pull requests
======================
PRs will be temporarily closed if they have been waiting on
-**Proposer** action for a certain amount of time without activity. A
+**Proposer** action for a certain amount of time without activity. A
PR will be marked as stale (with an explanatory comment) after 14 days
-of inactivity. It will be closed after a further 7 days of inactivity.
+of inactivity. It will be closed after a further 7 days of inactivity.
These closes are not considered permanent, and the closing message
should reflect this for the **Proposer**. However, if a PR is reopened,
it should effectively enter the `Opening phase`_ again, as it may
need some work done to get CI passing again.
+
+.. LINKS:
+.. _channel on the Libera IRC: https://kiwiirc.com/nextclient/irc.libera.chat/cloud-init
+.. _PR #237: https://github.com/canonical/cloud-init/pull/237
diff --git a/doc/rtd/topics/contributing.rst b/doc/rtd/development/contributing.rst
index b9aee867..b1cd2f37 100644
--- a/doc/rtd/topics/contributing.rst
+++ b/doc/rtd/development/contributing.rst
@@ -1,2 +1 @@
.. include:: ../../../CONTRIBUTING.rst
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/debugging.rst b/doc/rtd/development/debugging.rst
index 68e68cb4..b0a0da35 100644
--- a/doc/rtd/topics/debugging.rst
+++ b/doc/rtd/development/debugging.rst
@@ -1,28 +1,38 @@
-********************
-Debugging cloud-init
-********************
+.. _debugging:
+
+Debugging ``cloud-init``
+************************
Overview
========
-This topic will discuss general approaches for test and debug of cloud-init on
-deployed instances.
+
+This topic will discuss general approaches for testing and debugging
+``cloud-init`` on deployed instances.
.. _boot_time_analysis:
-Boot Time Analysis - cloud-init analyze
-=======================================
-Occasionally instances don't appear as performant as we would like and
-cloud-init packages a simple facility to inspect what operations took
-cloud-init the longest during boot and setup.
+Boot time analysis
+==================
+
+:command:`cloud-init analyze`
+-----------------------------
+
+Occasionally, instances don't appear as performant as we would like and
+``cloud-init`` packages a simple facility to inspect which operations took the
+longest during boot and setup.
-The script **/usr/bin/cloud-init** has an analyze sub-command **analyze**
-which parses any cloud-init.log file into formatted and sorted events. It
-allows for detailed analysis of the most costly cloud-init operations are to
-determine the long-pole in cloud-init configuration and setup. These
-subcommands default to reading /var/log/cloud-init.log.
+The script :file:`/usr/bin/cloud-init` has an analysis sub-command,
+:command:`analyze`, which parses any :file:`cloud-init.log` file into formatted
+and sorted events. It allows for detailed analysis of the most costly
+``cloud-init`` operations, and to determine the long-pole in ``cloud-init``
+configuration and setup. These subcommands default to reading
+:file:`/var/log/cloud-init.log`.
-* ``analyze show`` Parse and organize cloud-init.log events by stage and
- include each sub-stage granularity with time delta reports.
+:command:`analyze show`
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Parse and organise :file:`cloud-init.log` events by stage and include each
+sub-stage granularity with time delta reports.
.. code-block:: shell-session
@@ -44,8 +54,11 @@ Example output:
...
-* ``analyze dump`` Parse cloud-init.log into event records and return a list of
- dictionaries that can be consumed for other reporting needs.
+:command:`analyze dump`
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Parse :file:`cloud-init.log` into event records and return a list of
+dictionaries that can be consumed for other reporting needs.
.. code-block:: shell-session
@@ -64,9 +77,12 @@ Example output:
"timestamp": 1510807493.0
},...
-* ``analyze blame`` Parse cloud-init.log into event records and sort them based
- on highest time cost for quick assessment of areas of cloud-init that may
- need improvement.
+:command:`analyze blame`
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Parse :file:`cloud-init.log` into event records and sort them based on the
+highest time cost for a quick assessment of areas of ``cloud-init`` that may
+need improvement.
.. code-block:: shell-session
@@ -82,8 +98,12 @@ Example output:
00.00100s (modules-final/config-rightscale_userdata)
...
-* ``analyze boot`` Make subprocess calls to the kernel in order to get relevant
- pre-cloud-init timestamps, such as the kernel start, kernel finish boot, and cloud-init start.
+:command:`analyze boot`
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Make subprocess calls to the kernel in order to get relevant pre-``cloud-init``
+timestamps, such as the kernel start, kernel finish boot, and ``cloud-init``
+start.
.. code-block:: shell-session
@@ -100,10 +120,11 @@ Example output:
Cloud-init start: 2019-06-13 16:00:05.738396
Time between Kernel boot and Cloud-init start (seconds): 4.793656
-
Analyze quickstart - LXC
----------------------------
-To quickly obtain a cloud-init log try using lxc on any ubuntu system:
+------------------------
+
+To quickly obtain a ``cloud-init`` log, try using :command:``lxc`` on any
+Ubuntu system:
.. code-block:: shell-session
@@ -116,8 +137,8 @@ To quickly obtain a cloud-init log try using lxc on any ubuntu system:
Analyze quickstart - KVM
----------------------------
-To quickly analyze a KVM a cloud-init log:
+------------------------
+To quickly analyze a KVM ``cloud-init`` log:
1. Download the current cloud image
@@ -125,14 +146,14 @@ To quickly analyze a KVM a cloud-init log:
$ wget https://cloud-images.ubuntu.com/daily/server/focal/current/focal-server-cloudimg-amd64.img
-2. Create a snapshot image to preserve the original cloud-image
+2. Create a snapshot image to preserve the original cloud image
.. code-block:: shell-session
$ qemu-img create -b focal-server-cloudimg-amd64.img -f qcow2 \
test-cloudinit.qcow2
-3. Create a seed image with metadata using `cloud-localds`
+3. Create a seed image with metadata using :command:`cloud-localds`
.. code-block:: shell-session
@@ -151,7 +172,7 @@ To quickly analyze a KVM a cloud-init log:
-drive file=test-cloudinit.qcow2,if=virtio,format=qcow2 \
-drive file=my-seed.img,if=virtio,format=raw
-5. Analyze the boot (blame, dump, show)
+5. Analyze the boot (:command:`blame`, :command:`dump`, :command:`show`)
.. code-block:: shell-session
@@ -159,19 +180,20 @@ To quickly analyze a KVM a cloud-init log:
cloud-init analyze blame -i -
-Running single cloud config modules
+Running single cloud-config modules
===================================
+
This subcommand is not called by the init system. It can be called manually to
-load the configured datasource and run a single cloud-config module once using
-the cached userdata and metadata after the instance has booted. Each
-cloud-config module has a module FREQUENCY configured: PER_INSTANCE, PER_BOOT,
-PER_ONCE or PER_ALWAYS. When a module is run by cloud-init, it stores a
-semaphore file in
-``/var/lib/cloud/instance/sem/config_<module_name>.<frequency>`` which marks
-when the module last successfully ran. Presence of this semaphore file
+load the configured datasource and run a single cloud-config module once, using
+the cached user data and metadata after the instance has booted. Each
+cloud-config module has a module ``FREQUENCY`` configured: ``PER_INSTANCE``,
+``PER_BOOT``, ``PER_ONCE`` or ``PER_ALWAYS``. When a module is run by
+``cloud-init``, it stores a semaphore file in
+:file:`/var/lib/cloud/instance/sem/config_<module_name>.<frequency>` which
+marks when the module last successfully ran. Presence of this semaphore file
prevents a module from running again if it has already been run. To ensure that
-a module is run again, the desired frequency can be overridden on the
-commandline:
+a module is run again, the desired frequency can be overridden via the
+command line:
.. code-block:: shell-session
@@ -185,40 +207,42 @@ Example output:
Generating public/private ed25519 key pair
...
-Inspect cloud-init.log for output of what operations were performed as a
-result.
+Inspect :file:`cloud-init.log` for output of what operations were performed as
+a result.
.. _proposed_sru_testing:
-Stable Release Updates (SRU) testing for cloud-init
-===================================================
-Once an Ubuntu release is stable (i.e. after it is released), updates for it
-must follow a special procedure called a "stable release update" (or `SRU`_).
+Stable Release Updates (SRU) testing for ``cloud-init``
+=======================================================
-The cloud-init project has a specific process it follows when validating
-a cloud-init SRU, documented in the `CloudinitUpdates`_ wiki page.
+Once an Ubuntu release is stable (i.e. after it is released), updates for it
+must follow a special procedure called a "Stable Release Update" (`SRU`_).
-Generally an SRU test of cloud-init performs the following:
+The ``cloud-init`` project has a specific process it follows when validating
+a ``cloud-init`` SRU, documented in the `CloudinitUpdates`_ wiki page.
- * Install a pre-release version of cloud-init from the
- **-proposed** APT pocket (e.g. **bionic-proposed**)
- * Upgrade cloud-init and attempt a clean run of cloud-init to assert the new
- version of cloud-init works properly the specific platform and Ubuntu series
- * Check for tracebacks or errors in behavior
+Generally an SRU test of ``cloud-init`` performs the following:
+ * Install a pre-release version of ``cloud-init`` from the **-proposed** APT
+ pocket (e.g., **bionic-proposed**).
+ * Upgrade ``cloud-init`` and attempt a clean run of ``cloud-init`` to assert
+ that the new version works properly on the specific platform and Ubuntu
+ series.
+ * Check for tracebacks or errors in behaviour.
Manual SRU verification procedure
---------------------------------
-Below are steps to manually test a pre-release version of cloud-init
+
+Below are steps to manually test a pre-release version of ``cloud-init``
from **-proposed**
.. note::
- For each Ubuntu SRU, the Ubuntu Server team manually validates the new version of cloud-init
- on these platforms: **Amazon EC2, Azure, GCE, OpenStack, Oracle,
- Softlayer (IBM), LXD, KVM**
+ For each Ubuntu SRU, the Ubuntu Server team manually validates the new
+ version of ``cloud-init`` on these platforms: **Amazon EC2, Azure, GCE,
+ OpenStack, Oracle, Softlayer (IBM), LXD, KVM**
1. Launch a VM on your favorite platform, providing this cloud-config
- user-data and replacing `<YOUR_LAUNCHPAD_USERNAME>` with your username:
+ user data and replacing `<YOUR_LAUNCHPAD_USERNAME>` with your username:
.. code-block:: yaml
@@ -227,11 +251,11 @@ from **-proposed**
ssh_import_id: [<YOUR_LAUNCHPAD_USERNAME>]
hostname: SRU-worked-{{v1.cloud_name}}
-2. Wait for current cloud-init to complete, replace `<YOUR_VM_IP>` with the IP
- address of the VM that you launched in step 1. Be sure to make a note of the
- datasource cloud-init detected in --long output. You will need this during
- step 5, where you will use it to confirm the same datasource is
- detected after the upgrade:
+2. Wait for current ``cloud-init`` to complete, replace ``<YOUR_VM_IP>`` with
+ the IP address of the VM that you launched in step 1. Be sure to make a
+ note of the datasource ``cloud-init`` detected in ``--long`` output. You
+ will need this during step 5, where you will use it to confirm the same
+ datasource is detected after the upgrade:
.. code-block:: bash
@@ -239,8 +263,8 @@ from **-proposed**
$ ssh ubuntu@$CI_VM_IP -- cloud-init status --wait --long
3. Set up the **-proposed** pocket on your VM and upgrade to the **-proposed**
- cloud-init. To do this, create the following bash script, which will
- add the -proposed pocket to APT's sources and install cloud-init
+ ``cloud-init``. To do this, create the following bash script, which will
+ add the **-proposed** pocket to APT's sources and install ``cloud-init``
from that pocket:
.. code-block:: bash
@@ -259,29 +283,30 @@ from **-proposed**
$ scp setup_proposed.sh ubuntu@$CI_VM_IP:.
$ ssh ubuntu@$CI_VM_IP -- sudo bash setup_proposed.sh
-4. Change hostname, clean cloud-init's state, and reboot to run cloud-init
- from scratch:
+4. Change hostname, clean ``cloud-init``'s state, and reboot to run
+ ``cloud-init`` from scratch:
.. code-block:: shell-session
$ ssh ubuntu@$CI_VM_IP -- sudo hostname something-else
$ ssh ubuntu@$CI_VM_IP -- sudo cloud-init clean --logs --reboot
-5. Validate **-proposed** cloud-init came up without error. First, we block
- until cloud-init completes and verify from --long that the datasource is
- the same as the one picked up from step 1. Errors will show up in --long:
+5. Validate **-proposed** ``cloud-init`` came up without error. First, we block
+ until ``cloud-init`` completes, then verify from ``--long`` that the
+ datasource is the same as the one picked up from step 1. Errors will show up
+ in ``--long``:
.. code-block:: shell-session
$ ssh ubuntu@$CI_VM_IP -- cloud-init status --wait --long
-Make sure the hostname was set properly to SRU-worked-<cloud name>:
+Make sure the hostname was set properly to `SRU-worked-<cloud name>`:
.. code-block:: shell-session
$ ssh ubuntu@$CI_VM_IP -- hostname
-Then, check for any errors or warnings in cloud-init logs. If successful,
+Then, check for any errors or warnings in ``cloud-init`` logs. If successful,
this will produce no output:
.. code-block:: shell-session
@@ -290,9 +315,9 @@ this will produce no output:
6. If you encounter an error during SRU testing:
- * Create a `new cloud-init bug`_ reporting the version of cloud-init
+ * Create a `new cloud-init bug`_ reporting the version of ``cloud-init``
affected
- * Ping upstream cloud-init on Libera's `#cloud-init IRC channel`_
+ * Ping upstream ``cloud-init`` on Libera's `#cloud-init IRC channel`_
.. _SRU: https://wiki.ubuntu.com/StableReleaseUpdates
.. _CloudinitUpdates: https://wiki.ubuntu.com/CloudinitUpdates
diff --git a/doc/rtd/topics/dir_layout.rst b/doc/rtd/development/dir_layout.rst
index d4606ac5..56627fb8 100644
--- a/doc/rtd/topics/dir_layout.rst
+++ b/doc/rtd/development/dir_layout.rst
@@ -1,9 +1,10 @@
-****************
+.. _dir_layout:
+
Directory layout
****************
-Cloud-init's directory structure is somewhat different from a regular
-application::
+``Cloud-init``'s directory structure is somewhat different from a regular
+application: ::
/var/lib/cloud/
- data/
@@ -34,15 +35,15 @@ application::
``/var/lib/cloud``
- The main directory containing the cloud-init specific subdirectories.
- It is typically located at ``/var/lib`` but there are certain configuration
- scenarios where this can be altered.
+ The main directory containing the ``cloud-init``-specific subdirectories.
+ It is typically located at :file:`/var/lib` but there are certain
+ configuration scenarios where this can be altered.
.. TODO: expand this section
``data/``
- Contains information related to instance ids, datasources and hostnames of
+ Contains information related to instance IDs, datasources and hostnames of
the previous and current instance if they are different. These can be
examined as needed to determine any information related to a previous boot
(if applicable).
@@ -50,21 +51,21 @@ application::
``handlers/``
Custom ``part-handlers`` code is written out here. Files that end up here are
- written out with in the scheme of ``part-handler-XYZ`` where ``XYZ`` is the
- handler number (the first handler found starts at 0).
+ written out within the scheme of ``part-handler-XYZ`` where ``XYZ`` is the
+ handler number (the first handler found starts at ``0``).
``instance``
A symlink to the current ``instances/`` subdirectory that points to the
- currently active instance (which is active is dependent on the datasource
+ currently active instance (the active instance is dependent on the datasource
loaded).
``instances/``
All instances that were created using this image end up with instance
identifier subdirectories (and corresponding data for each instance). The
- currently active instance will be symlinked the ``instance`` symlink file
+ currently active instance will be symlinked to the ``instance`` symlink file
defined previously.
``scripts/``
@@ -74,12 +75,13 @@ application::
``seed/``
- Contains seeded data files: meta-data, network-config, user-data, vendor-data
+ Contains seeded data files: :file:`meta-data`, :file:`network-config`,
+ :file:`user-data`, :file:`vendor-data`.
``sem/``
- Cloud-init has a concept of a module semaphore, which basically consists
+ ``Cloud-init`` has a concept of a module semaphore, which basically consists
of the module name and its frequency. These files are used to ensure a module
- is only ran `per-once`, `per-instance`, `per-always`. This folder contains
- semaphore `files` which are only supposed to run `per-once` (not tied to the
- instance id).
+ is only run "per-once", "per-instance", or "per-always". This folder contains
+ semaphore :file:`files` which are only supposed to run "per-once" (not tied
+ to the instance ID).
diff --git a/doc/rtd/development/docs.rst b/doc/rtd/development/docs.rst
new file mode 100644
index 00000000..30d66559
--- /dev/null
+++ b/doc/rtd/development/docs.rst
@@ -0,0 +1,136 @@
+.. _docs:
+
+Documentation
+*************
+
+These docs are hosted on `Read the Docs`_. The following will explain how to
+contribute to, and build, these docs locally.
+
+The documentation is primarily written in reStructuredText, with some pages
+written in standard Markdown.
+
+Building
+========
+
+There is a makefile target to build the documentation for you:
+
+.. code-block:: shell-session
+
+ $ tox -e doc
+
+This will do two things:
+
+- Build the documentation using sphinx.
+- Run doc8 against the documentation source code.
+
+Once built, the HTML files will be viewable in `doc/rtd_html`. Use your
+web browser to open `index.html` to view and navigate the site.
+
+Style guide
+===========
+
+Language
+--------
+
+Where possible, text should be written in UK English. However, discretion and
+common sense can both be applied. For example, where text refers to code
+elements that exist in US English, the spelling of these elements should not
+be changed to UK English.
+
+Headings
+--------
+
+In reStructuredText, headings are denoted using symbols to underline the text.
+The headings used across the documentation use the following hierarchy:
+
+- ``#####``: Top level header (reserved for the main index page)
+- ``*****``: Title header (used once at the top of a new page)
+- ``=====``: Section headers
+- ``-----``: Subsection headers
+- ``^^^^^``: Sub-subsection headers
+- ``"""""``: Paragraphs
+
+The length of the underline must be at least as long as the title itself.
+
+Ensure that you do not skip header levels when creating your document
+structure, i.e., that a section is followed by a subsection, and not a
+sub-subsection.
+
+Line length
+-----------
+
+Please keep the line lengths to a maximum of **79** characters. This ensures
+that the pages and tables do not get so wide that side scrolling is required.
+
+Anchor labels
+-------------
+
+Adding an anchor label at the top of the page allows for the page to be
+referenced by other pages. For example for the FAQ page this would be:
+
+.. code-block:: rst
+
+ .. _faq:
+
+ FAQ
+ ***
+
+When the reference is used in a document, the displayed text will be that of
+the next heading immediately following the label (so, FAQ in this example),
+unless specifically overridden.
+
+If you use labels within a page to refer, for example, to a subsection, use a
+label that follows the format: ``[pagelabel]-[Section]`` e.g., for this
+"Anchor labels" section, something like ``_docs-Anchor:`` or ``_docs-Label:``.
+Using a consistent style will aid greatly when referencing from other pages.
+
+Links
+-----
+
+To aid in documentation maintenance and keeping links up-to-date, links should
+be presented in a single block at the end of the page.
+
+Where possible, use contextual text in your links to aid users with screen
+readers and other accessibility tools. For example, "check out our
+:ref:`documentation style guide<docs>`" is preferable to "click
+:ref:`here<docs>` for more".
+
+Code blocks
+-----------
+
+Our documentation uses the Sphinx extension "sphinx-copybutton", which creates
+a small button on the right-hand side of code blocks for users to copy the
+code snippets we provide.
+
+The copied code will strip out the prompt symbol (``$``) so that users can
+paste commands directly into their terminal. For user convenience, please
+ensure that code output is presented in a separate code block to the commands.
+
+Vertical whitespace
+-------------------
+
+One newline between each section helps ensure readability of the documentation
+source code.
+
+Common words
+------------
+
+There are some common words that should follow specific usage:
+
+- ``cloud-init``: Always hyphenated. Follows sentence case, so only
+ capitalised at the start of a sentence (e.g., ``Cloud-init``).
+- ``metadata``, ``datasource``: One word.
+- ``user data``, ``vendor data``: Two words, not to be combined or hyphenated.
+
+Acronyms
+--------
+
+Acronyms are always capitalised (e.g., JSON, YAML, QEMU, LXD) in text.
+
+The first time an acronym is used on a page, it is best practice to introduce
+it by showing the expanded name followed by the acronym in parentheses. E.g.,
+Quick EMUlator (QEMU). If the acronym is very common, or you provide a link to
+a documentation page that provides such details, you will not need to do this.
+
+
+.. _Read the Docs: https://readthedocs.com/
diff --git a/doc/rtd/development/index.rst b/doc/rtd/development/index.rst
new file mode 100644
index 00000000..8c077d8e
--- /dev/null
+++ b/doc/rtd/development/index.rst
@@ -0,0 +1,49 @@
+Development
+***********
+
+``Cloud-init`` is an open source project that warmly welcomes community
+projects, contributions, suggestions, fixes and constructive feedback. If you
+would like to contribute to ``cloud-init``, this set of documentation will help
+orient you with our processes.
+
+-----
+
+Contributing
+============
+
+.. toctree::
+ :maxdepth: 1
+
+ contributing.rst
+ module_creation.rst
+ code_review.rst
+ dir_layout.rst
+
+Debugging and reporting
+=======================
+
+.. toctree::
+ :maxdepth: 1
+
+ ../howto/bugs.rst
+ security.rst
+ analyze.rst
+ logging.rst
+ debugging.rst
+
+Testing
+=======
+
+.. toctree::
+ :maxdepth: 1
+
+ testing.rst
+ integration_tests.rst
+
+Documentation
+=============
+
+.. toctree::
+ :maxdepth: 1
+
+ docs.rst
diff --git a/doc/rtd/development/integration_tests.rst b/doc/rtd/development/integration_tests.rst
new file mode 100644
index 00000000..797cc5d0
--- /dev/null
+++ b/doc/rtd/development/integration_tests.rst
@@ -0,0 +1,214 @@
+.. _integration_tests:
+
+Integration testing
+*******************
+
+Overview
+=========
+
+Integration tests are written using ``pytest`` and are located at
+:file:`tests/integration_tests`. General design principles laid out in
+:ref:`testing` should be followed for integration tests.
+
+Setup is accomplished via a set of fixtures located in
+:file:`tests/integration_tests/conftest.py`.
+
+Test definition
+===============
+
+Tests are defined like any other ``pytest`` test. The ``user_data``
+mark can be used to supply the cloud-config user data. Platform-specific
+marks can be used to limit tests to particular platforms. The ``client``
+fixture can be used to interact with the launched test instance.
+
+See `Examples`_ section for examples.
+
+Test execution
+==============
+
+Test execution happens via ``pytest``. A ``tox`` definition exists to run
+integration tests. To run all integration tests, you would run:
+
+.. code-block:: bash
+
+ $ tox -e integration-tests
+
+``pytest`` arguments may also be passed. For example:
+
+.. code-block:: bash
+
+ $ tox -e integration-tests tests/integration_tests/modules/test_combined.py
+
+Configuration
+=============
+
+All possible configuration values are defined in
+`tests/integration_tests/integration_settings.py`_. Defaults can be overridden
+by supplying values in :file:`tests/integration_tests/user_settings.py` or by
+providing an environment variable of the same name prepended with
+``CLOUD_INIT_``. For example, to set the ``PLATFORM`` setting:
+
+.. code-block:: bash
+
+ CLOUD_INIT_PLATFORM='ec2' pytest tests/integration_tests/
+
+Cloud interaction
+=================
+
+Cloud interaction happens via the `pycloudlib library`_. In order to run
+integration tests, pycloudlib must `first be configured`_.
+
+For a minimal setup using LXD, write the following to
+:file:`~/.config/pycloudlib.toml`:
+
+.. code-block:: toml
+
+ [lxd]
+
+Image selection
+===============
+
+Each integration testing run uses a single image as its basis. This
+image is configured using the ``OS_IMAGE`` variable; see
+`Configuration`_ for details of how configuration works.
+
+``OS_IMAGE`` can take two types of value: an Ubuntu series name (e.g.
+"focal"), or an image specification. If an Ubuntu series name is
+given, then the most recent image for that series on the target cloud
+will be used. For other use cases, an image specification is used.
+
+In its simplest form, an image specification can simply be a cloud's
+image ID (e.g., "ami-deadbeef", "ubuntu:focal"). In this case, the
+identified image will be used as the basis for this testing run.
+
+This has a drawback, however. As we do not know what OS or release is
+within the image, the integration testing framework will run *all*
+tests against the image in question. If it's a RHEL8 image, then we
+would expect Ubuntu-specific tests to fail (and vice versa).
+
+To address this, a full image specification can be given. This is of
+the form: ``<image_id>[::<os>[::<release>]]`` where ``image_id`` is a
+cloud's image ID, ``os`` is the OS name, and ``release`` is the OS
+release name. So, for example, Ubuntu 18.04 (Bionic Beaver) on LXD is
+``ubuntu:bionic::ubuntu::bionic`` or RHEL8 on Amazon is
+``ami-justanexample::rhel::8``. When a full specification is given,
+only tests which are intended for use on that OS and release will be
+executed.
+
+Image setup
+===========
+
+Image setup occurs once when a test session begins and is implemented
+via fixture. Image setup roughly follows these steps:
+
+* Launch an instance on the specified test platform.
+* Install the version of ``cloud-init`` under test.
+* Run :command:`cloud-init clean` on the instance so subsequent boots
+ resemble "out of the box" behaviour.
+* Take a snapshot of the instance to be used as a new image from
+ which new instances can be launched.
+
+Test setup
+==========
+
+Test setup occurs between image setup and test execution. Test setup
+is implemented via one of the ``client`` fixtures. When a ``client`` fixture
+is used, a test instance from which to run tests is launched prior to
+test execution, and then torn down after.
+
+Continuous integration
+======================
+
+A subset of the integration tests are run when a pull request
+is submitted on GitHub. The tests run on these continuous
+integration (CI) runs are given a ``pytest`` mark:
+
+.. code-block:: python
+
+ @pytest.mark.ci
+
+Most new tests should *not* use this mark, so be aware that having a
+successful CI run does not necessarily mean that your test passed
+successfully.
+
+Fixtures
+========
+
+Integration tests rely heavily on fixtures to do initial test setup.
+One or more of these fixtures will be used in almost every integration test.
+
+Details such as the cloud platform or initial image to use are determined
+via what is specified in the `Configuration`_.
+
+``client``
+----------
+
+The ``client`` fixture should be used for most test cases. It ensures:
+
+- All setup performed by `session_cloud`_ and `setup_image`_.
+- `Pytest marks`_ used during instance creation are obtained and applied.
+- The test instance is launched.
+- Test failure status is determined after test execution.
+- Logs are collected (if configured) after test execution.
+- The test instance is torn down after test execution.
+
+``module_client`` and ``class_client`` fixtures also exist for the
+purpose of running multiple tests against a single launched instance.
+They provide the exact same functionality as ``client``, but are
+scoped to the module or class respectively.
+
+``session_cloud``
+-----------------
+
+The ``session_cloud`` session-scoped fixture will provide an
+`IntegrationCloud`_ instance for the currently configured cloud. The fixture
+also ensures that any custom cloud session cleanup is performed.
+
+``setup_image``
+---------------
+
+The ``setup_image`` session-scope fixture will create a new image to launch
+all further cloud instances during this test run. It ensures:
+
+- A cloud instance is launched on the configured platform.
+- The version of ``cloud-init`` under test is installed on the instance.
+- :command:`cloud-init clean --logs` is run on the instance.
+- A snapshot of the instance is taken to be used as the basis for
+ future instance launches.
+- The originally launched instance is torn down.
+- The custom created image is torn down after all tests finish.
+
+Examples
+--------
+A simple test case using the ``client`` fixture:
+
+.. code-block:: python
+
+ USER_DATA = """\
+ #cloud-config
+ bootcmd:
+ - echo 'hello!' > /var/tmp/hello.txt
+ """
+
+
+ @pytest.mark.user_data(USER_DATA)
+ def test_bootcmd(client):
+ log = client.read_from_file("/var/log/cloud-init.log")
+ assert "Shellified 1 commands." in log
+ assert client.execute('cat /var/tmp/hello.txt').strip() == "hello!"
+
+Customizing the launch arguments before launching an instance manually:
+
+.. code-block:: python
+
+ def test_launch(session_cloud: IntegrationCloud, setup_image):
+ with session_cloud.launch(launch_kwargs={"wait": False}) as client:
+ client.instance.wait()
+ assert client.execute("echo hello world").strip() == "hello world"
+
+.. LINKS:
+.. _tests/integration_tests/integration_settings.py: https://github.com/canonical/cloud-init/blob/main/tests/integration_tests/integration_settings.py
+.. _pycloudlib library: https://pycloudlib.readthedocs.io/en/latest/index.html
+.. _first be configured: https://pycloudlib.readthedocs.io/en/latest/configuration.html#configuration
+.. _Pytest marks: https://github.com/canonical/cloud-init/blob/af7eb1deab12c7208853c5d18b55228e0ba29c4d/tests/integration_tests/conftest.py#L220-L224
+.. _IntegrationCloud: https://github.com/canonical/cloud-init/blob/af7eb1deab12c7208853c5d18b55228e0ba29c4d/tests/integration_tests/clouds.py#L102
diff --git a/doc/rtd/development/logging.rst b/doc/rtd/development/logging.rst
new file mode 100644
index 00000000..e99eef8b
--- /dev/null
+++ b/doc/rtd/development/logging.rst
@@ -0,0 +1,278 @@
+.. _logging:
+
+Logging
+*******
+
+``Cloud-init`` supports both local and remote logging configurable through
+multiple configurations:
+
+- Python's built-in logging configuration
+- ``Cloud-init``'s event reporting system
+- The ``cloud-init`` ``rsyslog`` module
+
+Python logging
+==============
+
+``Cloud-init`` uses the Python logging module, and can accept config for this
+module using the standard Python ``fileConfig`` format. ``Cloud-init`` looks
+for config for the logging module under the ``logcfg`` key.
+
+.. note::
+ The logging configuration is not YAML, it is Python ``fileConfig`` format,
+ and is passed through directly to the Python logging module. Please use
+ the correct syntax for a multi-line string in YAML.
+
+By default, ``cloud-init`` uses the logging configuration provided in
+:file:`/etc/cloud/cloud.cfg.d/05_logging.cfg`. The default Python logging
+configuration writes all ``cloud-init`` events with a priority of ``WARNING``
+or higher to console, and writes all events with a level of ``DEBUG`` or
+higher to :file:`/var/log/cloud-init.log` and via :file:`syslog`.
+
+Python's ``fileConfig`` format consists of sections with headings in the
+format ``[title]`` and key value pairs in each section. Configuration for
+Python logging must contain the sections ``[loggers]``, ``[handlers]``, and
+``[formatters]``, which name the entities of their respective types that will
+be defined. The section name for each defined logger, handler and formatter
+will start with its type, followed by an underscore (``_``) and the name of
+the entity. For example, if a logger was specified with the name ``log01``,
+config for the logger would be in the section ``[logger_log01]``.
+
+Logger config entries contain basic logging setup. They may specify a list of
+handlers to send logging events to as well as the lowest priority level of
+events to handle. A logger named ``root`` must be specified and its
+configuration (under ``[logger_root]``) must contain a level and a list of
+handlers. A level entry can be any of the following: ``DEBUG``, ``INFO``,
+``WARNING``, ``ERROR``, ``CRITICAL``, or ``NOTSET``. For the ``root`` logger
+the ``NOTSET`` option will allow all logging events to be recorded.
+
+Each configured handler must specify a class under Python's ``logging``
+package namespace. A handler may specify a message formatter to use, a
+priority level, and arguments for the handler class. Common handlers are
+``StreamHandler``, which handles stream redirects (i.e., logging to
+``stderr``), and ``FileHandler`` which outputs to a log file. The logging
+module also supports logging over net sockets, over http, via smtp, and
+additional complex configurations. For full details about the handlers
+available for Python logging, please see the documentation for
+`python logging handlers`_.
+
+Log messages are formatted using the ``logging.Formatter`` class, which is
+configured using ``formatter`` config entities. A default format of
+``%(message)s`` is given if no formatter configs are specified. Formatter
+config entities accept a format string which supports variable replacements.
+These may also accept a ``datefmt`` string which may be used to configure the
+timestamp used in the log messages. The format variables ``%(asctime)s``,
+``%(levelname)s`` and ``%(message)s`` are commonly used and represent the
+timestamp, the priority level of the event and the event message. For
+additional information on logging formatters see `python logging formatters`_.
+
+.. note::
+ By default, the format string used in the logging formatter are in Python's
+ old style ``%s`` form. The ``str.format()`` and ``string.Template`` styles
+ can also be used by using ``{`` or ``$`` in place of ``%`` by setting the
+ ``style`` parameter in formatter config.
+
+A simple (but functional) Python logging configuration for ``cloud-init`` is
+below. It will log all messages of priority ``DEBUG`` or higher to both
+:file:`stderr` and :file:`/tmp/my.log` using a ``StreamHandler`` and a
+``FileHandler``, using the default format string ``%(message)s``: ::
+
+ logcfg: |
+ [loggers]
+ keys=root,cloudinit
+ [handlers]
+ keys=ch,cf
+ [formatters]
+ keys=
+ [logger_root]
+ level=DEBUG
+ handlers=
+ [logger_cloudinit]
+ level=DEBUG
+ qualname=cloudinit
+ handlers=ch,cf
+ [handler_ch]
+ class=StreamHandler
+ level=DEBUG
+ args=(sys.stderr,)
+ [handler_cf]
+ class=FileHandler
+ level=DEBUG
+ args=('/tmp/my.log',)
+
+For additional information about configuring Python's logging module, please
+see the documentation for `python logging config`_.
+
+.. _logging_command_output:
+
+Command output
+==============
+
+``Cloud-init`` can redirect its :file:`stdout` and :file:`stderr` based on
+config given under the ``output`` config key. The output of any commands run
+by ``cloud-init`` and any user or vendor scripts provided will also be
+included here. The ``output`` key accepts a dictionary for configuration.
+Output files may be specified individually for each stage (``init``,
+``config``, and ``final``), or a single key ``all`` may be used to specify
+output for all stages.
+
+The output for each stage may be specified as a dictionary of ``output`` and
+``error`` keys, for :file:`stdout` and :file:`stderr` respectively, as a tuple
+with :file:`stdout` first and :file:`stderr` second, or as a single string to
+use for both. The strings passed to all of these keys are handled by the
+system shell, so any form of redirection that can be used in bash is valid,
+including piping ``cloud-init``'s output to ``tee``, or ``logger``. If only a
+filename is provided, ``cloud-init`` will append its output to the file as
+though ``>>`` was specified.
+
+By default, ``cloud-init`` loads its output configuration from
+:file:`/etc/cloud/cloud.cfg.d/05_logging.cfg`. The default config directs both
+:file:`stdout` and :file:`stderr` from all ``cloud-init`` stages to
+:file:`/var/log/cloud-init-output.log`. The default config is given as: ::
+
+ output: { all: "| tee -a /var/log/cloud-init-output.log" }
+
+For a more complex example, the following configuration would output the init
+stage to :file:`/var/log/cloud-init.out` and :file:`/var/log/cloud-init.err`,
+for :file:`stdout` and :file:`stderr` respectively, replacing anything that
+was previously there. For the config stage, it would pipe both :file:`stdout`
+and :file:`stderr` through :command:`tee -a /var/log/cloud-config.log`. For
+the final stage it would append the output of :file:`stdout` and
+:file:`stderr` to :file:`/var/log/cloud-final.out` and
+:file:`/var/log/cloud-final.err` respectively. ::
+
+ output:
+ init:
+ output: "> /var/log/cloud-init.out"
+ error: "> /var/log/cloud-init.err"
+ config: "tee -a /var/log/cloud-config.log"
+ final:
+ - ">> /var/log/cloud-final.out"
+ - "/var/log/cloud-final.err"
+
+Event reporting
+===============
+
+``Cloud-init`` contains an eventing system that allows events to be emitted
+to a variety of destinations.
+
+Three configurations are available for reporting events:
+
+- ``webhook``: POST to a web server.
+- ``log``: Write to the ``cloud-init`` log at configurable log level.
+- ``stdout``: Print to :file:`stdout`.
+
+The default configuration is to emit events to the ``cloud-init`` log file
+at ``DEBUG`` level.
+
+Event reporting can be configured using the ``reporting`` key in
+``cloud-config`` user data.
+
+Configuration
+-------------
+
+``webhook``
+^^^^^^^^^^^
+
+.. code-block:: yaml
+
+ reporting:
+ <user-defined name>:
+ type: webhook
+ endpoint: <url>
+ timeout: <timeout in seconds>
+ retries: <number of retries>
+ consumer_key: <OAuth consumer key>
+ token_key: <OAuth token key>
+ token_secret: <OAuth token secret>
+ consumer_secret: <OAuth consumer secret>
+
+``endpoint`` is the only additional required key when specifying
+``type: webhook``.
+
+``log``
+^^^^^^^
+
+.. code-block:: yaml
+
+ reporting:
+ <user-defined name>:
+ type: log
+ level: <DEBUG|INFO|WARN|ERROR|FATAL>
+
+``level`` is optional and defaults to "DEBUG".
+
+``print``
+^^^^^^^^^
+
+.. code-block:: yaml
+
+ reporting:
+ <user-defined name>:
+ type: print
+
+
+Example
+^^^^^^^
+
+The follow example shows configuration for all three sources:
+
+.. code-block:: yaml
+
+ #cloud-config
+ reporting:
+ webserver:
+ type: webhook
+ endpoint: "http://10.0.0.1:55555/asdf"
+ timeout: 5
+ retries: 3
+ consumer_key: <consumer_key>
+ token_key: <token_key>
+ token_secret: <token_secret>
+ consumer_secret: <consumer_secret>
+ info_log:
+ type: log
+ level: WARN
+ stdout:
+ type: print
+
+``rsyslog`` module
+==================
+
+``Cloud-init``'s ``cc_rsyslog`` module allows for fully customizable
+``rsyslog`` configuration under the ``rsyslog`` config key. The simplest way
+to use the ``rsyslog`` module is by specifying remote servers under the
+``remotes`` key in ``rsyslog`` config. The ``remotes`` key takes a dictionary
+where each key represents the name of an ``rsyslog`` server and each value is
+the configuration for that server. The format for server config is:
+
+ - optional filter for log messages (defaults to ``*.*``)
+ - optional leading ``@`` or ``@@``, indicating UDP and TCP respectively
+ (defaults to ``@``, for UDP)
+ - IPv4 or IPv6 hostname or address. IPv6 addresses must be in ``[::1]``
+ format (e.g., ``@[fd00::1]:514``)
+ - optional port number (defaults to ``514``)
+
+For example, to send logging to an ``rsyslog`` server named ``log_serv`` with
+address ``10.0.4.1``, using port number ``514``, over UDP, with all log
+messages enabled one could use either of the following.
+
+With all options specified::
+
+ rsyslog:
+ remotes:
+ log_serv: "*.* @10.0.4.1:514"
+
+With defaults used::
+
+ rsyslog:
+ remotes:
+ log_serv: "10.0.4.1"
+
+
+For more information on ``rsyslog`` configuration, see
+:ref:`our module reference page<mod-rsyslog>`.
+
+.. LINKS:
+.. _python logging config: https://docs.python.org/3/library/logging.config.html#configuration-file-format
+.. _python logging handlers: https://docs.python.org/3/library/logging.handlers.html
+.. _python logging formatters: https://docs.python.org/3/library/logging.html#formatter-objects
diff --git a/doc/rtd/topics/module_creation.rst b/doc/rtd/development/module_creation.rst
index 56cadec4..cb46d7cf 100644
--- a/doc/rtd/topics/module_creation.rst
+++ b/doc/rtd/development/module_creation.rst
@@ -1,14 +1,15 @@
.. _module_creation:
-Module Creation
+Module creation
***************
-Much of cloud-init functionality is provided by :ref:`modules<modules>`.
+Much of ``cloud-init``'s functionality is provided by :ref:`modules<modules>`.
All modules follow a similar layout in order to provide consistent execution
and documentation. Use the example provided here to create a new module.
Example
=======
+
.. code-block:: python
# This file is part of cloud-init. See LICENSE file for license information.
@@ -50,32 +51,33 @@ Example
) -> None:
log.debug(f"Hi from module {name}")
+.. _module_creation-Guidelines:
Guidelines
==========
-* Create a new module in the ``cloudinit/config`` directory with a `cc_`
+* Create a new module in the :file:`cloudinit/config` directory with a ``cc_``
prefix.
* Your module must include a ``handle`` function. The arguments are:
- * ``name``: The module name specified in the configuration
+ * ``name``: The module name specified in the configuration.
* ``cfg``: A configuration object that is the result of the merging of
- cloud-config configuration with any datasource provided configuration.
+ cloud-config configuration with any datasource-provided configuration.
* ``cloud``: A cloud object that can be used to access various datasource
and paths for the given distro and data provided by the various datasource
instance types.
* ``log``: A logger object that can be used to log messages.
* ``args``: An argument list. This is usually empty and is only populated
if the module is called independently from the command line or if the
- module definition in ``/etc/cloud/cloud.cfg[.d]`` has been modified
+ module definition in :file:`/etc/cloud/cloud.cfg[.d]` has been modified
to pass arguments to this module.
* If your module introduces any new cloud-config keys, you must provide a
schema definition in `cloud-init-schema.json`_.
* The ``meta`` variable must exist and be of type `MetaSchema`_.
- * ``id``: The module id. In most cases this will be the filename without
- the `.py` extension.
+ * ``id``: The module ID. In most cases this will be the filename without
+ the ``.py`` extension.
* ``distros``: Defines the list of supported distros. It can contain
any of the values (not keys) defined in the `OSFAMILIES`_ map or
``[ALL_DISTROS]`` if there is no distro restriction.
@@ -84,11 +86,11 @@ Guidelines
* ``PER_ALWAYS``: Runs on every boot.
* ``ONCE``: Runs only on first boot.
* ``PER_INSTANCE``: Runs once per instance. When exactly this happens
- is dependent on the datasource but may triggered anytime there
+ is dependent on the datasource, but may triggered any time there
would be a significant change to the instance metadata. An example
could be an instance being moved to a different subnet.
- * ``activate_by_schema_keys``: (Optional) List of cloud-config keys that will
+ * ``activate_by_schema_keys``: Optional list of cloud-config keys that will
activate this module. When this list not empty, the config module will be
skipped unless one of the ``activate_by_schema_keys`` are present in merged
cloud-config instance-data.
@@ -100,15 +102,15 @@ Guidelines
* ``__doc__ = get_meta_doc(meta)`` is necessary to provide proper module
documentation.
-Module Execution
+Module execution
================
In order for a module to be run, it must be defined in a module run section in
-``/etc/cloud/cloud.cfg`` or ``/etc/cloud/cloud.cfg.d`` on the launched
+:file:`/etc/cloud/cloud.cfg` or :file:`/etc/cloud/cloud.cfg.d` on the launched
instance. The three module sections are
`cloud_init_modules`_, `cloud_config_modules`_, and `cloud_final_modules`_,
-corresponding to the :ref:`topics/boot:Network`, :ref:`topics/boot:Config`,
-and :ref:`topics/boot:Final` boot stages respectively.
+corresponding to the :ref:`Network<boot-Network>`, :ref:`Config<boot-Config>`,
+and :ref:`Final<boot-Final>` boot stages respectively.
Add your module to `cloud.cfg.tmpl`_ under the appropriate module section.
Each module gets run in the order listed, so ensure your module is defined
diff --git a/doc/rtd/topics/security.rst b/doc/rtd/development/security.rst
index ad934ded..c1ffd9ce 100644
--- a/doc/rtd/topics/security.rst
+++ b/doc/rtd/development/security.rst
@@ -1,6 +1,6 @@
-********
+.. _security:
+
Security
********
-.. _security:
.. mdinclude:: ../../../SECURITY.md
diff --git a/doc/rtd/topics/testing.rst b/doc/rtd/development/testing.rst
index 4bcbba5b..b1b52467 100644
--- a/doc/rtd/topics/testing.rst
+++ b/doc/rtd/development/testing.rst
@@ -1,102 +1,103 @@
.. _testing:
-*******
Testing
*******
-cloud-init has both unit tests and integration tests. Unit tests can
-be found at ``tests/unittests``. Integration tests can be found at
-``tests/integration_tests``. Documentation specifically for integration
+.. toctree::
+ :maxdepth: 1
+ :hidden:
+
+ integration_tests.rst
+
+``Cloud-init`` has both unit tests and integration tests. Unit tests can
+be found at :file:`tests/unittests`. Integration tests can be found at
+:file:`tests/integration_tests`. Documentation specifically for integration
tests can be found on the :ref:`integration_tests` page, but
the guidelines specified below apply to both types of tests.
-cloud-init uses `pytest`_ to run its tests, and has tests written both
-as ``unittest.TestCase`` sub-classes and as un-subclassed pytest tests.
+``Cloud-init`` uses `pytest`_ to run its tests, and has tests written both
+as ``unittest.TestCase`` sub-classes and as un-subclassed ``pytest`` tests.
Guidelines
==========
The following guidelines should be followed.
-Test Layout
+Test layout
-----------
-* For ease of organisation and greater accessibility for developers not
- familiar with pytest, all cloud-init unit tests must be contained
- within test classes
-
- * Put another way, module-level test functions should not be used
+* For ease of organisation and greater accessibility for developers unfamiliar
+ with ``pytest``, all ``cloud-init`` unit tests must be contained within test
+ classes. In other words, module-level test functions should not be used.
-* As all tests are contained within classes, it is acceptable to mix
- ``TestCase`` test classes and pytest test classes within the same
- test file
+* Since all tests are contained within classes, it is acceptable to mix
+ ``TestCase`` test classes and ``pytest`` test classes within the same
+ test file.
- * These can be easily distinguished by their definition: pytest
- classes will not use inheritance at all (e.g.
+ * These can be easily distinguished by their definition: ``pytest``
+ classes will not use inheritance at all (e.g.,
`TestGetPackageMirrorInfo`_), whereas ``TestCase`` classes will
- subclass (indirectly) from ``TestCase`` (e.g.
- `TestPrependBaseCommands`_)
+ subclass (indirectly) from ``TestCase`` (e.g.,
+ `TestPrependBaseCommands`_).
-* Unit tests and integration tests are located under cloud-init/tests
+* Unit tests and integration tests are located under :file:`cloud-init/tests`.
* For consistency, unit test files should have a matching name and
- directory location under `tests/unittests`
+ directory location under :file:`tests/unittests`.
- * For example: the expected test file for code in
- `cloudinit/path/to/file.py` is
- `tests/unittests/path/to/test_file.py`
+ * E.g., the expected test file for code in :file:`cloudinit/path/to/file.py`
+ is :file:`tests/unittests/path/to/test_file.py`.
-
-``pytest`` Tests
+``pytest`` tests
----------------
-* pytest test classes should use `pytest fixtures`_ to share
- functionality instead of inheritance
+* ``pytest`` test classes should use `pytest fixtures`_ to share
+ functionality instead of inheritance.
-* pytest tests should use bare ``assert`` statements, to take advantage
- of pytest's `assertion introspection`_
+* ``pytest`` tests should use bare ``assert`` statements, to take advantage
+ of ``pytest``'s `assertion introspection`_.
-``pytest`` Version Gotchas
---------------------------
+``pytest`` version "gotchas"
+----------------------------
-As we still support Ubuntu 18.04 (Bionic Beaver), we can only use pytest
-features that are available in v3.3.2. This is an inexhaustive list of
+As we still support Ubuntu 18.04 (Bionic Beaver), we can only use ``pytest``
+features that are available in v3.3.2. This is an inexhaustive list of
ways in which this may catch you out:
-* Only the following built-in fixtures are available [#fixture-list]_:
-
- * ``cache``
- * ``capfd``
- * ``capfdbinary``
- * ``caplog``
- * ``capsys``
- * ``capsysbinary``
- * ``doctest_namespace``
- * ``monkeypatch``
- * ``pytestconfig``
- * ``record_xml_property``
- * ``recwarn``
- * ``tmpdir_factory``
- * ``tmpdir``
-
-Mocking and Assertions
+ * Only the following built-in fixtures are available [#fixture-list]_:
+
+ * ``cache``
+ * ``capfd``
+ * ``capfdbinary``
+ * ``caplog``
+ * ``capsys``
+ * ``capsysbinary``
+ * ``doctest_namespace``
+ * ``monkeypatch``
+ * ``pytestconfig``
+ * ``record_xml_property``
+ * ``recwarn``
+ * ``tmpdir_factory``
+ * ``tmpdir``
+
+Mocking and assertions
----------------------
* Variables/parameter names for ``Mock`` or ``MagicMock`` instances
should start with ``m_`` to clearly distinguish them from non-mock
- variables
-
- * For example, ``m_readurl`` (which would be a mock for ``readurl``)
+ variables. For example, ``m_readurl`` (which would be a mock for
+ ``readurl``).
* The ``assert_*`` methods that are available on ``Mock`` and
``MagicMock`` objects should be avoided, as typos in these method
names may not raise ``AttributeError`` (and so can cause tests to
- silently pass). An important exception: if a ``Mock`` is
- `autospecced`_ then misspelled assertion methods *will* raise an
- ``AttributeError``, so these assertion methods may be used on
- autospecced ``Mock`` objects.
+ silently pass).
+
+ * **An important exception:** if a ``Mock`` is `autospecced`_ then
+ misspelled assertion methods *will* raise an ``AttributeError``, so these
+ assertion methods may be used on autospecced ``Mock`` objects.
- For non-autospecced ``Mock`` s, these substitutions can be used
+* For a non-autospecced ``Mock``, these substitutions can be used
(``m`` is assumed to be a ``Mock``):
* ``m.assert_any_call(*args, **kwargs)`` => ``assert
@@ -118,11 +119,10 @@ Mocking and Assertions
* When there are multiple patch calls in a test file for the module it
is testing, it may be desirable to capture the shared string prefix
- for these patch calls in a module-level variable. If used, such
- variables should be named ``M_PATH`` or, for datasource tests,
- ``DS_PATH``.
+ for these patch calls in a module-level variable. If used, such
+ variables should be named ``M_PATH`` or, for datasource tests, ``DS_PATH``.
-Test Argument Ordering
+Test argument ordering
----------------------
* Test arguments should be ordered as follows:
@@ -131,10 +131,10 @@ Test Argument Ordering
partially applies its generated ``Mock`` object as the first
argument, so these arguments must go first.
* ``pytest.mark.parametrize`` arguments, in the order specified to
- the ``parametrize`` decorator. These arguments are also provided
+ the ``parametrize`` decorator. These arguments are also provided
by a decorator, so it's natural that they sit next to the
``mock.patch`` arguments.
- * Fixture arguments, alphabetically. These are not provided by a
+ * Fixture arguments, alphabetically. These are not provided by a
decorator, so they are last, and their order has no defined
meaning, so we default to alphabetical.
@@ -152,6 +152,7 @@ Test Argument Ordering
in an ubuntu lxd container with python3-pytest installed.
+.. LINKS:
.. _pytest: https://docs.pytest.org/
.. _pytest fixtures: https://docs.pytest.org/en/latest/fixture.html
.. _TestGetPackageMirrorInfo: https://github.com/canonical/cloud-init/blob/42f69f410ab8850c02b1f53dd67c132aa8ef64f5/cloudinit/distros/tests/test_init.py\#L15
diff --git a/doc/rtd/explanation/boot.rst b/doc/rtd/explanation/boot.rst
new file mode 100644
index 00000000..42ccbc87
--- /dev/null
+++ b/doc/rtd/explanation/boot.rst
@@ -0,0 +1,263 @@
+.. _boot_stages:
+
+Boot stages
+***********
+
+To be able to provide the functionality that it does, ``cloud-init`` must be
+integrated into the boot in a fairly controlled way. There are five
+stages to boot:
+
+1. Generator
+2. Local
+3. Network
+4. Config
+5. Final
+
+.. _boot-Generator:
+
+Generator
+=========
+
+When booting under ``systemd``, a `generator`_ will run that determines if
+``cloud-init.target`` should be included in the boot goals. By default, this
+generator will enable ``cloud-init``. It will not enable ``cloud-init``
+if either:
+
+- The file :file:`/etc/cloud/cloud-init.disabled` exists, or
+- The kernel command line as found in :file:`/proc/cmdline` contains
+ ``cloud-init=disabled``. When running in a container, the kernel command
+ line is not honored, but ``cloud-init`` will read an environment
+ variable named ``KERNEL_CMDLINE`` in its place.
+
+.. note::
+ These mechanisms for disabling ``cloud-init`` at runtime currently only
+ exist in ``systemd``.
+
+.. _boot-Local:
+
+Local
+=====
+
++------------------+----------------------------------------------------------+
+| systemd service | ``cloud-init-local.service`` |
++---------+--------+----------------------------------------------------------+
+| runs | as soon as possible with ``/`` mounted read-write |
++---------+--------+----------------------------------------------------------+
+| blocks | as much of boot as possible, *must* block network |
++---------+--------+----------------------------------------------------------+
+| modules | none |
++---------+--------+----------------------------------------------------------+
+
+The purpose of the local stage is to:
+
+ - Locate "local" data sources, and
+ - Apply networking configuration to the system (including "fallback").
+
+In most cases, this stage does not do much more than that. It finds the
+datasource and determines the network configuration to be used. That
+network configuration can come from:
+
+- **datasource**: Cloud-provided network configuration via metadata.
+- **fallback**: ``Cloud-init``'s fallback networking consists of rendering
+ the equivalent to ``dhcp on eth0``, which was historically the most popular
+ mechanism for network configuration of a guest.
+- **none**: Network configuration can be disabled by writing the file
+ :file:`/etc/cloud/cloud.cfg` with the content:
+ ``network: {config: disabled}``.
+
+If this is an instance's first boot, then the selected network configuration
+is rendered. This includes clearing of all previous (stale) configuration
+including persistent device naming with old MAC addresses.
+
+This stage must block network bring-up or any stale configuration that might
+have already been applied. Otherwise, that could have negative effects such
+as DHCP hooks or broadcast of an old hostname. It would also put the system
+in an odd state to recover from, as it may then have to restart network
+devices.
+
+``Cloud-init`` then exits and expects for the continued boot of the operating
+system to bring network configuration up as configured.
+
+.. note::
+ In the past, local datasources have been only those that were available
+ without network (such as 'ConfigDrive'). However, as seen in the recent
+ additions to the :ref:`DigitalOcean datasource<datasource_digital_ocean>`,
+ even data sources that require a network can operate at this stage.
+
+.. _boot-Network:
+
+Network
+=======
+
++------------------+----------------------------------------------------------+
+| systemd service | ``cloud-init.service`` |
++---------+--------+----------------------------------------------------------+
+| runs | after local stage and configured networking is up |
++---------+--------+----------------------------------------------------------+
+| blocks | as much of remaining boot as possible |
++---------+--------+----------------------------------------------------------+
+| modules | *cloud_init_modules* in ``/etc/cloud/cloud.cfg`` |
++---------+--------+----------------------------------------------------------+
+
+This stage requires all configured networking to be online, as it will fully
+process any user data that is found. Here, processing means it will:
+
+- retrieve any ``#include`` or ``#include-once`` (recursively) including
+ http,
+- decompress any compressed content, and
+- run any part-handler found.
+
+This stage runs the ``disk_setup`` and ``mounts`` modules which may partition
+and format disks and configure mount points (such as in :file:`/etc/fstab`).
+Those modules cannot run earlier as they may receive configuration input
+from sources only available via the network. For example, a user may have
+provided user data in a network resource that describes how local mounts
+should be done.
+
+On some clouds, such as Azure, this stage will create filesystems to be
+mounted, including ones that have stale (previous instance) references in
+:file:`/etc/fstab`. As such, entries in :file:`/etc/fstab` other than those
+necessary for cloud-init to run should not be done until after this stage.
+
+A part-handler will run at this stage, as will boothooks including
+cloud-config ``bootcmd``. The user of this functionality has to be aware
+that the system is in the process of booting when their code runs.
+
+.. _boot-Config:
+
+Config
+======
+
++------------------+----------------------------------------------------------+
+| systemd service | ``cloud-config.service`` |
++---------+--------+----------------------------------------------------------+
+| runs | after network |
++---------+--------+----------------------------------------------------------+
+| blocks | nothing |
++---------+--------+----------------------------------------------------------+
+| modules | *cloud_config_modules* in ``/etc/cloud/cloud.cfg`` |
++---------+--------+----------------------------------------------------------+
+
+This stage runs config modules only. Modules that do not really have an
+effect on other stages of boot are run here, including ``runcmd``.
+
+.. _boot-Final:
+
+Final
+=====
+
++------------------+----------------------------------------------------------+
+| systemd service | ``cloud-final.service`` |
++---------+--------+----------------------------------------------------------+
+| runs | as final part of boot (traditional "rc.local") |
++---------+--------+----------------------------------------------------------+
+| blocks | nothing |
++---------+--------+----------------------------------------------------------+
+| modules | *cloud_final_modules* in ``/etc/cloud/cloud.cfg`` |
++---------+--------+----------------------------------------------------------+
+
+This stage runs as late in boot as possible. Any scripts that a user is
+accustomed to running after logging into a system should run correctly here.
+Things that run here include:
+
+- package installations,
+- configuration management plugins (Ansible, Puppet, Chef, salt-minion), and
+- user-defined scripts (i.e., shell scripts passed as user data).
+
+For scripts external to ``cloud-init`` looking to wait until ``cloud-init`` is
+finished, the :command:`cloud-init status --wait` subcommand can help block
+external scripts until ``cloud-init`` is done without having to write your own
+``systemd`` units dependency chains. See :ref:`cli_status` for more info.
+
+.. _boot-First_boot_determination:
+
+First boot determination
+========================
+
+``Cloud-init`` has to determine whether or not the current boot is the first
+boot of a new instance, so that it applies the appropriate configuration. On
+an instance's first boot, it should run all "per-instance" configuration,
+whereas on a subsequent boot it should run only "per-boot" configuration. This
+section describes how ``cloud-init`` performs this determination, as well as
+why it is necessary.
+
+When it runs, ``cloud-init`` stores a cache of its internal state for use
+across stages and boots.
+
+If this cache is present, then ``cloud-init`` has run on this system
+before [#not-present]_. There are two cases where this could occur. Most
+commonly, the instance has been rebooted, and this is a second/subsequent
+boot. Alternatively, the filesystem has been attached to a *new* instance,
+and this is the instance's first boot. The most obvious case where this
+happens is when an instance is launched from an image captured from a
+launched instance.
+
+By default, ``cloud-init`` attempts to determine which case it is running
+in by checking the instance ID in the cache against the instance ID it
+determines at runtime. If they do not match, then this is an instance's
+first boot; otherwise, it's a subsequent boot. Internally, ``cloud-init``
+refers to this behaviour as ``check``.
+
+This behaviour is required for images captured from launched instances to
+behave correctly, and so is the default that generic cloud images ship with.
+However, there are cases where it can cause problems [#problems]_. For these
+cases, ``cloud-init`` has support for modifying its behaviour to trust the
+instance ID that is present in the system unconditionally. This means that
+``cloud-init`` will never detect a new instance when the cache is present,
+and it follows that the only way to cause ``cloud-init`` to detect a new
+instance (and therefore its first boot) is to manually remove
+``cloud-init``'s cache. Internally, this behaviour is referred to as
+``trust``.
+
+To configure which of these behaviours to use, ``cloud-init`` exposes the
+``manual_cache_clean`` configuration option. When ``false`` (the default),
+``cloud-init`` will ``check`` and clean the cache if the instance IDs do
+not match (this is the default, as discussed above). When ``true``,
+``cloud-init`` will ``trust`` the existing cache (and therefore not clean it).
+
+Manual cache cleaning
+=====================
+
+``Cloud-init`` ships a command for manually cleaning the cache:
+:command:`cloud-init clean`. See :ref:`cli_clean`'s documentation for further
+details.
+
+Reverting ``manual_cache_clean`` setting
+----------------------------------------
+
+Currently there is no support for switching an instance that is launched with
+``manual_cache_clean: true`` from ``trust`` behaviour to ``check`` behaviour,
+other than manually cleaning the cache.
+
+.. warning:: If you want to capture an instance that is currently in ``trust``
+ mode as an image for launching other instances, you **must** manually clean
+ the cache. If you do not do so, then instances launched from the captured
+ image will all detect their first boot as a subsequent boot of the captured
+ instance, and will not apply any per-instance configuration.
+
+ This is a functional issue, but also a potential security one:
+ ``cloud-init`` is responsible for rotating SSH host keys on first boot,
+ and this will not happen on these instances.
+
+.. [#not-present] It follows that if this cache is not present,
+ ``cloud-init`` has not run on this system before, so this is
+ unambiguously this instance's first boot.
+
+.. [#problems] A couple of ways in which this strict reliance on the presence
+ of a datasource has been observed to cause problems:
+
+ - If a cloud's metadata service is flaky and ``cloud-init`` cannot
+ obtain the instance ID locally on that platform, ``cloud-init``'s
+ instance ID determination will sometimes fail to determine the current
+ instance ID, which makes it impossible to determine if this is an
+ instance's first or subsequent boot (`#1885527`_).
+ - If ``cloud-init`` is used to provision a physical appliance or device
+ and an attacker can present a datasource to the device with a different
+ instance ID, then ``cloud-init``'s default behaviour will detect this as
+ an instance's first boot and reset the device using the attacker's
+ configuration (this has been observed with the
+ :ref:`NoCloud datasource<datasource_nocloud>` in `#1879530`_).
+
+.. _generator: https://www.freedesktop.org/software/systemd/man/systemd.generator.html
+.. _#1885527: https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1885527
+.. _#1879530: https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1879530
diff --git a/doc/rtd/explanation/configuration.rst b/doc/rtd/explanation/configuration.rst
new file mode 100644
index 00000000..456ded97
--- /dev/null
+++ b/doc/rtd/explanation/configuration.rst
@@ -0,0 +1,81 @@
+.. _configuration:
+
+Configuration sources
+*********************
+
+Internally, ``cloud-init`` builds a single configuration that is then
+referenced throughout the life of ``cloud-init``. The configuration is built
+from multiple sources such that if a key is defined in multiple sources, the
+higher priority source overwrites the lower priority source.
+
+Base configuration
+==================
+
+From lowest priority to highest, configuration sources are:
+
+- **Hardcoded config**: Config_ that lives within the source of ``cloud-init``
+ and cannot be changed.
+- **Configuration directory**: Anything defined in :file:`/etc/cloud/cloud.cfg`
+ and :file:`/etc/cloud/cloud.cfg.d`.
+- **Runtime config**: Anything defined in :file:`/run/cloud-init/cloud.cfg`.
+- **Kernel command line**: On the kernel command line, anything found between
+ ``cc:`` and ``end_cc`` will be interpreted as cloud-config user data.
+
+These four sources make up the base configuration.
+
+Vendor and user data
+====================
+
+Added to the base configuration are :ref:`vendor data<vendordata>` and
+:ref:`user data<user_data_formats>` which are both provided by the datasource.
+
+These get fetched from the datasource and are defined at instance launch.
+
+.. note::
+ While much of what is defined in the base configuration can be overridden by
+ vendor data and user data, base configuration sources do not conform to
+ :ref:`#cloud-config<user_data_formats>`.
+
+Network configuration
+=====================
+
+Network configuration happens independently from other ``cloud-init``
+configuration. See :ref:`network configuration documentation<network_config>`
+for more information.
+
+Specifying configuration
+==========================
+
+End users
+---------
+
+Pass :ref:`user data<user_data_formats>` to the cloud provider.
+Every platform supporting ``cloud-init`` will provide a method of supplying
+user data. If you're unsure how to do this, reference the documentation
+provided by the cloud platform you're on. Additionally, there may be
+related ``cloud-init`` documentation in the :ref:`datasource<datasources>`
+section.
+
+Once an instance has been initialised, the user data may not be edited.
+It is sourced directly from the cloud, so even if you find a local file
+that contains user data, it will likely be overwritten in the next boot.
+
+Distro providers
+----------------
+
+Modify the base config. This often involves submitting a PR to modify
+the base `cloud.cfg template`_, which is used to customise
+:file:`/etc/cloud/cloud.cfg` per distro. Additionally, a file can be added to
+:file:`/etc/cloud/cloud.cfg.d` to override a piece of the base configuration.
+
+Cloud providers
+---------------
+
+Pass vendor data. This is the preferred method for clouds to provide
+their own customisation. In some cases, it may make sense to modify the
+base config in the same manner as distro providers on cloud-supported
+images.
+
+
+.. _Config: https://github.com/canonical/cloud-init/blob/b861ea8a5e1fd0eb33096f60f54eeff42d80d3bd/cloudinit/settings.py#L22
+.. _cloud.cfg template: https://github.com/canonical/cloud-init/blob/main/config/cloud.cfg.tmpl
diff --git a/doc/rtd/explanation/events.rst b/doc/rtd/explanation/events.rst
new file mode 100644
index 00000000..0767d025
--- /dev/null
+++ b/doc/rtd/explanation/events.rst
@@ -0,0 +1,95 @@
+.. _events:
+
+Events and updates
+******************
+
+Events
+======
+
+``Cloud-init`` will fetch and apply cloud and user data configuration
+upon several event types. The two most common events for ``cloud-init``
+are when an instance first boots and any subsequent boot thereafter (reboot).
+In addition to boot events, ``cloud-init`` users and vendors are interested
+in when devices are added. ``Cloud-init`` currently supports the following
+event types:
+
+- ``BOOT_NEW_INSTANCE``: New instance first boot.
+- ``BOOT``: Any system boot other than ``BOOT_NEW_INSTANCE``.
+- ``BOOT_LEGACY``: Similar to ``BOOT``, but applies networking config twice
+ each boot: once during the :ref:`Local stage<boot-Local>`, then again in the
+ :ref:`Network stage<boot-Network>`. As this behaviour was previously the
+ default behaviour, this option exists to prevent regressing such behaviour.
+- ``HOTPLUG``: Dynamic add of a system device.
+
+Future work will likely include infrastructure and support for the following
+events:
+
+- ``METADATA_CHANGE``: An instance's metadata has changed.
+- ``USER_REQUEST``: Directed request to update.
+
+Datasource event support
+========================
+
+All :ref:`datasources<datasources>` support the ``BOOT_NEW_INSTANCE`` event
+by default. Each datasource will declare a set of these events that it is
+capable of handling. Datasources may not support all event types. In some
+cases a system may be configured to allow a particular event but may be
+running on a platform whose datasource cannot support the event.
+
+Configuring event updates
+=========================
+
+Update configuration may be specified via user data, which can be used to
+enable or disable handling of specific events. This configuration will be
+honored as long as the events are supported by the datasource. However,
+configuration will always be applied at first boot, regardless of the user
+data specified.
+
+Updates
+-------
+
+Update policy configuration defines which events are allowed to be handled.
+This is separate from whether a particular platform or datasource has the
+capability for such events.
+
+``scope``: *<name of the* ``scope`` *for event policy>*
+ The ``scope`` value is a string which defines which domain the event occurs
+ under. Currently, the only known ``scope`` is ``network``, though more
+ ``scopes`` may be added in the future. ``Scopes`` are defined by convention
+ but arbitrary values can be used.
+
+``when``: *<list of events to handle for a particular* ``scope`` *>*
+ Each ``scope`` requires a ``when`` element to specify which events
+ are to allowed to be handled.
+
+Hotplug
+=======
+
+When the ``hotplug`` event is supported by the datasource and configured in
+user data, ``cloud-init`` will respond to the addition or removal of network
+interfaces to the system. In addition to fetching and updating the system
+metadata, ``cloud-init`` will also bring up/down the newly added interface.
+
+.. warning::
+ Due to its use of ``systemd`` sockets, ``hotplug`` functionality is
+ currently incompatible with SELinux. This issue is being `tracked
+ on Launchpad`_. Additionally, ``hotplug`` support is considered
+ experimental for non-Debian-based systems.
+
+Example
+=======
+
+Apply network config every boot
+-------------------------------
+
+On every boot, apply network configuration found in the datasource.
+
+.. code-block:: shell-session
+
+ # apply network config on every boot
+ updates:
+ network:
+ when: ['boot']
+
+.. _Cloud-init: https://launchpad.net/cloud-init
+.. _tracked on Launchpad: https://bugs.launchpad.net/cloud-init/+bug/1936229
diff --git a/doc/rtd/topics/format.rst b/doc/rtd/explanation/format.rst
index 6136753d..1e9c9307 100644
--- a/doc/rtd/topics/format.rst
+++ b/doc/rtd/explanation/format.rst
@@ -1,24 +1,23 @@
.. _user_data_formats:
-*****************
-User-Data Formats
+User data formats
*****************
-User data that will be acted upon by cloud-init must be in one of the following
-types.
+User data that will be acted upon by ``cloud-init`` must be in one of the
+following types.
-Cloud Config Data
+Cloud config data
=================
-Cloud-config is the simplest way to accomplish some things via user-data. Using
-cloud-config syntax, the user can specify certain things in a human friendly
-format.
+Cloud-config is the simplest way to accomplish some things via user data.
+Using cloud-config syntax, the user can specify certain things in a
+human-friendly format.
These things include:
-- apt upgrade should be run on first boot
-- a different apt mirror should be used
-- additional apt sources should be added
+- ``apt upgrade`` should be run on first boot
+- a different ``apt`` mirror should be used
+- additional ``apt`` sources should be added
- certain SSH keys should be imported
- *and many more...*
@@ -32,11 +31,13 @@ Begins with: ``#cloud-config`` or ``Content-Type: text/cloud-config`` when
using a MIME archive.
.. note::
- New in cloud-init v. 18.4: Cloud config data can also render cloud instance
- metadata variables using jinja templating. See
+ New in ``cloud-init`` v. 18.4: Cloud config data can also render cloud
+ instance metadata variables using jinja templating. See
:ref:`instance_metadata` for more information.
-User-Data Script
+.. _user_data_script:
+
+User data script
================
Typically used by those who just want to execute a shell script.
@@ -44,13 +45,13 @@ Typically used by those who just want to execute a shell script.
Begins with: ``#!`` or ``Content-Type: text/x-shellscript`` when using a MIME
archive.
-User-data scripts can optionally render cloud instance metadata variables using
+User data scripts can optionally render cloud instance metadata variables using
jinja templating. See :ref:`instance_metadata` for more information.
-Example Script
+Example script
--------------
-Create a script file ``myscript.sh`` that contains the following:
+Create a script file :file:`myscript.sh` that contains the following:
.. code-block::
@@ -63,30 +64,31 @@ Now run:
$ euca-run-instances --key mykey --user-data-file myscript.sh ami-a07d95c9
-Kernel Command Line
+Kernel command line
===================
-When using the :ref:`datasource_nocloud` datasource, users can pass user data
-via the kernel command line parameters. See the :ref:`datasource_nocloud`
-datasource and :ref:`kernel_cmdline` documentations for more details.
+When using the NoCloud datasource, users can pass user data via the kernel
+command line parameters. See the :ref:`NoCloud datasource<datasource_nocloud>`
+and :ref:`kernel_cmdline` documentation for more details.
-Gzip Compressed Content
+Gzip compressed content
=======================
Content found to be gzip compressed will be uncompressed.
The uncompressed data will then be used as if it were not compressed.
-This is typically useful because user-data is limited to ~16384 [#]_ bytes.
+This is typically useful because user data is limited to ~16384 [#]_ bytes.
-Mime Multi Part Archive
+MIME multi-part archive
=======================
This list of rules is applied to each part of this multi-part file.
-Using a mime-multi part file, the user can specify more than one type of data.
+Using a MIME multi-part file, the user can specify more than one type of data.
For example, both a user data script and a cloud-config type could be
specified.
-Supported content-types are listed from the cloud-init subcommand make-mime:
+Supported content-types are listed from the ``cloud-init`` subcommand
+:command:`make-mime`:
.. code-block:: shell-session
@@ -109,56 +111,56 @@ Example output:
x-shellscript-per-instance
x-shellscript-per-once
-Helper subcommand to generate mime messages
+Helper subcommand to generate MIME messages
-------------------------------------------
-The cloud-init subcommand can generate MIME multi-part files: `make-mime`_.
+The ``cloud-init`` `make-mime`_ subcommand can also generate MIME multi-part
+files.
-``make-mime`` subcommand takes pairs of (filename, "text/" mime subtype)
-separated by a colon (e.g. ``config.yaml:cloud-config``) and emits a MIME
-multipart message to stdout.
+The :command:`make-mime` subcommand takes pairs of (filename, "text/" mime
+subtype) separated by a colon (e.g., ``config.yaml:cloud-config``) and emits a
+MIME multipart message to :file:`stdout`.
Examples
--------
-Create userdata containing both a cloud-config (``config.yaml``)
-and a shell script (``script.sh``)
+
+Create user data containing both a cloud-config (:file:`config.yaml`)
+and a shell script (:file:`script.sh`)
.. code-block:: shell-session
$ cloud-init devel make-mime -a config.yaml:cloud-config -a script.sh:x-shellscript > userdata
-Create userdata containing 3 shell scripts:
+Create user data containing 3 shell scripts:
-- ``always.sh`` - Run every boot
-- ``instance.sh`` - Run once per instance
-- ``once.sh`` - Run once
+- :file:`always.sh` - run every boot
+- :file:`instance.sh` - run once per instance
+- :file:`once.sh` - run once
.. code-block:: shell-session
$ cloud-init devel make-mime -a always.sh:x-shellscript-per-boot -a instance.sh:x-shellscript-per-instance -a once.sh:x-shellscript-per-once
-.. _make-mime: https://github.com/canonical/cloud-init/blob/main/cloudinit/cmd/devel/make_mime.py
-
-Include File
-============
+``include`` file
+================
-This content is a ``include`` file.
+This content is an :file:`include` file.
-The file contains a list of urls, one per line. Each of the URLs will be read,
-and their content will be passed through this same set of rules. I.e., the
-content read from the URL can be gzipped, mime-multi-part, or plain text. If
+The file contains a list of URLs, one per line. Each of the URLs will be read
+and their content will be passed through this same set of rules, i.e., the
+content read from the URL can be gzipped, MIME multi-part, or plain text. If
an error occurs reading a file the remaining files will not be read.
Begins with: ``#include`` or ``Content-Type: text/x-include-url`` when using
a MIME archive.
-Cloud Boothook
-==============
+``cloud-boothook``
+==================
-This content is ``boothook`` data. It is stored in a file under
-``/var/lib/cloud`` and then executed immediately. This is the earliest ``hook``
+This content is `boothook` data. It is stored in a file under
+:file:`/var/lib/cloud` and executed immediately. This is the earliest `hook`
available. Note, that there is no mechanism provided for running only once. The
-boothook must take care of this itself.
+`boothook` must take care of this itself.
It is provided with the instance id in the environment variable
``INSTANCE_ID``. This could be made use of to provide a 'once-per-instance'
@@ -167,18 +169,18 @@ type of functionality.
Begins with: ``#cloud-boothook`` or ``Content-Type: text/cloud-boothook`` when
using a MIME archive.
-Part Handler
+Part-handler
============
-This is a ``part-handler``: It contains custom code for either supporting new
+This is a `part-handler`: It contains custom code for either supporting new
mime-types in multi-part user data, or overriding the existing handlers for
-supported mime-types. It will be written to a file in ``/var/lib/cloud/data``
-based on its filename (which is generated).
+supported mime-types. It will be written to a file in
+:file:`/var/lib/cloud/data` based on its filename (which is generated).
-This must be python code that contains a ``list_types`` function and a
+This must be Python code that contains a ``list_types`` function and a
``handle_part`` function. Once the section is read the ``list_types`` method
-will be called. It must return a list of mime-types that this part-handler
-handles. Because mime parts are processed in order, a ``part-handler`` part
+will be called. It must return a list of mime-types that this `part-handler`
+handles. Since MIME parts are processed in order, a `part-handler` part
must precede any parts with mime-types it is expected to handle in the same
user data.
@@ -192,10 +194,10 @@ The ``handle_part`` function must be defined like:
# filename = the filename of the part (or a generated filename if none is present in mime data)
# payload = the parts' content
-Cloud-init will then call the ``handle_part`` function once before it handles
-any parts, once per part received, and once after all parts have been handled.
-The ``'__begin__'`` and ``'__end__'`` sentinels allow the part handler to do
-initialization or teardown before or after receiving any parts.
+``Cloud-init`` will then call the ``handle_part`` function once before it
+handles any parts, once per part received, and once after all parts have been
+handled. The ``'__begin__'`` and ``'__end__'`` sentinels allow the part
+handler to do initialisation or teardown before or after receiving any parts.
Begins with: ``#part-handler`` or ``Content-Type: text/part-handler`` when
using a MIME archive.
@@ -207,15 +209,16 @@ Example
:language: python
:linenos:
-Also this `blog`_ post offers another example for more advanced usage.
+Also, `this blog post`_ offers another example for more advanced usage.
-Disabling User-Data
+Disabling user data
===================
-Cloud-init can be configured to ignore any user-data provided to instance.
+``Cloud-init`` can be configured to ignore any user data provided to instance.
This allows custom images to prevent users from accidentally breaking closed
appliances. Setting ``allow_userdata: false`` in the configuration will disable
-cloud-init from processing user-data.
+``cloud-init`` from processing user data.
+.. _make-mime: https://github.com/canonical/cloud-init/blob/main/cloudinit/cmd/devel/make_mime.py
.. [#] See your cloud provider for applicable user-data size limitations...
-.. _blog: http://foss-boss.blogspot.com/2011/01/advanced-cloud-init-custom-handlers.html
+.. _this blog post: http://foss-boss.blogspot.com/2011/01/advanced-cloud-init-custom-handlers.html
diff --git a/doc/rtd/explanation/index.rst b/doc/rtd/explanation/index.rst
new file mode 100644
index 00000000..ea015a40
--- /dev/null
+++ b/doc/rtd/explanation/index.rst
@@ -0,0 +1,18 @@
+Explanation
+***********
+
+Our explanatory and conceptual guides are written to provide a better
+understanding of how ``cloud-init`` works. They enable you to expand your
+knowledge and become better at using and configuring ``cloud-init``.
+
+-----
+
+.. toctree::
+ :maxdepth: 1
+
+ configuration.rst
+ boot.rst
+ format.rst
+ events.rst
+ instancedata.rst
+ vendordata.rst
diff --git a/doc/rtd/topics/instancedata.rst b/doc/rtd/explanation/instancedata.rst
index 575dbf1b..8f5b310a 100644
--- a/doc/rtd/topics/instancedata.rst
+++ b/doc/rtd/explanation/instancedata.rst
@@ -1,114 +1,111 @@
.. _instance_metadata:
-*****************
-Instance Metadata
+
+Instance metadata
*****************
.. toctree::
- :maxdepth: 1
- :hidden:
+ :maxdepth: 1
+ :hidden:
- kernel-cmdline.rst
+ kernel-cmdline.rst
-What is instance-data?
-========================
+What is ``instance-data?``
+==========================
-Each cloud provider presents unique
-configuration metadata to a launched cloud instance. Cloud-init
-crawls this metadata and then caches and exposes this information
-as a standarized and versioned JSON object known as instance-data.
-This instance-data may then be
-queried or later used by cloud-init in templated configuration and scripts.
+Each cloud provider presents unique configuration metadata to a launched cloud
+instance. ``Cloud-init`` crawls this metadata and then caches and exposes this
+information as a standardised and versioned JSON object known as
+``instance-data``. This ``instance-data`` may then be queried or later used
+by ``cloud-init`` in templated configuration and scripts.
An example of a small subset of instance-data on a launched EC2 instance:
.. code-block:: json
- {
- "v1": {
- "cloud_name": "aws",
- "distro": "ubuntu",
- "distro_release": "jammy",
- "distro_version": "22.04",
- "instance_id": "i-06b5687b4d7b8595d",
- "machine": "x86_64",
- "platform": "ec2",
- "python_version": "3.10.4",
- "region": "us-east-2",
- "variant": "ubuntu"
- }
- }
+ {
+ "v1": {
+ "cloud_name": "aws",
+ "distro": "ubuntu",
+ "distro_release": "jammy",
+ "distro_version": "22.04",
+ "instance_id": "i-06b5687b4d7b8595d",
+ "machine": "x86_64",
+ "platform": "ec2",
+ "python_version": "3.10.4",
+ "region": "us-east-2",
+ "variant": "ubuntu"
+ }
+ }
Discovery
=========
-One way to easily explore what instance-data variables are available on
+One way to easily explore which ``instance-data`` variables are available on
your machine is to use the :ref:`cloud-init query<cli_query>` tool.
-Warnings or exceptions will be raised on invalid instance-data keys,
+Warnings or exceptions will be raised on invalid ``instance-data`` keys,
paths or invalid syntax.
-The **query** command also publishes ``userdata`` and ``vendordata`` keys to
-the root user which will contain the decoded user and vendor data provided to
-this instance. Non-root users referencing userdata or vendordata keys will
-see only redacted values.
+The :command:`query` command also publishes ``userdata`` and ``vendordata``
+keys to the root user which will contain the decoded user and vendor data
+provided to this instance. Non-root users referencing ``userdata`` or
+``vendordata`` keys will see only redacted values.
.. note::
- To save time designing a user-data template for a specific cloud's
- instance-data.json, use the 'render' cloud-init command on an
- instance booted on your favorite cloud. See :ref:`cli_devel` for more
- information.
+ To save time designing a user data template for a specific cloud's
+ :file:`instance-data.json`, use the :command:`render` command on an
+ instance booted on your favorite cloud. See :ref:`cli_devel` for more
+ information.
+
+.. _instancedata-Using:
-Using instance-data
-===================
+Using ``instance-data``
+=======================
-Instance-data can be used in:
+``instance-data`` can be used in:
-* :ref:`User-data scripts<topics/format:User-Data Script>`
-* :ref:`Cloud-config data<topics/format:Cloud Config Data>`
-* :ref:`Base configuration<configuration>`
-* Command line interface via **cloud-init query** or
- **cloud-init devel render**
+* :ref:`User data scripts<user_data_script>`.
+* :ref:`Cloud-config data<user_data_formats>`.
+* :ref:`Base configuration<configuration>`.
+* Command line interface via :command:`cloud-init query` or
+ :command:`cloud-init devel render`.
The aforementioned configuration sources support jinja template rendering.
When the first line of the provided configuration begins with
-**## template: jinja**, cloud-init will use jinja to render that file.
-Any instance-data variables are surfaced as jinja template
-variables.
+**## template: jinja**, ``cloud-init`` will use jinja to render that file.
+Any ``instance-data`` variables are surfaced as jinja template variables.
.. note::
- Trying to reference jinja variables that don't exist in instance-data
- will result in warnings in ``/var/log/cloud-init.log`` and the following
- string in your rendered user-data:
- ``CI_MISSING_JINJA_VAR/<your_varname>``.
+ Trying to reference jinja variables that don't exist in ``instance-data``
+ will result in warnings in :file:`/var/log/cloud-init.log` and the following
+ string in your rendered :file:`user-data`:
+ ``CI_MISSING_JINJA_VAR/<your_varname>``.
-Sensitive data such as user passwords may be contained in
-instance-data. Cloud-init separates this sensitive data such that
-is it only readable by root. In the case that a non-root user attempts
-to read sensitive instance-data, they will receive redacted data or same
-warnings and text that occur if a variable does not exist.
+Sensitive data such as user passwords may be contained in ``instance-data``.
+``Cloud-init`` separates this sensitive data such that is it only readable by
+root. In the case that a non-root user attempts to read sensitive
+``instance-data``, they will receive redacted data or the same warnings and
+text that occur if a variable does not exist.
-Example Usage
--------------
-
-Cloud config with instance-data
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Example: Cloud config with ``instance-data``
+--------------------------------------------
.. code-block:: yaml
- ## template: jinja
- #cloud-config
- runcmd:
- - echo 'EC2 public hostname allocated to instance: {{
- ds.meta_data.public_hostname }}' > /tmp/instance_metadata
- - echo 'EC2 availability zone: {{ v1.availability_zone }}' >>
- /tmp/instance_metadata
- - curl -X POST -d '{"hostname": "{{ds.meta_data.public_hostname }}",
- "availability-zone": "{{ v1.availability_zone }}"}'
- https://example.com
-
-User-data script with instance-data
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ ## template: jinja
+ #cloud-config
+ runcmd:
+ - echo 'EC2 public hostname allocated to instance: {{
+ ds.meta_data.public_hostname }}' > /tmp/instance_metadata
+ - echo 'EC2 availability zone: {{ v1.availability_zone }}' >>
+ /tmp/instance_metadata
+ - curl -X POST -d '{"hostname": "{{ds.meta_data.public_hostname }}",
+ "availability-zone": "{{ v1.availability_zone }}"}'
+ https://example.com
+
+Example: User data script with ``instance-data``
+------------------------------------------------
.. code-block:: jinja
@@ -120,245 +117,275 @@ User-data script with instance-data
{%- endif %}
...
-CLI discovery of instance-data
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Example: CLI discovery of ``instance-data``
+-------------------------------------------
.. code-block:: shell-session
- # List all instance-data keys and values as root user
- % sudo cloud-init query --all
- {...}
-
- # List all top-level instance-data keys available
- % cloud-init query --list-keys
-
- # Introspect nested keys on an object
- % cloud-init query -f "{{ds.keys()}}"
- dict_keys(['meta_data', '_doc'])
-
- # Failure to reference valid dot-delimited key path on a known top-level key
- % cloud-init query v1.not_here
- ERROR: instance-data 'v1' has no 'not_here'
-
- # Test expected value using valid instance-data key path
- % cloud-init query -f "My AMI: {{ds.meta_data.ami_id}}"
- My AMI: ami-0fecc35d3c8ba8d60
-
- # The --format command renders jinja templates, this can also be used
- # to develop and test jinja template constructs
- % cat > test-templating.yaml <<EOF
- {% for val in ds.meta_data.keys() %}
- - {{ val }}
- {% endfor %}
- EOF
- % cloud-init query --format="$( cat test-templating.yaml )"
- - instance_id
- - dsmode
- - local_hostname
+ # List all instance-data keys and values as root user
+ $ sudo cloud-init query --all
+ {...}
+
+ # List all top-level instance-data keys available
+ $ cloud-init query --list-keys
+
+ # Introspect nested keys on an object
+ $ cloud-init query -f "{{ds.keys()}}"
+ dict_keys(['meta_data', '_doc'])
+
+ # Failure to reference valid dot-delimited key path on a known top-level key
+ $ cloud-init query v1.not_here
+ ERROR: instance-data 'v1' has no 'not_here'
+
+ # Test expected value using valid instance-data key path
+ $ cloud-init query -f "My AMI: {{ds.meta_data.ami_id}}"
+ My AMI: ami-0fecc35d3c8ba8d60
+
+ # The --format command renders jinja templates, this can also be used
+ # to develop and test jinja template constructs
+ $ cat > test-templating.yaml <<EOF
+ {% for val in ds.meta_data.keys() %}
+ - {{ val }}
+ {% endfor %}
+ EOF
+ $ cloud-init query --format="$( cat test-templating.yaml )"
+ - instance_id
+ - dsmode
+ - local_hostname
Reference
=========
-Storage Locations
+Storage locations
-----------------
-* ``/run/cloud-init/instance-data.json``: world-readable json containing
- standardized keys, sensitive keys redacted
-* ``/run/cloud-init/instance-data-sensitive.json``: root-readable unredacted
- json blob
-
-Format of instance-data.json
-----------------------------
-
-Top-level keys:
-
-* **base64_encoded_keys**: A list of forward-slash delimited key paths into
- the instance-data.json object whose value is base64encoded for json
- compatibility. Values at these paths should be decoded to get the original
- value.
-
-* **sensitive_keys**: A list of forward-slash delimited key paths into
- the instance-data.json object whose value is considered by the datasource as
- 'security sensitive'. Only the keys listed here will be redacted from
- instance-data.json for non-root users.
-
-* **merged_cfg**: Merged cloud-init :ref:`base_config_reference` from
- `/etc/cloud/cloud.cfg` and `/etc/cloud/cloud-cfg.d`. Values under this key
- could contain sensitive information such as passwords, so it is included in
- the **sensitive-keys** list which is only readable by root.
-
-* **ds**: Datasource-specific metadata crawled for the specific cloud
- platform. It should closely represent the structure of the cloud metadata
- crawled. The structure of content and details provided are entirely
- cloud-dependent. Mileage will vary depending on what the cloud exposes.
- The content exposed under the 'ds' key is currently **experimental** and
- expected to change slightly in the upcoming cloud-init release.
-
-* **sys_info**: Information about the underlying os, python, architecture and
- kernel. This represents the data collected by `cloudinit.util.system_info`.
-
-* **v1**: Standardized cloud-init metadata keys, these keys are guaranteed to
- exist on all cloud platforms. They will also retain their current behavior
- and format and will be carried forward even if cloud-init introduces a new
- version of standardized keys with **v2**.
-
-To cut down on keystrokes on the command line, cloud-init also provides
-top-level key aliases for any standardized ``v#`` keys present. The preceding
+
+* :file:`/run/cloud-init/instance-data.json`: world-readable JSON containing
+ standardised keys, sensitive keys redacted.
+* :file:`/run/cloud-init/instance-data-sensitive.json`: root-readable
+ unredacted JSON blob.
+
+:file:`instance-data.json` top level keys
+-----------------------------------------
+
+``base64_encoded_keys``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+A list of forward-slash delimited key paths into the :file:`instance-data.json`
+object whose value is base64encoded for JSON compatibility. Values at these
+paths should be decoded to get the original value.
+
+``sensitive_keys``
+^^^^^^^^^^^^^^^^^^
+
+A list of forward-slash delimited key paths into the :file:`instance-data.json`
+object whose value is considered by the datasource as 'security sensitive'.
+Only the keys listed here will be redacted from :file:`instance-data.json` for
+non-root users.
+
+``merged_cfg``
+^^^^^^^^^^^^^^
+
+Merged ``cloud-init`` :ref:`base_config_reference` from
+:file:`/etc/cloud/cloud.cfg` and :file:`/etc/cloud/cloud-cfg.d`. Values under
+this key could contain sensitive information such as passwords, so it is
+included in the ``sensitive-keys`` list which is only readable by root.
+
+``ds``
+^^^^^^
+
+Datasource-specific metadata crawled for the specific cloud platform. It should
+closely represent the structure of the cloud metadata crawled. The structure of
+content and details provided are entirely cloud-dependent. Mileage will vary
+depending on what the cloud exposes. The content exposed under the ``ds`` key
+is currently **experimental** and expected to change slightly in the upcoming
+``cloud-init`` release.
+
+``sys_info``
+^^^^^^^^^^^^
+
+Information about the underlying OS, Python, architecture and kernel. This
+represents the data collected by ``cloudinit.util.system_info``.
+
+``v1``
+^^^^^^
+
+Standardised ``cloud-init`` metadata keys, these keys are guaranteed to exist
+on all cloud platforms. They will also retain their current behaviour and
+format, and will be carried forward even if ``cloud-init`` introduces a new
+version of standardised keys with ``v2``.
+
+To cut down on keystrokes on the command line, ``cloud-init`` also provides
+top-level key aliases for any standardised ``v#`` keys present. The preceding
``v1`` is not required of ``v1.var_name`` These aliases will represent the
value of the highest versioned standard key. For example, ``cloud_name``
value will be ``v2.cloud_name`` if both ``v1`` and ``v2`` keys are present in
-instance-data.json.
+:file:`instance-data.json`.
-cloud-init also provides jinja-safe key aliases for any instance-data
-keys which contain jinja operator characters such as +, -, ., /, etc. Any
-jinja operator will be replaced with underscores in the jinja-safe key
-alias. This allows for cloud-init templates to use aliased variable
-references which allow for jinja's dot-notation reference such as
+``Cloud-init`` also provides jinja-safe key aliases for any ``instance-data``
+keys which contain jinja operator characters such as ``+``, ``-``, ``.``,
+``/``, etc. Any jinja operator will be replaced with underscores in the
+jinja-safe key alias. This allows for ``cloud-init`` templates to use aliased
+variable references which allow for jinja's dot-notation reference such as
``{{ ds.v1_0.my_safe_key }}`` instead of ``{{ ds["v1.0"]["my/safe-key"] }}``.
-The standardized keys present:
+Standardised :file:`instance-data.json` v1 keys
+-----------------------------------------------
+
+``v1._beta_keys``
+^^^^^^^^^^^^^^^^^
-v1._beta_keys
--------------
-List of standardized keys still in 'beta'. The format, intent or presence of
+List of standardised keys still in 'beta'. The format, intent or presence of
these keys can change. Do not consider them production-ready.
Example output:
-- [subplatform]
+ - [subplatform]
+
+``v1.cloud_name``
+^^^^^^^^^^^^^^^^^
-v1.cloud_name
--------------
Where possible this will indicate the 'name' of the cloud the system is running
on. This is different than the 'platform' item. For example, the cloud name of
Amazon Web Services is 'aws', while the platform is 'ec2'.
-If determining a specific name is not possible or provided in meta-data, then
-this filed may contain the same content as 'platform'.
+If determining a specific name is not possible or provided in
+:file:`meta-data`, then this filed may contain the same content as 'platform'.
Example output:
-- aws
-- openstack
-- azure
-- configdrive
-- nocloud
-- ovf
+ - aws
+ - openstack
+ - azure
+ - configdrive
+ - nocloud
+ - ovf
+
+``v1.distro``, ``v1.distro_version``, ``v1.distro_release``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-v1.distro, v1.distro_version, v1.distro_release
------------------------------------------------
This shall be the distro name, version and release as determined by
-`cloudinit.util.get_linux_distro`.
+``cloudinit.util.get_linux_distro``.
Example output:
-- alpine, 3.12.0, ''
-- centos, 7.5, core
-- debian, 9, stretch
-- freebsd, 12.0-release-p10,
-- opensuse, 42.3, x86_64
-- opensuse-tumbleweed, 20180920, x86_64
-- redhat, 7.5, 'maipo'
-- sles, 12.3, x86_64
-- ubuntu, 20.04, focal
-
-v1.instance_id
---------------
-Unique instance_id allocated by the cloud.
+ - alpine, 3.12.0, ''
+ - centos, 7.5, core
+ - debian, 9, stretch
+ - freebsd, 12.0-release-p10,
+ - opensuse, 42.3, x86_64
+ - opensuse-tumbleweed, 20180920, x86_64
+ - redhat, 7.5, 'maipo'
+ - sles, 12.3, x86_64
+ - ubuntu, 20.04, focal
-Examples output:
+``v1.instance_id``
+^^^^^^^^^^^^^^^^^^
-- i-<hash>
+Unique ``instance_id`` allocated by the cloud.
-v1.kernel_release
------------------
-This shall be the running kernel `uname -r`
+Example output:
+
+ - i-<hash>
+
+``v1.kernel_release``
+^^^^^^^^^^^^^^^^^^^^^
+
+This shall be the running kernel ``uname -r``.
Example output:
-- 5.3.0-1010-aws
+ - 5.3.0-1010-aws
+
+``v1.local_hostname``
+^^^^^^^^^^^^^^^^^^^^^
-v1.local_hostname
------------------
The internal or local hostname of the system.
-Examples output:
+Example output:
+
+ - ip-10-41-41-70
+ - <user-provided-hostname>
-- ip-10-41-41-70
-- <user-provided-hostname>
+``v1.machine``
+^^^^^^^^^^^^^^
-v1.machine
-----------
-This shall be the running cpu machine architecture `uname -m`
+This shall be the running cpu machine architecture ``uname -m``.
Example output:
-- x86_64
-- i686
-- ppc64le
-- s390x
+ - x86_64
+ - i686
+ - ppc64le
+ - s390x
+
+``v1.platform``
+^^^^^^^^^^^^^^^
-v1.platform
--------------
An attempt to identify the cloud platform instance that the system is running
on.
-Examples output:
+Example output:
+
+ - ec2
+ - openstack
+ - lxd
+ - gce
+ - nocloud
+ - ovf
-- ec2
-- openstack
-- lxd
-- gce
-- nocloud
-- ovf
+``v1.subplatform``
+^^^^^^^^^^^^^^^^^^
-v1.subplatform
---------------
Additional platform details describing the specific source or type of metadata
used. The format of subplatform will be:
``<subplatform_type> (<url_file_or_dev_path>)``
-Examples output:
+Example output:
+
+ - metadata (http://168.254.169.254)
+ - seed-dir (/path/to/seed-dir/)
+ - config-disk (/dev/cd0)
+ - configdrive (/dev/sr0)
-- metadata (http://168.254.169.254)
-- seed-dir (/path/to/seed-dir/)
-- config-disk (/dev/cd0)
-- configdrive (/dev/sr0)
+``v1.public_ssh_keys``
+^^^^^^^^^^^^^^^^^^^^^^
-v1.public_ssh_keys
-------------------
A list of SSH keys provided to the instance by the datasource metadata.
-Examples output:
+Example output:
-- ['ssh-rsa AA...', ...]
+ - ['ssh-rsa AA...', ...]
-v1.python_version
------------------
-The version of python that is running cloud-init as determined by
-`cloudinit.util.system_info`
+``v1.python_version``
+^^^^^^^^^^^^^^^^^^^^^
+
+The version of Python that is running ``cloud-init`` as determined by
+``cloudinit.util.system_info``.
Example output:
-- 3.7.6
+ - 3.7.6
+
+``v1.region``
+^^^^^^^^^^^^^
-v1.region
----------
-The physical region/data center in which the instance is deployed.
+The physical region/data centre in which the instance is deployed.
-Examples output:
+Example output:
+
+ - us-east-2
-- us-east-2
+``v1.availability_zone``
+^^^^^^^^^^^^^^^^^^^^^^^^
-v1.availability_zone
---------------------
The physical availability zone in which the instance is deployed.
-Examples output:
+Example output:
-- us-east-2b
-- nova
-- null
+ - us-east-2b
+ - nova
+ - null
Example Output
--------------
diff --git a/doc/rtd/explanation/kernel-cmdline.rst b/doc/rtd/explanation/kernel-cmdline.rst
new file mode 100644
index 00000000..94f646f5
--- /dev/null
+++ b/doc/rtd/explanation/kernel-cmdline.rst
@@ -0,0 +1,69 @@
+.. _kernel_cmdline:
+
+Kernel command line
+*******************
+
+In order to allow an ephemeral, or otherwise pristine image to receive some
+configuration, ``cloud-init`` will read a URL directed by the kernel command
+line and proceed as if its data had previously existed.
+
+This allows for configuring a metadata service, or some other data.
+
+.. note::
+ Usage of the kernel command line is somewhat of a last resort,
+ as it requires knowing in advance the correct command line or modifying
+ the boot loader to append data.
+
+For example, when :command:`cloud-init init --local` runs, it will check to
+see if ``cloud-config-url`` appears in key/value fashion in the kernel command
+line, as in:
+
+.. code-block:: text
+
+ root=/dev/sda ro cloud-config-url=http://foo.bar.zee/abcde
+
+``Cloud-init`` will then read the contents of the given URL. If the content
+starts with ``#cloud-config``, it will store that data to the local filesystem
+in a static filename :file:`/etc/cloud/cloud.cfg.d/91_kernel_cmdline_url.cfg`,
+and consider it as part of the config from that point forward.
+
+If that file exists already, it will not be overwritten, and the
+``cloud-config-url`` parameter is completely ignored.
+
+Then, when the datasource runs, it will find that config already available.
+
+So, to be able to configure the MAAS datasource by controlling the
+kernel command line from outside the image, you can append:
+
+.. code-block:: text
+
+ cloud-config-url=http://your.url.here/abcdefg
+
+Then, have the following content at that url:
+
+.. code-block:: yaml
+
+ #cloud-config
+ datasource:
+ MAAS:
+ metadata_url: http://mass-host.localdomain/source
+ consumer_key: Xh234sdkljf
+ token_key: kjfhgb3n
+ token_secret: 24uysdfx1w4
+
+.. warning::
+
+ ``url`` kernel command line key is deprecated.
+ Please use ``cloud-config-url`` parameter instead.
+
+.. note::
+
+ Since ``cloud-config-url=`` is so generic, in order to avoid false
+ positives, ``cloud-init`` requires the content to start with
+ ``#cloud-config`` for it to be considered.
+
+.. note::
+
+ The ``cloud-config-url=`` is un-authed http GET, and contains credentials.
+ It could be set up to be randomly generated and also to check the source
+ address in order to be more secure.
diff --git a/doc/rtd/explanation/vendordata.rst b/doc/rtd/explanation/vendordata.rst
new file mode 100644
index 00000000..621fcdeb
--- /dev/null
+++ b/doc/rtd/explanation/vendordata.rst
@@ -0,0 +1,71 @@
+.. _vendordata:
+
+Vendor data
+***********
+
+Overview
+========
+
+Vendor data is data provided by the entity that launches an instance (e.g.,
+the cloud provider). This data can be used to customise the image to fit into
+the particular environment it is being run in.
+
+Vendor data follows the same rules as user data, with the following
+caveats:
+
+1. Users have ultimate control over vendor data. They can disable its
+ execution or disable handling of specific parts of multi-part input.
+2. By default it only runs on first boot.
+3. Vendor data can be disabled by the user. If the use of vendor data is
+ required for the instance to run, then vendor data should not be used.
+4. User-supplied cloud-config is merged over cloud-config from vendor data.
+
+Users providing cloud-config data can use the ``#cloud-config-jsonp`` method
+to more finely control their modifications to the vendor-supplied
+cloud-config. For example, if both vendor and user have provided ``runcmd``
+then the default merge handler will cause the user's ``runcmd`` to override
+the one provided by the vendor. To append to ``runcmd``, the user could better
+provide multi-part input with a ``cloud-config-jsonp`` part like:
+
+.. code:: yaml
+
+ #cloud-config-jsonp
+ [{ "op": "add", "path": "/runcmd", "value": ["my", "command", "here"]}]
+
+Further, we strongly advise vendors to not "be evil". By evil, we mean any
+action that could compromise a system. Since users trust you, please take
+care to make sure that any vendor data is safe, atomic, idempotent and does
+not put your users at risk.
+
+Input formats
+=============
+
+``Cloud-init`` will download and cache to filesystem any vendor data that it
+finds. Vendor data is handled exactly like user data. This means that the
+vendor can supply multi-part input and have those parts acted on in the same
+way as with user data.
+
+The only differences are:
+
+* Vendor-data-defined scripts are stored in a different location than
+ user-data-defined scripts (to avoid namespace collision).
+* The user can disable part handlers via the cloud-config settings.
+ For example, to disable handling of 'part-handlers' in vendor data,
+ the user could provide user data like this:
+
+.. code:: yaml
+
+ #cloud-config
+ vendordata: {excluded: 'text/part-handler'}
+
+Examples
+========
+
+You can find examples in the examples subdirectory.
+
+Additionally, the :file:`tools` directory contains
+:file:`write-mime-multipart`, which can be used to easily generate MIME
+multi-part files from a list of input files. That data can then be given to
+an instance.
+
+See :command:`write-mime-multipart --help` for usage.
diff --git a/doc/rtd/topics/bugs.rst b/doc/rtd/howto/bugs.rst
index d7e79740..753d4545 100644
--- a/doc/rtd/topics/bugs.rst
+++ b/doc/rtd/howto/bugs.rst
@@ -1,19 +1,20 @@
.. _reporting_bugs:
-Reporting Bugs
+Reporting bugs
**************
-The following documents:
+In this guide, we will show you how to:
-1) How to collect information for reporting bugs
-2) How to file bugs to the upstream cloud-init project or for distro specific
- packages
+1) Collect logs to support your bug report.
+2) File bugs to the upstream ``cloud-init`` project via `Launchpad`_.
+3) Report issues for distro-specific packages.
-Collect Logs
+Collect logs
============
To aid in debugging, please collect the necessary logs. To do so, run the
-`collect-logs` subcommand to produce a tarfile that you can easily upload:
+:command:`collect-logs` subcommand to produce a tarfile that you can easily
+upload:
.. code-block:: shell-session
@@ -25,8 +26,9 @@ Example output:
Wrote /home/ubuntu/cloud-init.tar.gz
-If your version of cloud-init does not have the `collect-logs` subcommand,
-then please manually collect the base log files by doing the following:
+If your version of ``cloud-init`` does not have the :command:`collect-logs`
+subcommand, then please manually collect the base log files by running the
+following:
.. code-block:: shell-session
@@ -35,34 +37,34 @@ then please manually collect the base log files by doing the following:
$ sudo tar -cvf cloud-init.tar dmesg.txt journal.txt /run/cloud-init \
/var/log/cloud-init.log /var/log/cloud-init-output.log
-Report Upstream Bug
-===================
+Report upstream bugs
+====================
-Bugs for upstream cloud-init are tracked using Launchpad. To file a bug:
+Bugs for upstream ``cloud-init`` are tracked using Launchpad. To file a bug:
-1. Collect the necessary debug logs as described above
-2. `Create a Launchpad account`_ or login to your existing account
-3. `Report an upstream cloud-init bug`_
+1. Collect the necessary debug logs as described above.
+2. `Create a Launchpad account`_ or login to your existing account.
+3. `Report an upstream cloud-init bug`_.
If debug logs are not provided, you will be asked for them before any
further time is spent debugging. If you are unable to obtain the required
logs please explain why in the bug.
-If your bug is for a specific distro using cloud-init, please first consider
-reporting it with the upstream distro or confirm that it still occurs
-with the latest upstream cloud-init code. See below for details on specific
-distro reporting.
+If your bug is for a specific distro using ``cloud-init``, please first
+consider reporting it with the upstream distro or confirm that it still occurs
+with the latest upstream ``cloud-init`` code. See the following section for
+details on specific distro reporting.
-Distro Specific Issues
+Distro-specific issues
======================
-For issues specific to your distro please use one of the following distro
-specific reporting mechanisms:
+For issues specific to your distro please use one of the following
+distro-specific reporting mechanisms:
Ubuntu
------
-To report a bug on Ubuntu use the `ubuntu-bug` command on the affected
+To report a bug on Ubuntu use the :command:`ubuntu-bug` command on the affected
system to automatically collect the necessary logs and file a bug on
Launchpad:
@@ -77,29 +79,31 @@ commands in the above Collect Logs section and then report the bug on the
Debian
------
-To file a bug against the Debian package fo cloud-init please use the
+To file a bug against the Debian package of ``cloud-init`` please use the
`Debian bug tracker`_ to file against 'Package: cloud-init'. See the
-`Debian bug reporting wiki`_ wiki page for more details.
+`Debian bug reporting wiki`_ page for more details.
-Red Hat, CentOS, & Fedora
--------------------------
+Red Hat, CentOS and Fedora
+--------------------------
-To file a bug against the Red Hat or Fedora packages of cloud-init please use
-the `Red Hat bugzilla`_.
+To file a bug against the Red Hat or Fedora packages of ``cloud-init`` please
+use the `Red Hat bugzilla`_.
-SUSE & openSUSE
----------------
+SUSE and openSUSE
+-----------------
-To file a bug against the SuSE packages of cloud-init please use the
+To file a bug against the SUSE packages of ``cloud-init`` please use the
`SUSE bugzilla`_.
Arch Linux
----------
-To file a bug against the Arch package of cloud-init please use the
+To file a bug against the Arch package of ``cloud-init`` please use the
`Arch Linux Bugtracker`_. See the `Arch Linux bug reporting wiki`_ for more
details.
+.. LINKS:
+.. _Launchpad: https://launchpad.net/
.. _Create a Launchpad account: https://help.launchpad.net/YourAccount/NewAccount
.. _Report an upstream cloud-init bug: https://bugs.launchpad.net/cloud-init/+filebug
.. _Ubuntu bug tracker: https://bugs.launchpad.net/ubuntu/+source/cloud-init/+filebug
@@ -109,5 +113,3 @@ details.
.. _SUSE bugzilla: https://bugzilla.suse.com/index.cgi
.. _Arch Linux Bugtracker: https://bugs.archlinux.org/
.. _Arch Linux bug reporting wiki: https://wiki.archlinux.org/index.php/Bug_reporting_guidelines
-
-.. vi: textwidth=79
diff --git a/doc/rtd/howto/index.rst b/doc/rtd/howto/index.rst
new file mode 100644
index 00000000..23936fa9
--- /dev/null
+++ b/doc/rtd/howto/index.rst
@@ -0,0 +1,23 @@
+.. _howto_index:
+
+How-to guides
+*************
+
+If you have a specific goal in mind and are already familiar with the basics
+of ``cloud-init``, our how-to guides cover some of the more common operations
+and tasks that you may need to complete.
+
+They will help you to achieve a particular end result, but may require you to
+understand and adapt the steps to fit your specific requirements.
+
+-----
+
+How do I...?
+============
+
+.. toctree::
+ :maxdepth: 1
+
+ Test cloud-init locally before deploying <predeploy_testing.rst>
+ Change how often a module runs <module_run_frequency.rst>
+ Report a bug <bugs.rst>
diff --git a/doc/rtd/howto/module_run_frequency.rst b/doc/rtd/howto/module_run_frequency.rst
new file mode 100644
index 00000000..fc0f8921
--- /dev/null
+++ b/doc/rtd/howto/module_run_frequency.rst
@@ -0,0 +1,40 @@
+.. _module_frequency:
+
+How to change a module's run frequency
+**************************************
+
+You may want to change the default frequency at which a module runs, for
+example, to make the module run on every boot.
+
+To override the default frequency, you will need to modify the module
+list in :file:`/etc/cloud/cloud.cfg`:
+
+1. Change the module from a string (default) to a list.
+2. Set the first list item to the module name and the second item to the
+ frequency.
+
+Example
+=======
+
+The following example demonstrates how to log boot times to a file every boot.
+
+Update :file:`/etc/cloud/cloud.cfg`:
+
+.. code-block:: yaml
+ :name: /etc/cloud/cloud.cfg
+ :emphasize-lines: 3
+
+ cloud_final_modules:
+ # list shortened for brevity
+ - [phone-home, always]
+ - final-message
+ - power-state-change
+
+Then your user data could then be:
+
+.. code-block:: yaml
+
+ #cloud-config
+ phone_home:
+ url: http://example.com/$INSTANCE_ID/
+ post: all
diff --git a/doc/rtd/howto/predeploy_testing.rst b/doc/rtd/howto/predeploy_testing.rst
new file mode 100644
index 00000000..783ef51e
--- /dev/null
+++ b/doc/rtd/howto/predeploy_testing.rst
@@ -0,0 +1,141 @@
+.. _predeploy_testing:
+
+How to test ``cloud-init`` locally before deploying
+***************************************************
+
+It's very likely that you will want to test ``cloud-init`` locally before
+deploying it to the cloud. Fortunately, there are several different virtual
+machines (VMs) and container tools that are ideal for this sort of local
+testing.
+
+In this guide, we will show how to use three of the most popular tools:
+`Multipass`_, `LXD`_ and `QEMU`_.
+
+Multipass
+=========
+
+Multipass is a cross-platform tool for launching Ubuntu VMs across Linux,
+Windows, and macOS.
+
+When a user launches a Multipass VM, user data can be passed by adding the
+``--cloud-init`` flag and the appropriate YAML file containing the user data:
+
+.. code-block:: shell-session
+
+ $ multipass launch bionic --name test-vm --cloud-init userdata.yaml
+
+Multipass will validate the YAML syntax of the cloud-config file before
+attempting to start the VM! A nice addition which saves time when you're
+experimenting and launching instances with various cloud-configs.
+
+Multipass *only* supports passing user data, and *only* as YAML cloud-config
+files. Passing a script, a MIME archive, or any of the other user data formats
+``cloud-init`` supports will result in an error from the YAML syntax validator.
+
+LXD
+===
+
+LXD offers a streamlined user experience for using Linux system containers.
+With LXD, a user can pass:
+
+* user data,
+* vendor data,
+* metadata, and
+* network configuration.
+
+The following command initialises a container with user data:
+
+.. code-block:: shell-session
+
+ $ lxc init ubuntu-daily:bionic test-container
+ $ lxc config set test-container user.user-data - < userdata.yaml
+ $ lxc start test-container
+
+To avoid the extra commands this can also be done at launch:
+
+.. code-block:: shell-session
+
+ $ lxc launch ubuntu-daily:bionic test-container --config=user.user-data="$(cat userdata.yaml)"
+
+Finally, a profile can be set up with the specific data if you need to
+launch this multiple times:
+
+.. code-block:: shell-session
+
+ $ lxc profile create dev-user-data
+ $ lxc profile set dev-user-data user.user-data - < cloud-init-config.yaml
+ $ lxc launch ubuntu-daily:bionic test-container -p default -p dev-user-data
+
+The above examples all show how to pass user data. To pass other types of
+configuration data use the config option specified below:
+
++----------------+---------------------------+
+| Data | Config option |
++================+===========================+
+| user data | cloud-init.user-data |
++----------------+---------------------------+
+| vendor data | cloud-init.vendor-data |
++----------------+---------------------------+
+| network config | cloud-init.network-config |
++----------------+---------------------------+
+
+See the LXD `Instance Configuration`_ docs for more info about configuration
+values or the LXD `Custom Network Configuration`_ document for more about
+custom network config.
+
+QEMU
+====
+
+The :command:`cloud-localds` command from the `cloud-utils`_ package generates
+a disk with user-supplied data. The ``NoCloud`` datasouce allows users to
+provide their own user data, metadata, or network configuration directly to
+an instance without running a network service. This is helpful for launching
+local cloud images with QEMU, for example.
+
+The following is an example of creating the local disk using the
+:command:`cloud-localds` command:
+
+.. code-block:: shell-session
+
+ $ cat >user-data <<EOF
+ #cloud-config
+ password: password
+ chpasswd:
+ expire: False
+ ssh_pwauth: True
+ ssh_authorized_keys:
+ - ssh-rsa AAAA...UlIsqdaO+w==
+ EOF
+ $ cloud-localds seed.img user-data
+
+The resulting :file:`seed.img` can then be passed along to a cloud image
+containing ``cloud-init``. Below is an example of passing the :file:`seed.img`
+with QEMU:
+
+.. code-block:: shell-session
+
+ $ qemu-system-x86_64 -m 1024 -net nic -net user \
+ -hda ubuntu-20.04-server-cloudimg-amd64.img \
+ -hdb seed.img
+
+The now-booted image will allow for login using the password provided above.
+
+For additional configuration, users can provide much more detailed
+configuration, including network configuration and metadata:
+
+.. code-block:: shell-session
+
+ $ cloud-localds --network-config=network-config-v2.yaml \
+ seed.img userdata.yaml metadata.yaml
+
+See the :ref:`network_config_v2` page for details on the format and config of
+network configuration. To learn more about the possible values for metadata,
+check out the :ref:`datasource_nocloud` page.
+
+
+.. _Multipass: https://multipass.run/
+.. _LXD: https://linuxcontainers.org/
+.. _QEMU: https://www.qemu.org/
+.. _Instance Configuration: https://linuxcontainers.org/lxd/docs/master/instances
+.. _Custom Network Configuration: https://linuxcontainers.org/lxd/docs/master/cloud-init
+.. _cloud-utils: https://github.com/canonical/cloud-utils/
diff --git a/doc/rtd/index.rst b/doc/rtd/index.rst
index c660c02b..1d581129 100644
--- a/doc/rtd/index.rst
+++ b/doc/rtd/index.rst
@@ -1,109 +1,90 @@
.. _index:
-cloud-init documentation
+Cloud-init documentation
########################
-Cloud-init is the *industry standard* multi-distribution method for
-cross-platform cloud instance initialization. It is supported across all major
+``Cloud-init`` is the *industry standard* multi-distribution method for
+cross-platform cloud instance initialisation. It is supported across all major
public cloud providers, provisioning systems for private cloud infrastructure,
and bare-metal installations.
-During boot, cloud-init identifies the cloud it is running on and initializes
-the system accordingly. Cloud instances will automatically be provisioned
-during first boot with networking, storage, SSH keys, packages and various
-other system aspects already configured.
+During boot, ``cloud-init`` identifies the cloud it is running on and
+initialises the system accordingly. Cloud instances will automatically be
+provisioned during first boot with networking, storage, SSH keys, packages
+and various other system aspects already configured.
-Cloud-init provides the necessary glue between launching a cloud instance and
-connecting to it so that it works as expected.
+``Cloud-init`` provides the necessary glue between launching a cloud instance
+and connecting to it so that it works as expected.
-For cloud users, cloud-init provides no-install first-boot configuration
+For cloud users, ``cloud-init`` provides no-install first-boot configuration
management of a cloud instance. For cloud providers, it provides instance setup
that can be integrated with your cloud.
-Project and community
-*********************
-Cloud-init is an open source project that warmly welcomes community
-projects, contributions, suggestions, fixes and constructive feedback.
+-----
-* Read our `Code of conduct`_
-* Ask questions in the ``#cloud-init`` `IRC channel on Libera`_
-* Join the `cloud-init mailing list`_
-* :ref:`Contribute on Github<contributing>`
-* `Release schedule`_
+.. grid:: 1 1 2 2
+ :gutter: 3
-Having trouble? We would like to help!
-**************************************
+ .. grid-item-card:: **Tutorials**
+ :link: tutorial/index
+ :link-type: doc
-- Check out the :ref:`tutorial_lxd` if you're new to cloud-init
-- Try the :ref:`FAQ` for answers to some common questions
-- You can also search the cloud-init `mailing list archive`_
-- Find a bug? `Report bugs on Launchpad`_
+ Get started - a hands-on introduction to ``cloud-init`` for new users
-.. toctree::
- :hidden:
- :titlesonly:
- :caption: Getting Started
+ .. grid-item-card:: **How-to guides**
+ :link: howto/index
+ :link-type: doc
- topics/tutorials/lxd.rst
- topics/availability.rst
- topics/boot.rst
- topics/cli.rst
- topics/faq.rst
- topics/bugs.rst
+ Step-by-step guides covering key operations and common tasks
-.. toctree::
- :hidden:
- :titlesonly:
- :caption: Explanation
+ .. grid-item-card:: **Explanation**
+ :link: explanation/index
+ :link-type: doc
- topics/configuration.rst
+ Discussion and clarification of key topics
-.. toctree::
- :hidden:
- :titlesonly:
- :caption: User Data
+ .. grid-item-card:: **Reference**
+ :link: reference/index
+ :link-type: doc
- topics/format.rst
- topics/examples.rst
- topics/events.rst
- topics/merging.rst
+ Technical information - specifications, APIs, architecture
-.. toctree::
- :hidden:
- :titlesonly:
- :caption: Instance Data
+-----
- topics/instancedata.rst
- topics/datasources.rst
- topics/vendordata.rst
- topics/network-config.rst
+Having trouble? We would like to help!
+======================================
-.. toctree::
- :hidden:
- :titlesonly:
- :caption: Reference
+- :ref:`Check out our tutorials<tutorial_index>` if you're new to
+ ``cloud-init``
+- :ref:`Try the FAQ<faq>` for answers to some common questions
+- You can also search the ``cloud-init`` `mailing list archive`_
+- Find a bug? `Report bugs on Launchpad`_
+
+Project and community
+=====================
+
+``Cloud-init`` is an open source project that warmly welcomes community
+projects, contributions, suggestions, fixes and constructive feedback.
- topics/base_config_reference.rst
- topics/modules.rst
+* Read our `Code of Conduct`_
+* Ask questions in the ``#cloud-init`` `IRC channel on Libera`_
+* Join the `cloud-init mailing list`_
+* :ref:`Contribute on GitHub<contributing>`
+* `Release schedule`_
.. toctree::
:hidden:
- :titlesonly:
- :caption: Development
-
- topics/contributing.rst
- topics/module_creation.rst
- topics/code_review.rst
- topics/security.rst
- topics/debugging.rst
- topics/logging.rst
- topics/dir_layout.rst
- topics/analyze.rst
- topics/docs.rst
- topics/testing.rst
- topics/integration_tests.rst
+ :maxdepth: 2
+
+ tutorial/index
+ howto/index
+ explanation/index
+ reference/index
+ development/index
+
+
.. LINKS
-.. _Code of conduct: https://ubuntu.com/community/code-of-conduct
+.. _Code of Conduct: https://ubuntu.com/community/code-of-conduct
.. _IRC channel on Libera: https://kiwiirc.com/nextclient/irc.libera.chat/cloud-init
.. _cloud-init mailing list: https://launchpad.net/~cloud-init
.. _mailing list archive: https://lists.launchpad.net/cloud-init/
diff --git a/doc/rtd/topics/availability.rst b/doc/rtd/reference/availability.rst
index bf4de71d..b70342a5 100644
--- a/doc/rtd/topics/availability.rst
+++ b/doc/rtd/reference/availability.rst
@@ -3,19 +3,19 @@
Availability
************
-Below outlines the current availability of cloud-init across
+Below outlines the current availability of ``cloud-init`` across
distributions and clouds, both public and private.
.. note::
- If a distribution or cloud does not show up in the list below contact
- them and ask for images to be generated using cloud-init!
+ If a distribution or cloud does not show up in the list below, contact
+ them and ask for images to be generated using ``cloud-init``!
Distributions
=============
-Cloud-init has support across all major Linux distributions, FreeBSD, NetBSD,
-OpenBSD and DragonFlyBSD:
+``Cloud-init`` has support across all major Linux distributions, FreeBSD,
+NetBSD, OpenBSD and DragonFlyBSD:
- Alpine Linux
- Arch Linux
@@ -34,7 +34,7 @@ OpenBSD and DragonFlyBSD:
Clouds
======
-Cloud-init provides support across a wide ranging list of execution
+``Cloud-init`` provides support across a wide ranging list of execution
environments in the public cloud:
- Amazon Web Services
@@ -62,7 +62,7 @@ environments in the public cloud:
- Zadara Edge Cloud Platform
- 3DS Outscale
-Additionally, cloud-init is supported on these private clouds:
+Additionally, ``cloud-init`` is supported on these private clouds:
- Bare metal installs
- OpenStack
@@ -70,5 +70,3 @@ Additionally, cloud-init is supported on these private clouds:
- KVM
- Metal-as-a-Service (MAAS)
- VMware
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/base_config_reference.rst b/doc/rtd/reference/base_config_reference.rst
index 97abcff5..928efc55 100644
--- a/doc/rtd/topics/base_config_reference.rst
+++ b/doc/rtd/reference/base_config_reference.rst
@@ -1,19 +1,18 @@
.. _base_config_reference:
-Base Configuration
+Base configuration
******************
.. warning::
- This documentation is intended for custom image creators, such as
- distros and cloud providers, not
- end users. Modifying the base configuration should not be necessary for
- end users and can result in a system that may be unreachable or
- may no longer boot.
+ This documentation is intended for custom image creators, such as distros
+ and cloud providers, not end users. Modifying the base configuration
+ should not be necessary for end users and can result in a system that may
+ be unreachable or may no longer boot.
-Cloud-init base config is primarily defined in two places:
+``Cloud-init`` base config is primarily defined in two places:
-* **/etc/cloud/cloud.cfg**
-* **/etc/cloud/cloud.cfg.d/*.cfg**
+* :file:`/etc/cloud/cloud.cfg`
+* :file:`/etc/cloud/cloud.cfg.d/*.cfg`
See the :ref:`configuration sources explanation<configuration>` for more
information on how these files get sourced and combined with other
@@ -22,34 +21,33 @@ configuration.
Generation
==========
-``cloud.cfg`` isn't present in any of cloud-init's source files. The
-`configuration is templated`_ and customized for each
-distribution supported by cloud-init.
+:file:`cloud.cfg` isn't present in any of ``cloud-init``'s source files. The
+`configuration is templated`_ and customised for each
+distribution supported by ``cloud-init``.
-Base Configuration Keys
+Base configuration keys
=======================
-Module Keys
+Module keys
-----------
Modules are grouped into the following keys:
-* **cloud_init_modules**: Modules run during
- :ref:`network<topics/boot:network>` timeframe.
-* **cloud_config_modules**: Modules run during
- :ref:`config<topics/boot:config>` timeframe.
-* **cloud_final_modules**: Modules run during
- :ref:`final<topics/boot:final>` timeframe.
+* ``cloud_init_modules``: Modules run during :ref:`network<boot-Network>`
+ timeframe.
+* ``cloud_config_modules``: Modules run during :ref:`config<boot-Config>`
+ timeframe.
+* ``cloud_final_modules``: Modules run during :ref:`final<boot-Final>`
+ timeframe.
-Each ``modules`` definition contains an array of strings, where each string
-is the name of the module. Each name is taken directly from the
-module filename,
-with the ``cc_`` prefix and ``.py`` suffix removed, and with
-``-`` and ``_`` being interchangeable.
+Each ``module`` definition contains an array of strings, where each string
+is the name of the module. Each name is taken directly from the module
+filename, with the ``cc_`` prefix and ``.py`` suffix removed, and with ``-``
+and ``_`` being interchangeable.
Alternatively, in place of the module name, an array of
-`<name>, <frequency>[, <args>]` args may be specified. See
-:ref:`the module creation guidelines<topics/module_creation:guidelines>` for
+``<name>, <frequency>[, <args>]`` args may be specified. See
+:ref:`the module creation guidelines<module_creation-Guidelines>` for
more information on ``frequency`` and ``args``.
.. note::
@@ -58,10 +56,9 @@ more information on ``frequency`` and ``args``.
frequency is **not** a recommended way to reduce instance boot time.
Examples
-^^^^^^^^
+--------
-To specify that only `cc_final_message.py`_ run during final
-timeframe:
+To specify that only `cc_final_message.py`_ run during final timeframe:
.. code-block:: yaml
@@ -83,9 +80,9 @@ user data):
cloud_final_modules:
- [final_message, once, "my final message"]
-.. _datasource_base_config:
+.. _base_config-Datasource:
-Datasource Keys
+Datasource keys
---------------
Many datasources allow configuration of the datasource for use in
@@ -100,126 +97,157 @@ generally take the form of:
<datasource_name>:
...
-System Info Keys
+System info keys
----------------
-These keys are used for setup of cloud-init itself, or the datasource
-or distro. Anything under the ``system_info`` cannot be overridden by
-vendor data, user data, or any other handlers or transforms. In some cases,
-there may be a ``system_info`` key used for the distro, while the same
-key is used outside of ``system_info`` for a userdata module.
+
+These keys are used for setup of ``cloud-init`` itself, or the datasource
+or distro. Anything under ``system_info`` cannot be overridden by vendor data,
+user data, or any other handlers or transforms. In some cases there may be a
+``system_info`` key used for the distro, while the same key is used outside of
+``system_info`` for a user data module.
Both keys will be processed independently.
-* **system_info**: Top-level key
+* ``system_info``: Top-level key.
- - **paths**: Definitions of common paths used by cloud-init
+ - ``paths``: Definitions of common paths used by ``cloud-init``.
- + **cloud_dir**: Defaults to ``/var/lib/cloud``
- + **templates_dir**: Defaults to ``/etc/cloud/templates``
+ + ``cloud_dir``: Defaults to :file:`/var/lib/cloud`.
+ + ``templates_dir``: Defaults to :file:`/etc/cloud/templates`.
- - **distro**: Name of distro being used.
- - **default_user**: Defines the default user for the system using the same
- user configuration as :ref:`topics/modules:users and groups`. Note that
+ - ``distro``: Name of distro being used.
+ - ``default_user``: Defines the default user for the system using the same
+ user configuration as :ref:`Users and Groups<mod-users_groups>`. Note that
this CAN be overridden if a ``users`` configuration
is specified without a ``- default`` entry.
- - **ntp_client**: The default ntp client for the distro. Takes the same
- form as ``ntp_client`` defined in :ref:`topics/modules:ntp`.
- - **package_mirrors**: Defines the package mirror info for apt.
- - **ssh_svcname**: The ssh service name. For most distros this will be
+ - ``ntp_client``: The default NTP client for the distro. Takes the same
+ form as ``ntp_client`` defined in :ref:`NTP<mod-ntp>`.
+ - ``package_mirrors``: Defines the package mirror info for apt.
+ - ``ssh_svcname``: The SSH service name. For most distros this will be
either ``ssh`` or ``sshd``.
- - **network**: Top-level key for distro-specific networking configuration
+ - ``network``: Top-level key for distro-specific networking configuration.
- + **renderers**: Prioritized list of networking configurations to try
+ + ``renderers``: Prioritised list of networking configurations to try
on this system. The first valid entry found will be used.
Options are:
- * **eni** - For /etc/network/interfaces
- * **network-manager**
- * **netplan**
- * **networkd** - For systemd-networkd
- * **freebsd**
- * **netbsd**
- * **openbsd**
+ * ``eni``: For :file:`/etc/network/interfaces`.
+ * ``network-manager``
+ * ``netplan``
+ * ``networkd``: For ``systemd-networkd``.
+ * ``freebsd``
+ * ``netbsd``
+ * ``openbsd``
- + **activators**: Prioritized list of networking tools to try to activate
+ + ``activators``: Prioritised list of networking tools to try to activate
network on this system. The first valid entry found will be used.
Options are:
- * **eni** - For ``ifup``/``ifdown``
- * **netplan** - For ``netplan generate``/``netplan apply``
- * **network-manager** - For ``nmcli connection load``/
- ``nmcli connection up``
- * **networkd** - For ``ip link set up``/``ip link set down``
+ * ``eni``: For ``ifup``/``ifdown``.
+ * ``netplan``: For ``netplan generate``/``netplan apply``.
+ * ``network-manager``: For ``nmcli connection load``/
+ ``nmcli connection up``.
+ * ``networkd``: For ``ip link set up``/``ip link set down``.
-Logging Keys
+Logging keys
------------
See :ref:`the logging explanation<logging>` for a comprehensive
-logging explanation. Note that cloud-init has a default logging
-definition that shouldn't need to be altered. It is defined on the
-instance at ``/etc/cloud/cloud.cfg.d/05_logging.cfg``.
+logging explanation. Note that ``cloud-init`` has a default logging
+definition that shouldn't need to be altered. It is defined in this
+instance at :file:`/etc/cloud/cloud.cfg.d/05_logging.cfg`.
The logging keys used in the base configuration are as follows:
-**logcfg**: A standard python `fileConfig`_ formatted log configuration.
+``logcfg``
+^^^^^^^^^^
+
+A standard python `fileConfig`_ formatted log configuration.
This is the primary logging configuration key and will take precedence over
-**log_cfgs** or **log_basic** keys.
+``log_cfgs`` or ``log_basic`` keys.
+
+``log_cfgs``
+^^^^^^^^^^^^
-**log_cfgs**: A list of logging configs in `fileConfig`_ format to apply
-when running cloud-init. Note that **log_cfgs** is used in
-``/etc/cloud.cfg.d/05_logging.cfg``.
+A list of logging configs in `fileConfig`_ format to apply
+when running ``cloud-init``. Note that ``log_cfgs`` is used in
+:file:`/etc/cloud.cfg.d/05_logging.cfg`.
-**log_basic**: Boolean value to determine if cloud-init should apply a
+``log_basic``
+^^^^^^^^^^^^^
+
+Boolean value to determine if ``cloud-init`` should apply a
basic default logging configuration if none has been provided. Defaults
-to ``true`` but only takes effect if **logcfg** or **log_cfgs** hasn't
+to ``true`` but only takes effect if ``logcfg`` or ``log_cfgs`` hasn't
been defined.
-**output**: If and how to redirect stdout/stderr. Defined in
-``/etc/cloud.cfg.d/05_logging.cfg`` and explained in
+``output``
+^^^^^^^^^^
+
+If and how to redirect ``stdout``/``stderr``. Defined in
+:file:`/etc/cloud.cfg.d/05_logging.cfg` and explained in
:ref:`the logging explanation<logging_command_output>`.
-**syslog_fix_perms**: Takes a list of ``<owner:group>`` strings and will set
-the owner of **def_log_file** accordingly.
+``syslog_fix_perms``
+^^^^^^^^^^^^^^^^^^^^
+
+Takes a list of ``<owner:group>`` strings and will set the owner of
+``def_log_file`` accordingly.
-**def_log_file**: Only used in conjunction with **syslog_fix_perms**.
+``def_log_file``
+^^^^^^^^^^^^^^^^
+
+Only used in conjunction with ``syslog_fix_perms``.
Specifies the filename to be used for setting permissions. Defaults
-to ``/var/log/cloud-init.log``.
+to :file:`/var/log/cloud-init.log`.
-Other Keys
+Other keys
----------
-**network**: The :ref:`network_config` to be applied to this instance.
+``network``
+^^^^^^^^^^^
+
+The :ref:`network configuration<network_config>` to be applied to this
+instance.
+
+``datasource_pkg_list``
+^^^^^^^^^^^^^^^^^^^^^^^
-**datasource_pkg_list**: Prioritized list of python packages to search when
-finding a datasource. Automatically includes ``cloudinit.sources``.
+Prioritised list of python packages to search when finding a datasource.
+Automatically includes ``cloudinit.sources``.
-**datasource_list**: Prioritized list of datasources that cloud-init will
-attempt to find on boot. By default, this will be defined in
-``/etc/cloud/cloud.cfg.d``. There are two primary use cases for modifying
-the datasource_list:
+``datasource_list``
+^^^^^^^^^^^^^^^^^^^
-1. Remove known invalid datasources. This may avoid long timeouts attempting
- to detect datasources on any system without a systemd-generator hook
- that invokes ds-identify.
+Prioritised list of datasources that ``cloud-init`` will attempt to find on
+boot. By default, this will be defined in :file:`/etc/cloud/cloud.cfg.d`. There
+are two primary use cases for modifying the ``datasource_list``:
+
+1. Remove known invalid datasources. This may avoid long timeouts when
+ attempting to detect datasources on any system without a systemd-generator
+ hook that invokes ``ds-identify``.
2. Override default datasource ordering to discover a different datasource
- type than would typically be prioritized.
+ type than would typically be prioritised.
+
+If ``datasource_list`` has only a single entry (or a single entry + ``None``),
+:ref:`cloud-init's generator script<boot-Generator>` will automatically assume
+and use this datasource without attempting detection.
-If **datasource_list** has only a single entry (or a single entry + ``None``),
-:ref:`cloud-init's generator script<topics/boot:generator>`
-will automatically assume and use this datasource without
-attempting detection.
+``vendor_data``/``vendor_data2``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-**vendor_data**/**vendor_data2**: Allows the user to disable ``vendor_data``
-or ``vendor_data2`` along with providing a prefix for any executed scripts.
+Allows the user to disable ``vendor_data`` or ``vendor_data2`` along with
+providing a prefix for any executed scripts.
Format is a dict with ``enabled`` and ``prefix`` keys:
-* **enabled**: Boolean indicating whether to enable or disable the vendor_data
-* **prefix**: A path to prepend to any vendor_data provided script
+* ``enabled``: A boolean indicating whether to enable or disable the
+ ``vendor_data``.
+* ``prefix``: A path to prepend to any ``vendor_data``-provided script.
Example
=======
-On an ubuntu system, ``/etc/cloud/cloud.cfg`` should look similar to:
+On an Ubuntu system, :file:`/etc/cloud/cloud.cfg` should look similar to:
.. code-block:: yaml
diff --git a/doc/rtd/reference/cli.rst b/doc/rtd/reference/cli.rst
new file mode 100644
index 00000000..a4b41315
--- /dev/null
+++ b/doc/rtd/reference/cli.rst
@@ -0,0 +1,414 @@
+.. _cli:
+
+CLI commands
+************
+
+For the latest list of subcommands and arguments use ``cloud-init``'s
+``--help`` option. This can be used against ``cloud-init`` itself, or on any
+of its subcommands.
+
+.. code-block:: shell-session
+
+ $ cloud-init --help
+
+Example output:
+
+.. code-block::
+
+ usage: cloud-init [-h] [--version] [--file FILES] [--debug] [--force]
+ {init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status,schema} ...
+
+ options:
+ -h, --help show this help message and exit
+ --version, -v Show program's version number and exit.
+ --file FILES, -f FILES
+ Use additional yaml configuration files.
+ --debug, -d Show additional pre-action logging (default: False).
+ --force Force running even if no datasource is found (use at your own risk).
+
+ Subcommands:
+ {init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status,schema}
+ init Initialize cloud-init and perform initial modules.
+ modules Activate modules using a given configuration key.
+ single Run a single module.
+ query Query standardized instance metadata from the command line.
+ dhclient-hook Run the dhclient hook to record network info.
+ features List defined features.
+ analyze Devel tool: Analyze cloud-init logs and data.
+ devel Run development tools.
+ collect-logs Collect and tar all cloud-init debug info.
+ clean Remove logs and artifacts so cloud-init can re-run.
+ status Report cloud-init status or wait on completion.
+ schema Validate cloud-config files using jsonschema.
+
+
+The rest of this document will give an overview of each of the subcommands.
+
+.. _cli_analyze:
+
+:command:`analyze`
+==================
+
+Get detailed reports of where ``cloud-init`` spends its time during the boot
+process. For more complete reference see :ref:`analyze`.
+
+Possible subcommands include:
+
+* :command:`blame`: report ordered by most costly operations.
+* :command:`dump`: machine-readable JSON dump of all ``cloud-init`` tracked
+ events.
+* :command:`show`: show time-ordered report of the cost of operations during
+ each boot stage.
+* :command:`boot`: show timestamps from kernel initialisation, kernel finish
+ initialisation, and ``cloud-init`` start.
+
+.. _cli_clean:
+
+:command:`clean`
+================
+
+Remove ``cloud-init`` artifacts from :file:`/var/lib/cloud` to simulate a clean
+instance. On reboot, ``cloud-init`` will re-run all stages as it did on
+first boot.
+
+* :command:`--logs`: Optionally remove all ``cloud-init`` log files in
+ :file:`/var/log/`.
+* :command:`--reboot`: Reboot the system after removing artifacts.
+* :command:`--machine-id`: Remove :file:`/etc/machine-id` on this image. Best
+ practice when cloning a golden image, to ensure that the next boot of that
+ image auto-generates a unique machine ID. `More details on machine-id`_.
+
+.. _cli_collect_logs:
+
+:command:`collect-logs`
+=======================
+
+Collect and tar ``cloud-init``-generated logs, data files, and system
+information for triage. This subcommand is integrated with apport.
+
+Logs collected include:
+
+* :file:`/var/log/cloud-init.log`
+* :file:`/var/log/cloud-init-output.log`
+* :file:`/run/cloud-init`
+* :file:`/var/lib/cloud/instance/user-data.txt`
+* ``cloud-init`` package version
+* ``dmesg`` output
+* ``journalctl`` output
+
+.. note::
+ Ubuntu users can file bugs using :command:`ubuntu-bug cloud-init` to
+ automatically attach these logs to a bug report.
+
+.. _cli_devel:
+
+:command:`devel`
+================
+
+Collection of development tools under active development. These tools will
+likely be promoted to top-level subcommands when stable.
+
+Do **NOT** rely on the output of these commands as they can and will change.
+
+Current subcommands:
+
+:command:`net-convert`
+----------------------
+
+Manually use ``cloud-init``'s network format conversion. Useful for testing
+configuration or testing changes to the network conversion logic itself.
+
+:command:`render`
+-----------------
+
+Use ``cloud-init``'s jinja template render to process **#cloud-config** or
+**custom-scripts**, injecting any variables from
+:file:`/run/cloud-init/instance-data.json`. It accepts a user data file
+containing the jinja template header ``## template: jinja`` and renders that
+content with any :file:`instance-data.json` variables present.
+
+:command:`hotplug-hook`
+-----------------------
+
+Respond to newly added system devices by retrieving updated system metadata
+and bringing up/down the corresponding device. This command is intended to be
+called via a ``systemd`` service and is not considered user-accessible except
+for debugging purposes.
+
+.. _cli_features:
+
+:command:`features`
+===================
+
+Print out each feature supported. If ``cloud-init`` does not have the
+:command:`features` subcommand, it also does not support any features
+described in this document.
+
+.. code-block:: shell-session
+
+ $ cloud-init features
+
+Example output:
+
+.. code-block::
+
+ NETWORK_CONFIG_V1
+ NETWORK_CONFIG_V2
+
+
+.. _cli_init:
+
+:command:`init`
+===============
+
+Generally run by OS init systems to execute ``cloud-init``'s stages:
+*init* and *init-local*. See :ref:`boot_stages` for more info.
+Can be run on the commandline, but is generally gated to run only once
+due to semaphores in :file:`/var/lib/cloud/instance/sem/` and
+:file:`/var/lib/cloud/sem`.
+
+* :command:`--local`: Run *init-local* stage instead of *init*.
+
+.. _cli_modules:
+
+:command:`modules`
+==================
+
+Generally run by OS init systems to execute ``modules:config`` and
+``modules:final`` boot stages. This executes cloud config :ref:`modules`
+configured to run in the Init, Config and Final stages. The modules are
+declared to run in various boot stages in the file
+:file:`/etc/cloud/cloud.cfg` under keys:
+
+* ``cloud_init_modules``
+* ``cloud_config_modules``
+* ``cloud_final_modules``
+
+Can be run on the command line, but each module is gated to run only once due
+to semaphores in :file:`/var/lib/cloud/`.
+
+* :command:`--mode [init|config|final]`: Run ``modules:init``,
+ ``modules:config`` or ``modules:final`` ``cloud-init`` stages.
+ See :ref:`boot_stages` for more info.
+
+.. _cli_query:
+
+:command:`query`
+================
+
+Query standardised cloud instance metadata crawled by ``cloud-init`` and stored
+in :file:`/run/cloud-init/instance-data.json`. This is a convenience
+command-line interface to reference any cached configuration metadata that
+``cloud-init`` crawls when booting the instance. See :ref:`instance_metadata`
+for more info.
+
+* :command:`--all`: Dump all available instance data as JSON which can be
+ queried.
+* :command:`--instance-data`: Optional path to a different
+ :file:`instance-data.json` file to source for queries.
+* :command:`--list-keys`: List available query keys from cached instance data.
+* :command:`--format`: A string that will use jinja-template syntax to render a
+ string replacing.
+* :command:`<varname>`: A dot-delimited variable path into the
+ :file:`instance-data.json` object.
+
+Below demonstrates how to list all top-level query keys that are standardised
+aliases:
+
+.. code-block:: shell-session
+
+ $ cloud-init query --list-keys
+
+Example output:
+
+.. code-block::
+
+ _beta_keys
+ availability_zone
+ base64_encoded_keys
+ cloud_name
+ ds
+ instance_id
+ local_hostname
+ platform
+ public_ssh_keys
+ region
+ sensitive_keys
+ subplatform
+ userdata
+ v1
+ vendordata
+
+Here are a few examples of how to query standardised metadata from clouds:
+
+.. code-block:: shell-session
+
+ $ cloud-init query v1.cloud_name
+
+Example output:
+
+.. code-block::
+
+ aws # or openstack, azure, gce etc.
+
+Any standardised ``instance-data`` under a <v#> key is aliased as a top-level
+key for convenience:
+
+.. code-block:: shell-session
+
+ $ cloud-init query cloud_name
+
+Example output:
+
+.. code-block::
+
+ aws # or openstack, azure, gce etc.
+
+One can also query datasource-specific metadata on EC2, e.g.:
+
+.. code-block:: shell-session
+
+ $ cloud-init query ds.meta_data.public_ipv4
+
+
+.. note::
+
+ The standardised instance data keys under **v#** are guaranteed not to
+ change behaviour or format. If using top-level convenience aliases for any
+ standardised instance data keys, the most value (highest **v#**) of that key
+ name is what is reported as the top-level value. So these aliases act as a
+ 'latest'.
+
+This data can then be formatted to generate custom strings or data. For
+example, we can generate a custom hostname FQDN based on ``instance-id``, cloud
+and region:
+
+.. code-block:: shell-session
+
+ $ cloud-init query --format 'custom-{{instance_id}}.{{region}}.{{v1.cloud_name}}.com'
+
+.. code-block::
+
+ custom-i-0e91f69987f37ec74.us-east-2.aws.com
+
+
+.. _cli_schema:
+
+:command:`schema`
+=================
+
+Validate cloud-config files using jsonschema.
+
+* :command:`-h, --help`: Show this help message and exit.
+* :command:`-c CONFIG_FILE, --config-file CONFIG_FILE`: Path of the
+ cloud-config YAML file to validate.
+* :command:`--system`: Validate the system cloud-config user data.
+* :command:`-d DOCS [cc_module ...], --docs DOCS [cc_module ...]`:
+ Print schema module
+ docs. Choices are: "all" or "space-delimited" ``cc_names``.
+* :command:`--annotate`: Annotate existing cloud-config file with errors.
+
+The following example checks a config file and annotates the config file with
+errors on :file:`stdout`.
+
+.. code-block:: shell-session
+
+ $ cloud-init schema -c ./config.yml --annotate
+
+
+.. _cli_single:
+
+:command:`single`
+=================
+
+Attempt to run a single, named, cloud config module.
+
+* :command:`--name`: The cloud-config module name to run.
+* :command:`--frequency`: Module frequency for this run.
+ One of (``always``|``once-per-instance``|``once``).
+* :command:`--report`: Enable reporting.
+
+The following example re-runs the ``cc_set_hostname`` module ignoring the
+module default frequency of ``once-per-instance``:
+
+.. code-block:: shell-session
+
+ $ cloud-init single --name set_hostname --frequency always
+
+.. note::
+
+ Mileage may vary trying to re-run each ``cloud-config`` module, as
+ some are not idempotent.
+
+.. _cli_status:
+
+:command:`status`
+=================
+
+Report whether ``cloud-init`` is running, done, disabled or errored. Exits
+non-zero if an error is detected in ``cloud-init``.
+
+* :command:`--long`: Detailed status information.
+* :command:`--wait`: Block until ``cloud-init`` completes.
+* :command:`--format [yaml|json|tabular]`: Machine-readable JSON or YAML
+ detailed output.
+
+The :command:`status` command can be used simply as follows:
+
+.. code-block:: shell-session
+
+ $ cloud-init status
+
+Which shows whether ``cloud-init`` is currently running, done, disabled, or in
+error, as in this example output:
+
+.. code-block::
+
+ status: running
+
+The :command:`--long` option, shown below, provides a more verbose output.
+
+.. code-block:: shell-session
+
+ $ cloud-init status --long
+
+Example output when ``cloud-init`` is running:
+
+.. code-block::
+
+ status: running
+ time: Fri, 26 Jan 2018 21:39:43 +0000
+ detail:
+ Running in stage: init-local
+
+Example output when ``cloud-init`` is done:
+
+.. code-block::
+
+ status: done
+ boot_status_code: enabled-by-generator
+ last_update: Tue, 16 Aug 2022 19:12:58 +0000
+ detail:
+ DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net]
+
+The detailed output can be shown in machine-readable JSON or YAML with the
+:command:`format` option, for example:
+
+.. code-block:: shell-session
+
+ $ cloud-init status --format=json
+
+Which would produce the following example output:
+
+.. code-block::
+
+ {
+ "boot_status_code": "enabled-by-generator",
+ "datasource": "nocloud",
+ "detail": "DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net]",
+ "errors": [],
+ "last_update": "Tue, 16 Aug 2022 19:12:58 +0000",
+ "status": "done"
+ }
+
+.. _More details on machine-id: https://www.freedesktop.org/software/systemd/man/machine-id.html
diff --git a/doc/rtd/reference/datasources.rst b/doc/rtd/reference/datasources.rst
new file mode 100644
index 00000000..6db0053a
--- /dev/null
+++ b/doc/rtd/reference/datasources.rst
@@ -0,0 +1,134 @@
+.. _datasources:
+
+Datasources
+***********
+
+Datasources are sources of configuration data for ``cloud-init`` that typically
+come from the user (i.e., user data) or come from the cloud that created the
+configuration drive (i.e., metadata). Typical user data includes files,
+YAML, and shell scripts whereas typical metadata includes server name,
+instance id, display name, and other cloud specific details.
+
+Since there are multiple ways to provide this data (each cloud solution seems
+to prefer its own way), a datasource abstract class was internally created to
+allow for a single way to access the different cloud systems methods, providing
+this data through the typical usage of subclasses.
+
+Any metadata processed by ``cloud-init``'s datasources is persisted as
+:file:`/run/cloud-init/instance-data.json`. ``Cloud-init`` provides tooling to
+quickly introspect some of that data. See :ref:`instance_metadata` for more
+information.
+
+Known sources
+=============
+
+The following is a list of documents for each supported datasource:
+
+.. toctree::
+ :titlesonly:
+
+ datasources/aliyun.rst
+ datasources/altcloud.rst
+ datasources/ec2.rst
+ datasources/azure.rst
+ datasources/cloudsigma.rst
+ datasources/cloudstack.rst
+ datasources/configdrive.rst
+ datasources/digitalocean.rst
+ datasources/e24cloud.rst
+ datasources/exoscale.rst
+ datasources/fallback.rst
+ datasources/gce.rst
+ datasources/lxd.rst
+ datasources/maas.rst
+ datasources/nocloud.rst
+ datasources/nwcs.rst
+ datasources/opennebula.rst
+ datasources/openstack.rst
+ datasources/oracle.rst
+ datasources/ovf.rst
+ datasources/rbxcloud.rst
+ datasources/smartos.rst
+ datasources/upcloud.rst
+ datasources/vmware.rst
+ datasources/vultr.rst
+ datasources/zstack.rst
+
+Datasource creation
+===================
+
+The datasource objects have a few touch points with ``cloud-init``. If you
+are interested in adding a new datasource for your cloud platform you will
+need to take care of the following items:
+
+Identify a mechanism for positive identification of the platform
+----------------------------------------------------------------
+
+It is good practice for a cloud platform to positively identify itself to
+the guest. This allows the guest to make educated decisions based on the
+platform on which it is running. On the x86 and arm64 architectures, many
+clouds identify themselves through DMI data. For example, Oracle's public
+cloud provides the string ``'OracleCloud.com'`` in the DMI chassis-asset
+field.
+
+``Cloud-init``-enabled images produce a log file with details about the
+platform. Reading through this log in :file:`/run/cloud-init/ds-identify.log`
+may provide the information needed to uniquely identify the platform.
+If the log is not present, you can generate it by running from source
+:file:`./tools/ds-identify` or the installed location
+:file:`/usr/lib/cloud-init/ds-identify`.
+
+The mechanism used to identify the platform will be required for the
+``ds-identify`` and datasource module sections below.
+
+Add datasource module :file:`cloudinit/sources/DataSource<CloudPlatform>.py`
+----------------------------------------------------------------------------
+
+It is suggested that you start by copying one of the simpler datasources
+such as ``DataSourceHetzner``.
+
+Add tests for datasource module
+-------------------------------
+
+Add a new file with some tests for the module to
+:file:`cloudinit/sources/test_<yourplatform>.py`. For example, see
+:file:`cloudinit/sources/tests/test_oracle.py`
+
+Update ``ds-identify``
+----------------------
+
+In ``systemd`` systems, ``ds-identify`` is used to detect which datasource
+should be enabled, or if ``cloud-init`` should run at all. You'll need to
+make changes to :file:`tools/ds-identify`.
+
+Add tests for ``ds-identify``
+-----------------------------
+
+Add relevant tests in a new class to
+:file:`tests/unittests/test_ds_identify.py`. You can use ``TestOracle`` as
+an example.
+
+Add your datasource name to the built-in list of datasources
+------------------------------------------------------------
+
+Add your datasource module name to the end of the ``datasource_list``
+entry in :file:`cloudinit/settings.py`.
+
+Add your cloud platform to apport collection prompts
+----------------------------------------------------
+
+Update the list of cloud platforms in :file:`cloudinit/apport.py`. This list
+will be provided to the user who invokes :command:`ubuntu-bug cloud-init`.
+
+Enable datasource by default in Ubuntu packaging branches
+---------------------------------------------------------
+
+Ubuntu packaging branches contain a template file,
+:file:`debian/cloud-init.templates`, which ultimately sets the default
+``datasource_list`` when installed via package. This file needs updating when
+the commit gets into a package.
+
+Add documentation for your datasource
+-------------------------------------
+
+You should add a new file in :file:`doc/datasources/<cloudplatform>.rst`.
diff --git a/doc/rtd/topics/datasources/aliyun.rst b/doc/rtd/reference/datasources/aliyun.rst
index 32fcb4bc..5121f53d 100644
--- a/doc/rtd/topics/datasources/aliyun.rst
+++ b/doc/rtd/reference/datasources/aliyun.rst
@@ -1,21 +1,24 @@
.. _datasource_aliyun:
Alibaba Cloud (AliYun)
-======================
-The ``AliYun`` datasource reads data from Alibaba Cloud ECS. Support is
-present in cloud-init since 0.7.9.
+**********************
-Metadata Service
-----------------
-The Alibaba Cloud metadata service is available at the well known url
-``http://100.100.100.200/``. For more information see
-Alibaba Cloud ECS on `metadata
-<https://www.alibabacloud.com/help/zh/faq-detail/49122.htm>`__.
+The ``AliYun`` datasource reads data from Alibaba Cloud ECS. Support is
+present in ``cloud-init`` since 0.7.9.
+
+Metadata service
+================
+
+The Alibaba Cloud metadata service is available at the well known URL
+:file:`http://100.100.100.200/`. For more information see Alibaba Cloud ECS
+on `metadata`_.
Configuration
--------------
+=============
+
The following configuration can be set for the datasource in system
-configuration (in ``/etc/cloud/cloud.cfg`` or ``/etc/cloud/cloud.cfg.d/``).
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
An example configuration with the default values is provided below:
@@ -28,15 +31,16 @@ An example configuration with the default values is provided below:
max_wait: 120
Versions
-^^^^^^^^
+--------
+
Like the EC2 metadata service, Alibaba Cloud's metadata service provides
-versioned data under specific paths. As of April 2018, there are only
+versioned data under specific paths. As of April 2018, there are only
``2016-01-01`` and ``latest`` versions.
It is expected that the dated version will maintain a stable interface but
``latest`` may change content at a future date.
-Cloud-init uses the ``2016-01-01`` version.
+``Cloud-init`` uses the ``2016-01-01`` version.
You can list the versions available to your instance with:
@@ -52,9 +56,10 @@ Example output:
latest
Metadata
-^^^^^^^^
+--------
+
Instance metadata can be queried at
-``http://100.100.100.200/2016-01-01/meta-data``:
+:file:`http://100.100.100.200/2016-01-01/meta-data`:
.. code-block:: shell-session
@@ -85,10 +90,11 @@ Example output:
vpc-id
Userdata
-^^^^^^^^
-If provided, user-data will appear at
-``http://100.100.100.200/2016-01-01/user-data``.
-If no user-data is provided, this will return a 404.
+--------
+
+If provided, user data will appear at
+:file:`http://100.100.100.200/2016-01-01/user-data`.
+If no user data is provided, this will return a 404.
.. code-block:: shell-session
@@ -101,4 +107,5 @@ Example output:
#!/bin/sh
echo "Hello World."
-.. vi: textwidth=79
+.. LINKS
+.. _metadata: https://www.alibabacloud.com/help/zh/faq-detail/49122.htm
diff --git a/doc/rtd/topics/datasources/altcloud.rst b/doc/rtd/reference/datasources/altcloud.rst
index b69a3093..19233404 100644
--- a/doc/rtd/topics/datasources/altcloud.rst
+++ b/doc/rtd/reference/datasources/altcloud.rst
@@ -1,24 +1,22 @@
.. _datasource_alt_cloud:
-Alt Cloud
-=========
+AltCloud
+*********
-The datasource altcloud will be used to pick up user data on `RHEVm`_ and
+The datasource AltCloud will be used to pick up user data on `RHEVm`_ and
`vSphere`_.
RHEVm
------
+=====
-For `RHEVm`_ v3.0 the userdata is injected into the VM using floppy
+For `RHEVm`_ v3.0 the user data is injected into the VM using floppy
injection via the `RHEVm`_ dashboard "Custom Properties".
-The format of the Custom Properties entry must be:
-
-::
+The format of the "Custom Properties" entry must be: ::
floppyinject=user-data.txt:<base64 encoded data>
-For example to pass a simple bash script:
+For example, to pass a simple bash script:
.. code-block:: sh
@@ -29,43 +27,42 @@ For example to pass a simple bash script:
$ base64 < simple_script.bash
IyEvYmluL2Jhc2gKZWNobyAiSGVsbG8gSm9lISIgPj4gL3RtcC9KSlZfSm9lX291dC50eHQK
-To pass this example script to cloud-init running in a `RHEVm`_ v3.0 VM
-set the "Custom Properties" when creating the RHEMv v3.0 VM to:
-
-::
+To pass this example script to ``cloud-init`` running in a `RHEVm`_ v3.0 VM
+set the "Custom Properties" when creating the RHEMv v3.0 VM to: ::
floppyinject=user-data.txt:IyEvYmluL2Jhc2gKZWNobyAiSGVsbG8gSm9lISIgPj4gL3RtcC9KSlZfSm9lX291dC50eHQK
-**NOTE:** The prefix with file name must be: ``floppyinject=user-data.txt:``
+.. note::
+ The prefix with file name must be: ``floppyinject=user-data.txt:``
It is also possible to launch a `RHEVm`_ v3.0 VM and pass optional user
-data to it using the Delta Cloud.
-
-For more information on Delta Cloud see: http://deltacloud.apache.org
+data to it using the `Delta Cloud`_.
vSphere
--------
+=======
-For VMWare's `vSphere`_ the userdata is injected into the VM as an ISO
-via the cdrom. This can be done using the `vSphere`_ dashboard
+For VMWare's `vSphere`_ the user data is injected into the VM as an ISO
+via the CD-ROM. This can be done using the `vSphere`_ dashboard
by connecting an ISO image to the CD/DVD drive.
-To pass this example script to cloud-init running in a `vSphere`_ VM
+To pass this example script to ``cloud-init`` running in a `vSphere`_ VM
set the CD/DVD drive when creating the vSphere VM to point to an
ISO on the data store.
-**Note:** The ISO must contain the user data.
+.. note::
+ The ISO must contain the user data.
For example, to pass the same ``simple_script.bash`` to vSphere:
Create the ISO
-^^^^^^^^^^^^^^
+--------------
.. code-block:: sh
$ mkdir my-iso
-NOTE: The file name on the ISO must be: ``user-data.txt``
+.. note::
+ The file name on the ISO must be: ``user-data.txt``
.. code-block:: sh
@@ -73,7 +70,7 @@ NOTE: The file name on the ISO must be: ``user-data.txt``
$ genisoimage -o user-data.iso -r my-iso
Verify the ISO
-^^^^^^^^^^^^^^
+--------------
.. code-block:: sh
@@ -82,13 +79,11 @@ Verify the ISO
$ cat /media/vsphere_iso/user-data.txt
$ sudo umount /media/vsphere_iso
-Then, launch the `vSphere`_ VM the ISO user-data.iso attached as a CDROM.
+Then, launch the `vSphere`_ VM the ISO ``user-data.iso`` attached as a CD-ROM.
It is also possible to launch a `vSphere`_ VM and pass optional user
data to it using the Delta Cloud.
-For more information on Delta Cloud see: http://deltacloud.apache.org
-
.. _RHEVm: https://www.redhat.com/virtualization/rhev/desktop/rhevm/
.. _vSphere: https://www.vmware.com/products/datacenter-virtualization/vsphere/overview.html
-.. vi: textwidth=79
+.. _Delta Cloud: http://deltacloud.apache.org
diff --git a/doc/rtd/reference/datasources/azure.rst b/doc/rtd/reference/datasources/azure.rst
new file mode 100644
index 00000000..5f8f3b84
--- /dev/null
+++ b/doc/rtd/reference/datasources/azure.rst
@@ -0,0 +1,133 @@
+.. _datasource_azure:
+
+Azure
+*****
+
+This datasource finds metadata and user data from the Azure cloud platform.
+
+The Azure cloud platform provides initial data to an instance via an attached
+CD formatted in UDF. This CD contains a :file:`ovf-env.xml` file that
+provides some information. Additional information is obtained via interaction
+with the "endpoint".
+
+IMDS
+====
+
+Azure provides the `instance metadata service (IMDS)`_, which is a REST service
+on ``169.254.169.254`` providing additional configuration information to the
+instance. ``Cloud-init`` uses the IMDS for:
+
+- Network configuration for the instance which is applied per boot.
+- A pre-provisioning gate which blocks instance configuration until Azure
+ fabric is ready to provision.
+- Retrieving SSH public keys. ``Cloud-init`` will first try to utilise SSH
+ keys returned from IMDS, and if they are not provided from IMDS then it will
+ fall back to using the OVF file provided from the CD-ROM. There is a large
+ performance benefit to using IMDS for SSH key retrieval, but in order to
+ support environments where IMDS is not available then we must continue to
+ all for keys from OVF[?]
+
+Configuration
+=============
+
+The following configuration can be set for the datasource in system
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
+
+The settings that may be configured are:
+
+* :command:`apply_network_config`
+
+ Boolean set to True to use network configuration described by Azure's IMDS
+ endpoint instead of fallback network config of DHCP on eth0. Default is
+ True.
+* :command:`data_dir`
+
+ Path used to read metadata files and write crawled data.
+
+* :command:`disk_aliases`
+
+ A dictionary defining which device paths should be interpreted as ephemeral
+ images. See :ref:`cc_disk_setup <mod-disk_setup>` module for more info.
+
+Configuration for the datasource can also be read from a ``dscfg`` entry in
+the ``LinuxProvisioningConfigurationSet``. Content in ``dscfg`` node is
+expected to be base64 encoded YAML content, and it will be merged into the
+``'datasource: Azure'`` entry.
+
+An example configuration with the default values is provided below:
+
+.. code-block:: yaml
+
+ datasource:
+ Azure:
+ apply_network_config: true
+ data_dir: /var/lib/waagent
+ disk_aliases:
+ ephemeral0: /dev/disk/cloud/azure_resource
+
+
+User data
+=========
+
+User data is provided to ``cloud-init`` inside the :file:`ovf-env.xml` file.
+``Cloud-init`` expects that user data will be provided as a base64 encoded
+value inside the text child of an element named ``UserData`` or
+``CustomData``, which is a direct child of the
+``LinuxProvisioningConfigurationSet`` (a sibling to ``UserName``).
+
+If both ``UserData`` and ``CustomData`` are provided, the behaviour is
+undefined on which will be selected. In the example below, user data provided
+is ``'this is my userdata'``.
+
+Example:
+
+.. code-block:: xml
+
+ <wa:ProvisioningSection>
+ <wa:Version>1.0</wa:Version>
+ <LinuxProvisioningConfigurationSet
+ xmlns="http://schemas.microsoft.com/windowsazure"
+ xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
+ <HostName>myHost</HostName>
+ <UserName>myuser</UserName>
+ <UserPassword/>
+ <CustomData>dGhpcyBpcyBteSB1c2VyZGF0YQ===</CustomData>
+ <dscfg>eyJhZ2VudF9jb21tYW5kIjogWyJzdGFydCIsICJ3YWxpbnV4YWdlbnQiXX0=</dscfg>
+ <DisableSshPasswordAuthentication>true</DisableSshPasswordAuthentication>
+ <SSH>
+ <PublicKeys>
+ <PublicKey>
+ <Fingerprint>6BE7A7C3C8A8F4B123CCA5D0C2F1BE4CA7B63ED7</Fingerprint>
+ <Path>this-value-unused</Path>
+ </PublicKey>
+ </PublicKeys>
+ </SSH>
+ </LinuxProvisioningConfigurationSet>
+ </wa:ProvisioningSection>
+
+HostName
+========
+
+When the user launches an instance, they provide a hostname for that instance.
+The hostname is provided to the instance in the :file:`ovf-env.xml` file as
+``HostName``.
+
+Whatever value the instance provides in its DHCP request will resolve in the
+domain returned in the 'search' request.
+
+A generic image will already have a hostname configured. The Ubuntu cloud
+images have ``ubuntu`` as the hostname of the system, and the initial DHCP
+request on eth0 is not guaranteed to occur after the datasource code has been
+run. So, on first boot, that initial value will be sent in the DHCP request
+and *that* value will resolve.
+
+In order to make the ``HostName`` provided in the :file:`ovf-env.xml`
+resolve, a DHCP request must be made with the new value. ``Cloud-init``
+handles this by setting the hostname in the datasource's ``get_data`` method
+via :command:`hostname $HostName`, and then bouncing the interface. This
+behaviour can be configured or disabled in the datasource config. See
+'Configuration' above.
+
+.. _instance metadata service (IMDS): https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service
diff --git a/doc/rtd/reference/datasources/cloudsigma.rst b/doc/rtd/reference/datasources/cloudsigma.rst
new file mode 100644
index 00000000..84c42706
--- /dev/null
+++ b/doc/rtd/reference/datasources/cloudsigma.rst
@@ -0,0 +1,39 @@
+.. _datasource_cloudsigma:
+
+CloudSigma
+**********
+
+This datasource finds metadata and user data from the `CloudSigma`_ cloud
+platform. Data transfer occurs through a virtual serial port of the
+`CloudSigma`_'s VM, and the presence of a network adapter is **NOT** a
+requirement. See `server context`_ in their public documentation for more
+information.
+
+Setting a hostname
+==================
+
+By default, the name of the server will be applied as a hostname on the first
+boot.
+
+Providing user data
+-------------------
+
+You can provide user data to the VM using the dedicated `meta field`_ in the
+`server context`_ ``cloudinit-user-data``. By default, *cloud-config* format
+is expected there, and the ``#cloud-config`` header can be omitted. However,
+since this is a raw-text field you could provide any of the valid `config
+formats`_.
+
+You have the option to encode your user data using Base64. In order to do that
+you have to add the ``cloudinit-user-data`` field to the ``base64_fields``.
+The latter is a comma-separated field with all the meta fields having
+Base64-encoded values.
+
+If your user data does not need an internet connection you can create a
+`meta field`_ in the `server context`_ ``cloudinit-dsmode`` and set "local" as
+the value. If this field does not exist, the default value is "net".
+
+.. _CloudSigma: http://cloudsigma.com/
+.. _server context: http://cloudsigma-docs.readthedocs.org/en/latest/server_context.html
+.. _meta field: http://cloudsigma-docs.readthedocs.org/en/latest/meta.html
+.. _config formats: http://cloudinit.readthedocs.org/en/latest/topics/format.html
diff --git a/doc/rtd/reference/datasources/cloudstack.rst b/doc/rtd/reference/datasources/cloudstack.rst
new file mode 100644
index 00000000..2cf439e1
--- /dev/null
+++ b/doc/rtd/reference/datasources/cloudstack.rst
@@ -0,0 +1,66 @@
+.. _datasource_cloudstack:
+
+CloudStack
+**********
+
+`Apache CloudStack`_ exposes user data, metadata, user password, and account
+SSH key through the ``virtual router``. The datasource obtains the ``virtual
+router`` address via DHCP lease information given to the instance.
+For more details on metadata and user data, refer to the
+`CloudStack Administrator Guide`_.
+
+The following URLs provide to access user data and metadata from the Virtual
+Machine. ``data-server.`` is a well-known hostname provided by the CloudStack
+``virtual router`` that points to the next ``UserData`` server (which is
+usually also the ``virtual router``).
+
+.. code-block:: bash
+
+ http://data-server./latest/user-data
+ http://data-server./latest/meta-data
+ http://data-server./latest/meta-data/{metadata type}
+
+If ``data-server.`` cannot be resolved, ``cloud-init`` will try to obtain the
+``virtual router``'s address from the system's DHCP leases. If that fails,
+it will use the system's default gateway.
+
+Configuration
+=============
+
+The following configuration can be set for the datasource in system
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
+
+The settings that may be configured are:
+
+* :command:`max_wait`
+
+ The maximum amount of clock time in seconds that should be spent searching
+ ``metadata_urls``. A value less than zero will result in only one request
+ being made, to the first in the list.
+
+ Default: 120
+
+* :command:`timeout`
+
+ The timeout value provided to ``urlopen`` for each individual http request.
+ This is used both when selecting a ``metadata_url`` and when crawling
+ the metadata service.
+
+ Default: 50
+
+Example
+-------
+
+An example configuration with the default values is provided below:
+
+.. code-block:: yaml
+
+ datasource:
+ CloudStack:
+ max_wait: 120
+ timeout: 50
+
+
+.. _Apache CloudStack: http://cloudstack.apache.org/
+.. _CloudStack Administrator Guide: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/virtual_machines.html#user-data-and-meta-data
diff --git a/doc/rtd/reference/datasources/configdrive.rst b/doc/rtd/reference/datasources/configdrive.rst
new file mode 100644
index 00000000..17913517
--- /dev/null
+++ b/doc/rtd/reference/datasources/configdrive.rst
@@ -0,0 +1,141 @@
+.. _datasource_config_drive:
+
+Config drive
+************
+
+The configuration drive datasource supports the `OpenStack`_ configuration
+drive disk.
+
+By default, ``cloud-init`` *always* considers this source to be a
+fully-fledged datasource. Instead, the typical behavior is to assume it is
+really only present to provide networking information. ``Cloud-init`` will
+copy the network information, apply it to the system, and then continue on.
+The "full" datasource could then be found in the EC2 metadata service. If
+this is not the case then the files contained on the located drive must
+provide equivalents to what the EC2 metadata service would provide (which is
+typical of the version 2 support listed below).
+
+.. note::
+ See `the config drive extension`_ and `metadata introduction`_ in the
+ public documentation for more information.
+
+.. dropdown:: Version 1 (deprecated)
+
+ **Note: Version 1 is legacy and should be considered deprecated.
+ Version 2 has been supported in OpenStack since 2012.2 (Folsom).**
+
+ The following criteria are required to use a config drive:
+
+ 1. Must be formatted with `vfat`_ filesystem.
+ 2. Must contain *one* of the following files: ::
+
+ /etc/network/interfaces
+ /root/.ssh/authorized_keys
+ /meta.js
+
+ ``/etc/network/interfaces``
+
+ This file is laid down by nova in order to pass static networking
+ information to the guest. ``Cloud-init`` will copy it off of the
+ config-drive and into /etc/network/interfaces (or convert it to RH
+ format) as soon as it can, and then attempt to bring up all network
+ interfaces.
+
+ ``/root/.ssh/authorized_keys``
+
+ This file is laid down by nova, and contains the ssk keys that were
+ provided to nova on instance creation (nova-boot --key ....)
+
+ ``/meta.js``
+
+ meta.js is populated on the config-drive in response to the user
+ passing "meta flags" (nova boot --meta key=value ...). It is
+ expected to be json formatted.
+
+
+Version 2
+=========
+
+The following criteria are required to use a config drive:
+
+1. Must be formatted with `vfat`_ or `iso9660`_ filesystem, or have a
+ *filesystem* label of ``config-2`` or ``CONFIG-2``.
+2. The files that will typically be present in the config drive are: ::
+
+ openstack/
+ - 2012-08-10/ or latest/
+ - meta_data.json
+ - user_data (not mandatory)
+ - content/
+ - 0000 (referenced content files)
+ - 0001
+ - ....
+ ec2
+ - latest/
+ - meta-data.json (not mandatory)
+
+Keys and values
+===============
+
+``Cloud-init``'s behaviour can be modified by keys found in the
+:file:`meta.js` (version 1 only) file in the following ways.
+
+``ds-mode``
+-----------
+
+::
+
+ dsmode:
+ values: local, net, pass
+ default: pass
+
+This is what indicates if config drive is a final datasource or not. By
+default it is 'pass', meaning this datasource should not be read. Set it to
+'local' or 'net' to stop ``cloud-init`` from continuing to search for other
+datasources after network config.
+
+The difference between 'local' and 'net' is that local will not require
+networking to be up before user-data actions (or boothooks) are run.
+
+``instance-id``
+---------------
+
+::
+
+ instance-id:
+ default: iid-dsconfigdrive
+
+This is utilised as the metadata's instance-id. It should generally
+be unique, as it is what is used to determine "is this a new instance?".
+
+``public-keys``
+---------------
+
+::
+
+ public-keys:
+ default: None
+
+If present, these keys will be used as the public keys for the
+instance. This value overrides the content in ``authorized_keys``.
+
+.. note::
+ It is likely preferable to provide keys via user data.
+
+``user-data``
+-------------
+
+::
+
+ user-data:
+ default: None
+
+This provides ``cloud-init`` user data. See :ref:`examples <yaml_examples>`
+for details of what needs to be present here.
+
+.. _OpenStack: http://www.openstack.org/
+.. _metadata introduction: https://docs.openstack.org/nova/latest/user/metadata.html#config-drives
+.. _python-novaclient: https://github.com/openstack/python-novaclient
+.. _iso9660: https://en.wikipedia.org/wiki/ISO_9660
+.. _vfat: https://en.wikipedia.org/wiki/File_Allocation_Table
+.. _the config drive extension: https://docs.openstack.org/nova/latest/admin/config-drive.html
diff --git a/doc/rtd/reference/datasources/digitalocean.rst b/doc/rtd/reference/datasources/digitalocean.rst
new file mode 100644
index 00000000..7283aac1
--- /dev/null
+++ b/doc/rtd/reference/datasources/digitalocean.rst
@@ -0,0 +1,32 @@
+.. _datasource_digital_ocean:
+
+DigitalOcean
+************
+
+The `DigitalOcean`_ datasource consumes the content served from DigitalOcean's
+metadata service. This metadata service serves information about the
+running droplet via http over the link local address ``169.254.169.254``. The
+metadata API endpoints are fully described in the DigitalOcean
+`metadata documentation`_.
+
+Configuration
+=============
+
+DigitalOcean's datasource can be configured as follows: ::
+
+ datasource:
+ DigitalOcean:
+ retries: 3
+ timeout: 2
+
+* ``retries``
+
+ Specifies the number of times to attempt connection to the metadata service.
+
+* ``timeout``
+
+ Specifies the timeout (in seconds) to wait for a response from the
+ metadata service.
+
+.. _DigitalOcean: http://digitalocean.com/
+.. _metadata documentation: https://developers.digitalocean.com/metadata/
diff --git a/doc/rtd/reference/datasources/e24cloud.rst b/doc/rtd/reference/datasources/e24cloud.rst
new file mode 100644
index 00000000..e2c125db
--- /dev/null
+++ b/doc/rtd/reference/datasources/e24cloud.rst
@@ -0,0 +1,10 @@
+.. _datasource_e24cloud:
+
+E24Cloud
+********
+
+`E24Cloud`_ platform provides an AWS EC2 metadata service clone. It identifies
+itself to guests using the DMI system-manufacturer
+(:file:`/sys/class/dmi/id/sys_vendor`).
+
+.. _E24Cloud: https://www.e24cloud.com/en/
diff --git a/doc/rtd/reference/datasources/ec2.rst b/doc/rtd/reference/datasources/ec2.rst
new file mode 100644
index 00000000..7e2b522a
--- /dev/null
+++ b/doc/rtd/reference/datasources/ec2.rst
@@ -0,0 +1,153 @@
+.. _datasource_ec2:
+
+Amazon EC2
+**********
+
+The EC2 datasource is the oldest and most widely used datasource that
+``cloud-init`` supports. This datasource interacts with a *magic* IP provided
+to the instance by the cloud provider (typically this IP is
+``169.254.169.254``). At this IP a http server is provided to the
+instance so that the instance can make calls to get instance user data and
+instance metadata.
+
+Metadata is accessible via the following URL: ::
+
+ GET http://169.254.169.254/2009-04-04/meta-data/
+ ami-id
+ ami-launch-index
+ ami-manifest-path
+ block-device-mapping/
+ hostname
+ instance-id
+ instance-type
+ local-hostname
+ local-ipv4
+ placement/
+ public-hostname
+ public-ipv4
+ public-keys/
+ reservation-id
+ security-groups
+
+User data is accessible via the following URL: ::
+
+ GET http://169.254.169.254/2009-04-04/user-data
+ 1234,fred,reboot,true | 4512,jimbo, | 173,,,
+
+Note that there are multiple EC2 Metadata versions of this data provided
+to instances. ``Cloud-init`` attempts to use the most recent API version it
+supports in order to get the latest API features and instance-data. If a given
+API version is not exposed to the instance, those API features will be
+unavailable to the instance.
+
++----------------+----------------------------------------------------------+
++ EC2 version | supported instance-data/feature |
++================+==========================================================+
++ **2021-03-23** | Required for Instance tag support. This feature must be |
+| | enabled individually on each instance. See the |
+| | `EC2 tags user guide`_. |
++----------------+----------------------------------------------------------+
+| **2016-09-02** | Required for secondary IP address support. |
++----------------+----------------------------------------------------------+
+| **2009-04-04** | Minimum supports EC2 API version for metadata and |
+| | user data. |
++----------------+----------------------------------------------------------+
+
+To see which versions are supported by your cloud provider use the following
+URL: ::
+
+ GET http://169.254.169.254/
+ 1.0
+ 2007-01-19
+ 2007-03-01
+ 2007-08-29
+ 2007-10-10
+ 2007-12-15
+ 2008-02-01
+ 2008-09-01
+ 2009-04-04
+ ...
+ latest
+
+
+Configuration settings
+======================
+
+The following configuration can be set for the datasource in system
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
+
+The settings that may be configured are:
+
+``metadata_urls``
+-----------------
+
+This list of URLs will be searched for an EC2 metadata service. The first
+entry that successfully returns a 200 response for
+``<url>/<version>/meta-data/instance-id`` will be selected.
+
+Default: ['http://169.254.169.254', 'http://[fd00:ec2::254]',
+'http://instance-data:8773'].
+
+``max_wait``
+------------
+
+The maximum amount of clock time in seconds that should be spent searching
+``metadata_urls``. A value less than zero will result in only one request
+being made, to the first in the list.
+
+Default: 120
+
+``timeout``
+-----------
+
+The timeout value provided to ``urlopen`` for each individual http request.
+This is used both when selecting a ``metadata_url`` and when crawling the
+metadata service.
+
+Default: 50
+
+``apply_full_imds_network_config``
+----------------------------------
+
+Boolean (default: True) to allow ``cloud-init`` to configure any secondary
+NICs and secondary IPs described by the metadata service. All network
+interfaces are configured with DHCP (v4) to obtain a primary IPv4 address and
+route. Interfaces which have a non-empty ``ipv6s`` list will also enable
+DHCPv6 to obtain a primary IPv6 address and route. The DHCP response (v4 and
+v6) return an IP that matches the first element of ``local-ipv4s`` and
+``ipv6s`` lists respectively. All additional values (secondary addresses) in
+the static IP lists will be added to the interface.
+
+An example configuration with the default values is provided below:
+
+.. code-block:: yaml
+
+ datasource:
+ Ec2:
+ metadata_urls: ["http://169.254.169.254:80", "http://instance-data:8773"]
+ max_wait: 120
+ timeout: 50
+ apply_full_imds_network_config: true
+
+Notes
+=====
+
+ * There are 2 types of EC2 instances, network-wise: Virtual Private
+ Cloud (VPC) ones and Classic ones (also known as non-VPC). One major
+ difference between them is that Classic instances have their MAC address
+ changed on stop/restart operations, so ``cloud-init`` will recreate the
+ network config file for EC2 Classic instances every boot. On VPC instances
+ this file is generated only on the first boot of the instance.
+ The check for the instance type is performed by ``is_classic_instance()``
+ method.
+
+ * For EC2 instances with multiple network interfaces (NICs) attached, DHCP4
+ will be enabled to obtain the primary private IPv4 address of those NICs.
+ Wherever DHCP4 or DHCP6 is enabled for a NIC, a DHCP route-metric will be
+ added with the value of ``<device-number + 1> * 100`` to ensure DHCP
+ routes on the primary NIC are preferred to any secondary NICs.
+ For example: the primary NIC will have a DHCP route-metric of 100,
+ the next NIC will have 200.
+
+.. _EC2 tags user guide: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS
diff --git a/doc/rtd/reference/datasources/exoscale.rst b/doc/rtd/reference/datasources/exoscale.rst
new file mode 100644
index 00000000..f6824b75
--- /dev/null
+++ b/doc/rtd/reference/datasources/exoscale.rst
@@ -0,0 +1,83 @@
+.. _datasource_exoscale:
+
+Exoscale
+********
+
+This datasource supports reading from the metadata server used on the
+`Exoscale platform`_. Use of the Exoscale datasource is recommended to benefit
+from new features of the Exoscale platform.
+
+The datasource relies on the availability of a compatible metadata server
+(``http://169.254.169.254`` is used by default) and its companion password
+server, reachable at the same address (by default on port 8080).
+
+Crawling of metadata
+====================
+
+The metadata service and password server are crawled slightly differently:
+
+* The "metadata service" is crawled every boot.
+* The password server is also crawled every boot (the Exoscale datasource
+ forces the password module to run with "frequency always").
+
+In the password server case, the following rules apply in order to enable the
+"restore instance password" functionality:
+
+* If a password is returned by the password server, it is then marked "saved"
+ by the ``cloud-init`` datasource. Subsequent boots will skip setting the
+ password (the password server will return ``saved_password``).
+* When the instance password is reset (via the Exoscale UI), the password
+ server will return the non-empty password at next boot, therefore causing
+ ``cloud-init`` to reset the instance's password.
+
+Configuration
+=============
+
+Users of this datasource are discouraged from changing the default settings
+unless instructed to by Exoscale support.
+
+The following settings are available and can be set for the
+:ref:`datasource base configuration<base_config-Datasource>`
+(in :file:`/etc/cloud/cloud.cfg.d/`).
+
+The settings available are:
+
+* ``metadata_url``: The URL for the metadata service.
+
+ Defaults to ``http://169.254.169.254``.
+
+* ``api_version``: The API version path on which to query the instance
+ metadata.
+
+ Defaults to ``1.0``.
+
+* ``password_server_port``: The port (on the metadata server) on which the
+ password server listens.
+
+ Defaults to ``8080``.
+
+* ``timeout``: The timeout value provided to ``urlopen`` for each individual
+ http request.
+
+ Defaults to ``10``.
+
+* ``retries``: The number of retries that should be done for a http request.
+
+ Defaults to ``6``.
+
+Example
+-------
+
+An example configuration with the default values is provided below:
+
+.. code-block:: yaml
+
+ datasource:
+ Exoscale:
+ metadata_url: "http://169.254.169.254"
+ api_version: "1.0"
+ password_server_port: 8080
+ timeout: 10
+ retries: 6
+
+.. _Exoscale platform: https://exoscale.com
diff --git a/doc/rtd/reference/datasources/fallback.rst b/doc/rtd/reference/datasources/fallback.rst
new file mode 100644
index 00000000..98283c0b
--- /dev/null
+++ b/doc/rtd/reference/datasources/fallback.rst
@@ -0,0 +1,19 @@
+.. _datasource_fallback:
+
+Fallback/no datasource
+**********************
+
+This is the fallback datasource when no other datasource can be selected. It
+is the equivalent of an empty datasource, in that it provides an empty string
+as user data, and an empty dictionary as metadata.
+
+It is useful for testing, as well as for occasions when you do not need an
+actual datasource to meet your instance requirements (i.e. you just want to
+run modules that are not concerned with any external data).
+
+It is typically put at the end of the datasource search list so that if all
+other datasources are not matched, then this one will be so that the user is
+not left with an inaccessible instance.
+
+.. note::
+ The instance id that this datasource provides is ``iid-datasource-none``.
diff --git a/doc/rtd/topics/datasources/gce.rst b/doc/rtd/reference/datasources/gce.rst
index c3de32a5..5f0dc77b 100644
--- a/doc/rtd/topics/datasources/gce.rst
+++ b/doc/rtd/reference/datasources/gce.rst
@@ -1,32 +1,44 @@
.. _datasource_gce:
Google Compute Engine
-=====================
+*********************
The GCE datasource gets its data from the internal compute metadata server.
Metadata can be queried at the URL
-'``http://metadata.google.internal/computeMetadata/v1/``'
-from within an instance. For more information see the `GCE metadata docs`_.
+:file:`http://metadata.google.internal/computeMetadata/v1/`
+from within an instance. For more information see the `GCE metadata docs`_.
-Currently the default project and instance level metadatakeys keys
+Currently, the default project and instance level metadata keys
``project/attributes/sshKeys`` and ``instance/attributes/ssh-keys`` are merged
to provide ``public-keys``.
-``user-data`` and ``user-data-encoding`` can be provided to cloud-init by
+``user-data`` and ``user-data-encoding`` can be provided to ``cloud-init`` by
setting those custom metadata keys for an *instance*.
Configuration
--------------
+=============
+
The following configuration can be set for the datasource in system
-configuration (in `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d/`).
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
The settings that may be configured are:
- * **retries**: The number of retries that should be done for an http request.
- This value is used only after metadata_url is selected. (default: 5)
- * **sec_between_retries**: The amount of wait time between the retries when
- crawling the metadata service. (default: 1)
+* ``retries``
+
+ The number of retries that should be attempted for a http request.
+ This value is used only after ``metadata_url`` is selected.
+
+ Default: 5
+
+* ``sec_between_retries``
+ The amount of wait time between retries when crawling the metadata service.
+
+ Default: 1
+
+Example
+-------
An example configuration with the default values is provided below:
@@ -38,5 +50,3 @@ An example configuration with the default values is provided below:
sec_between_retries: 1
.. _GCE metadata docs: https://cloud.google.com/compute/docs/storing-retrieving-metadata
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/lxd.rst b/doc/rtd/reference/datasources/lxd.rst
index b7986228..632f2669 100644
--- a/doc/rtd/topics/datasources/lxd.rst
+++ b/doc/rtd/reference/datasources/lxd.rst
@@ -1,10 +1,10 @@
.. _datasource_lxd:
LXD
-===
+***
-The data source ``LXD`` allows the user to provide custom user-data,
-vendor-data, meta-data and network-config to the instance without running
+The LXD datasource allows the user to provide custom user data,
+vendor data, metadata and network-config to the instance without running
a network service (or even without having a network at all). This datasource
performs HTTP GETs against the `LXD socket device`_ which is provided to each
running LXD container and VM as ``/dev/lxd/sock`` and represents all
@@ -18,44 +18,47 @@ instance-metadata as versioned HTTP routes such as:
The LXD socket device ``/dev/lxd/sock`` is only present on containers and VMs
when the instance configuration has ``security.devlxd=true`` (default).
-Disabling ``security.devlxd`` configuration setting at initial launch will
-ensure that cloud-init uses the :ref:`datasource_nocloud` datasource.
+Disabling the ``security.devlxd`` configuration setting at initial launch will
+ensure that ``cloud-init`` uses the :ref:`datasource_nocloud` datasource.
Disabling ``security.devlxd`` over the life of the container will result in
-warnings from cloud-init and cloud-init will keep the originally detected LXD
-datasource.
+warnings from ``cloud-init``, and ``cloud-init`` will keep the
+originally-detected LXD datasource.
-The LXD datasource is detected as viable by ``ds-identify`` during systemd
-generator time when either ``/dev/lxd/sock`` exists or
+The LXD datasource is detected as viable by ``ds-identify`` during ``systemd``
+generator time when either ``/dev/lxd/sock`` exists, or
``/sys/class/dmi/id/board_name`` matches "LXD".
-The LXD datasource provides cloud-init the ability to react to meta-data,
-vendor-data, user-data and network-config changes and render the updated
-configuration across a system reboot.
+The LXD datasource provides ``cloud-init`` with the ability to react to
+metadata, vendor data, user data and network-config changes, and to render the
+updated configuration across a system reboot.
-To modify what meta-data, vendor-data or user-data are provided to the
+To modify which metadata, vendor data or user data are provided to the
launched container, use either LXD profiles or
-``lxc launch ... -c <key>="<value>"`` at initial container launch setting one
-of the following keys:
-
- - user.meta-data: YAML metadata which will be appended to base meta-data
- - user.vendor-data: YAML which overrides any meta-data values
- - user.network-config: YAML representing either :ref:`network_config_v1` or
- :ref:`network_config_v2` format
- - user.user-data: YAML which takes preference and overrides both meta-data
- and vendor-data values
- - user.any-key: Custom user configuration key and value pairs can be passed to
- cloud-init. Those keys/values will be present in instance-data which can be
- used by both `#template: jinja` #cloud-config templates and
- the `cloud-init query` command.
-
-Note: LXD version 4.22 introduced a new scope of config keys prefaced by
-``cloud-init.`` which are preferred above the related ``user.*`` keys:
-
- - cloud-init.meta-data
- - cloud-init.vendor-data
- - cloud-init.network-config
- - cloud-init.user-data
-
+``lxc launch ... -c <key>="<value>"`` at initial container launch, by setting
+one of the following keys:
+
+- ``user.meta-data``: YAML metadata which will be appended to base metadata.
+- ``user.vendor-data``: YAML which overrides any metadata values.
+- ``user.network-config``: YAML representing either :ref:`network_config_v1` or
+ :ref:`network_config_v2` format.
+- ``user.user-data``: YAML which takes precedence and overrides both metadata
+ and vendor data values.
+- ``user.any-key``: Custom user configuration key and value pairs, which can be
+ passed to ``cloud-init``. Those keys/values will be present in instance-data
+ which can be used by both `#template: jinja` #cloud-config templates and
+ the :command:`cloud-init query` command.
+
+.. note::
+ LXD version 4.22 introduced a new scope of config keys prefaced by
+ ``cloud-init.``, which are preferred above the related ``user.*`` keys:
+
+ - ``cloud-init.meta-data``
+ - ``cloud-init.vendor-data``
+ - ``cloud-init.network-config``
+ - ``cloud-init.user-data``
+
+Configuration
+=============
By default, network configuration from this datasource will be:
@@ -73,25 +76,24 @@ This datasource is intended to replace :ref:`datasource_nocloud`
datasource for LXD instances with a more direct support for LXD APIs instead
of static NoCloud seed files.
-.. _LXD socket device: https://linuxcontainers.org/lxd/docs/master/dev-lxd
-.. vi: textwidth=79
-
Hotplug
--------
+=======
Network hotplug functionality is supported for the LXD datasource as described
in the :ref:`events` documentation. As hotplug functionality relies on the
-cloud provided network metadata, the LXD datasource will only meaningfully
+cloud-provided network metadata, the LXD datasource will only meaningfully
react to a hotplug event if it has the configuration necessary to respond to
-the change has been provided to LXD. Practically, this means that
-even with hotplug enabled, **the default behavior for adding a new virtual
-NIC will result no change**.
+the change. Practically, this means that even with hotplug enabled, **the
+default behavior for adding a new virtual NIC will result in no change**.
To update the configuration to be used by hotplug, first pass the network
configuration via the ``cloud-init.network-config`` (or
``user.network-config`` on older versions).
-For example, given an LXD instance named ``my-lxd`` with hotplug enabled and
+Example
+-------
+
+Given an LXD instance named ``my-lxd`` with hotplug enabled and
an LXD bridge named ``my-bridge``, the following will allow for additional
DHCP configuration of ``eth1``:
@@ -108,3 +110,5 @@ DHCP configuration of ``eth1``:
$ lxc config set my-lxd cloud-init.network-config="$(cat /tmp/cloud-network-config.yaml)"
$ lxc config device add my-lxd eth1 nic name=eth1 nictype=bridged parent=my-bridge
Device eth1 added to my-lxd
+
+.. _LXD socket device: https://linuxcontainers.org/lxd/docs/master/dev-lxd
diff --git a/doc/rtd/topics/datasources/maas.rst b/doc/rtd/reference/datasources/maas.rst
index eb59dab9..eb59dab9 100644
--- a/doc/rtd/topics/datasources/maas.rst
+++ b/doc/rtd/reference/datasources/maas.rst
diff --git a/doc/rtd/reference/datasources/nocloud.rst b/doc/rtd/reference/datasources/nocloud.rst
new file mode 100644
index 00000000..682c8477
--- /dev/null
+++ b/doc/rtd/reference/datasources/nocloud.rst
@@ -0,0 +1,221 @@
+.. _datasource_nocloud:
+
+NoCloud
+*******
+
+The data source ``NoCloud`` allows the user to provide user data and metadata
+to the instance without running a network service (or even without having a
+network at all).
+
+You can provide metadata and user data to a local VM boot via files on a
+`vfat`_ or `iso9660`_ filesystem. The filesystem volume label must be
+``cidata`` or ``CIDATA``.
+
+Alternatively, you can provide metadata via the kernel command line or SMBIOS
+"serial number" option. The data must be passed in the form of a string: ::
+
+ ds=nocloud[;key=val;key=val]
+
+or, ::
+
+ ds=nocloud-net[;key=val;key=val]
+
+Permitted keys
+==============
+
+The permitted keys are:
+
+* ``h`` or ``local-hostname``
+* ``i`` or ``instance-id``
+* ``s`` or ``seedfrom``
+
+With ``ds=nocloud``, the ``seedfrom`` value must start with ``/`` or
+``file://``. With ``ds=nocloud-net``, the ``seedfrom`` value must start
+with ``http://`` or ``https://`` and end with a trailing ``/``.
+
+Cloud-init performs variable expansion of the ``seedfrom`` URL for any DMI
+kernel variables present in :file:`/sys/class/dmi/id` (kenv on FreeBSD).
+Your ``seedfrom`` URL can contain variable names of the format
+``__dmi.varname__`` to indicate to the ``cloud-init`` NoCloud datasource that
+``dmi.varname`` should be expanded to the value of the DMI system attribute
+wanted.
+
+.. list-table:: Available DMI variables for expansion in ``seedfrom`` URL
+ :widths: 35 35 30
+ :header-rows: 0
+
+ * - ``dmi.baseboard-asset-tag``
+ - ``dmi.baseboard-manufacturer``
+ - ``dmi.baseboard-version``
+ * - ``dmi.bios-release-date``
+ - ``dmi.bios-vendor``
+ - ``dmi.bios-version``
+ * - ``dmi.chassis-asset-tag``
+ - ``dmi.chassis-manufacturer``
+ - ``dmi.chassis-serial-number``
+ * - ``dmi.chassis-version``
+ - ``dmi.system-manufacturer``
+ - ``dmi.system-product-name``
+ * - ``dmi.system-serial-number``
+ - ``dmi.system-uuid``
+ - ``dmi.system-version``
+
+For example, you can pass this option to QEMU: ::
+
+ -smbios type=1,serial=ds=nocloud-net;s=http://10.10.0.1:8000/__dmi.chassis-serial-number__/
+
+This will cause NoCloud to fetch the full metadata from a URL based on
+YOUR_SERIAL_NUMBER as seen in :file:`/sys/class/dmi/id/chassis_serial_number`
+(kenv on FreeBSD) from http://10.10.0.1:8000/YOUR_SERIAL_NUMBER/meta-data after
+the network initialisation is complete.
+
+File formats
+============
+
+These user data and metadata files are required as separate files at the
+same base URL: ::
+
+ /user-data
+ /meta-data
+
+Both files must be present for it to be considered a valid seed ISO.
+
+Basically, ``user-data`` is simply :ref:`user data<user_data_formats>` and
+``meta-data`` is a YAML-formatted file representing what you'd find in the EC2
+metadata service.
+
+You may also optionally provide a vendor data file adhering to
+:ref:`user data formats<user_data_formats>` at the same base URL: ::
+
+ /vendor-data
+
+Creating a disk
+===============
+
+Given a disk Ubuntu cloud image in :file:`disk.img`, you can create a
+sufficient disk by following the following example.
+
+1. Create the :file:`user-data` and :file:`meta-data` files that will be used
+ to modify the image on first boot.
+
+.. code-block:: sh
+
+ $ echo -e "instance-id: iid-local01\nlocal-hostname: cloudimg" > meta-data
+ $ echo -e "#cloud-config\npassword: passw0rd\nchpasswd: { expire: False }\nssh_pwauth: True\n" > user-data
+
+2. At this stage you have three options:
+
+ a. Create a disk to attach with some user data and metadata:
+
+ .. code-block:: sh
+
+ $ genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
+
+ b. Alternatively, create a ``vfat`` filesystem with the same files:
+
+ .. code-block:: sh
+
+ $ truncate --size 2M seed.iso
+ $ mkfs.vfat -n cidata seed.iso
+
+ * 2b) Option 1: mount and copy files:
+
+ .. code-block:: sh
+
+ $ sudo mount -t vfat seed.iso /mnt
+ $ sudo cp user-data meta-data /mnt
+ $ sudo umount /mnt
+
+ * 2b) Option 2: the ``mtools`` package provides ``mcopy``, which can
+ access ``vfat`` filesystems without mounting them:
+
+ .. code-block::
+
+ $ mcopy -oi seed.iso user-data meta-data
+
+3. Create a new qcow image to boot, backed by your original image:
+
+.. code-block:: sh
+
+ $ qemu-img create -f qcow2 -b disk.img -F qcow2 boot-disk.img
+
+4. Boot the image and log in as "Ubuntu" with password "passw0rd":
+
+.. code-block:: sh
+
+ $ kvm -m 256 \
+ -net nic -net user,hostfwd=tcp::2222-:22 \
+ -drive file=boot-disk.img,if=virtio \
+ -drive driver=raw,file=seed.iso,if=virtio
+
+.. note::
+ Note that "passw0rd" was set as password through the user data above. There
+ is no password set on these images.
+
+.. note::
+ The ``instance-id`` provided (``iid-local01`` above) is what is used to
+ determine if this is "first boot". So, if you are making updates to
+ user data you will also have to change the ``instance-id``, or start the
+ disk fresh.
+
+Also, you can inject an :file:`/etc/network/interfaces` file by providing the
+content for that file in the ``network-interfaces`` field of
+:file:`meta-data`.
+
+Example ``meta-data``
+---------------------
+
+::
+
+ instance-id: iid-abcdefg
+ network-interfaces: |
+ iface eth0 inet static
+ address 192.168.1.10
+ network 192.168.1.0
+ netmask 255.255.255.0
+ broadcast 192.168.1.255
+ gateway 192.168.1.254
+ hostname: myhost
+
+
+Network configuration can also be provided to ``cloud-init`` in either
+:ref:`network_config_v1` or :ref:`network_config_v2` by providing that
+YAML formatted data in a file named :file:`network-config`. If found,
+this file will override a :file:`network-interfaces` file.
+
+See an example below. Note specifically that this file does not
+have a top level ``network`` key as it is already assumed to
+be network configuration based on the filename.
+
+Example config
+--------------
+
+.. code-block:: yaml
+
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: "52:54:00:12:34:00"
+ subnets:
+ - type: static
+ address: 192.168.1.10
+ netmask: 255.255.255.0
+ gateway: 192.168.1.254
+
+
+.. code-block:: yaml
+
+ version: 2
+ ethernets:
+ interface0:
+ match:
+ macaddress: "52:54:00:12:34:00"
+ set-name: interface0
+ addresses:
+ - 192.168.1.10/255.255.255.0
+ gateway4: 192.168.1.254
+
+
+.. _iso9660: https://en.wikipedia.org/wiki/ISO_9660
+.. _vfat: https://en.wikipedia.org/wiki/File_Allocation_Table
diff --git a/doc/rtd/reference/datasources/nwcs.rst b/doc/rtd/reference/datasources/nwcs.rst
new file mode 100644
index 00000000..19c9ddd6
--- /dev/null
+++ b/doc/rtd/reference/datasources/nwcs.rst
@@ -0,0 +1,28 @@
+.. _datasource_nwcs:
+
+NWCS
+****
+
+The NWCS datasource retrieves basic configuration values from the locally
+accessible metadata service. All data is served over HTTP from the address
+``169.254.169.254``.
+
+Configuration
+=============
+
+The NWCS datasource can be configured as follows: ::
+
+ datasource:
+ NWCS:
+ url: 'http://169.254.169.254'
+ retries: 3
+ timeout: 2
+ wait: 2
+
+* ``url``: The URL used to acquire the metadata configuration.
+* ``retries``: Determines the number of times to attempt to connect to the
+ metadata service.
+* ``timeout``: Determines the timeout (in seconds) to wait for a response from
+ the metadata service
+* ``wait``: Determines the timeout in seconds to wait before retrying after
+ accessible failure.
diff --git a/doc/rtd/topics/datasources/opennebula.rst b/doc/rtd/reference/datasources/opennebula.rst
index 65570a53..2ad9d5c3 100644
--- a/doc/rtd/topics/datasources/opennebula.rst
+++ b/doc/rtd/reference/datasources/opennebula.rst
@@ -1,66 +1,61 @@
.. _datasource_opennebula:
OpenNebula
-==========
+**********
-The `OpenNebula`_ (ON) datasource supports the contextualization disk.
+The `OpenNebula`_ (ON) datasource supports the contextualisation disk.
- See `contextualization overview`_, `contextualizing VMs`_ and
- `network configuration`_ in the public documentation for
- more information.
+.. THESE LINKS ARE BROKEN
+.. See `contextualization overview`_, `contextualizing VMs`_ and
+.. `network configuration`_ in the public documentation for
+.. more information.
-OpenNebula's virtual machines are contextualized (parametrized) by
-CD-ROM image, which contains a shell script *context.sh* with
+OpenNebula's virtual machines are contextualised (parametrised) by
+CD-ROM image, which contains a shell script :file:`context.sh`, with
custom variables defined on virtual machine start. There are no
-fixed contextualization variables, but the datasource accepts
+fixed contextualisation variables, but the datasource accepts
many used and recommended across the documentation.
Datasource configuration
-~~~~~~~~~~~~~~~~~~~~~~~~~
+========================
-Datasource accepts following configuration options.
-
-::
+Datasource accepts the following configuration options: ::
dsmode:
values: local, net, disabled
default: net
-Tells if this datasource will be processed in 'local' (pre-networking) or
-'net' (post-networking) stage or even completely 'disabled'.
+These specify whether the datasource will be processed in ``local``
+(pre-networking) stage, ``net`` (post-networking) stage or be ``disabled``.
::
parseuser:
default: nobody
-Unprivileged system user used for contextualization script
-processing.
+Unprivileged system user used for contextualisation script processing.
-Contextualization disk
-~~~~~~~~~~~~~~~~~~~~~~
+Contextualisation disk
+======================
The following criteria are required:
1. Must be formatted with `iso9660`_ filesystem
- or have a *filesystem* label of **CONTEXT** or **CDROM**
-2. Must contain file *context.sh* with contextualization variables.
- File is generated by OpenNebula, it has a KEY='VALUE' format and
- can be easily read by bash
+ or have a *filesystem* label of ``CONTEXT`` or ``CDROM``.
+2. Must contain the file :file:`context.sh` with contextualisation variables.
+ The file is generated by OpenNebula and has a ``KEY='VALUE'`` format that
+ can be easily read by bash.
-Contextualization variables
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Contextualisation variables
+===========================
-There are no fixed contextualization variables in OpenNebula, no standard.
-Following variables were found on various places and revisions of
+There are no fixed or standard contextualisation variables in OpenNebula.
+The following variables were found in various places and in revisions of
the OpenNebula documentation. Where multiple similar variables are
-specified, only first found is taken.
-
-::
-
- DSMODE
+specified, only the one found first is taken.
-Datasource mode configuration override. Values: local, net, disabled.
+* ``DSMODE``: Datasource mode configuration override. Values are: ``local``,
+ ``net``, ``disabled``.
::
@@ -94,9 +89,10 @@ Instance hostname.
IP_PUBLIC
ETH0_IP
-If no hostname has been specified, cloud-init will try to create hostname
-from instance's IP address in 'local' dsmode. In 'net' dsmode, cloud-init
-tries to resolve one of its IP addresses to get hostname.
+If no hostname has been specified, ``cloud-init`` will try to create a
+hostname from the instance's IP address in ``local`` dsmode. In ``net``
+dsmode, ``cloud-init`` tries to resolve one of its IP addresses to get
+the hostname.
::
@@ -110,13 +106,13 @@ One or multiple SSH keys (separated by newlines) can be specified.
USER_DATA
USERDATA
-cloud-init user data.
+``Cloud-init`` user data.
Example configuration
-~~~~~~~~~~~~~~~~~~~~~
+=====================
-This example cloud-init configuration (*cloud.cfg*) enables
-OpenNebula datasource only in 'net' mode.
+This example ``cloud-init`` configuration (:file:`cloud.cfg`) enables
+OpenNebula datasource only in ``net`` mode.
::
@@ -128,7 +124,7 @@ OpenNebula datasource only in 'net' mode.
parseuser: nobody
Example VM's context section
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+============================
.. code-block:: sh
@@ -153,4 +149,3 @@ Example VM's context section
.. _contextualizing VMs: http://opennebula.org/documentation:documentation:cong
.. _network configuration: http://opennebula.org/documentation:documentation:cong#network_configuration
.. _iso9660: https://en.wikipedia.org/wiki/ISO_9660
-.. vi: textwidth=79
diff --git a/doc/rtd/reference/datasources/openstack.rst b/doc/rtd/reference/datasources/openstack.rst
new file mode 100644
index 00000000..f8fd2eb4
--- /dev/null
+++ b/doc/rtd/reference/datasources/openstack.rst
@@ -0,0 +1,128 @@
+.. _datasource_openstack:
+
+OpenStack
+*********
+
+This datasource supports reading data from the `OpenStack Metadata Service`_.
+
+Discovery
+=========
+
+To determine whether a platform looks like it may be OpenStack, ``cloud-init``
+checks the following environment attributes as a potential OpenStack platform:
+
+* May be OpenStack **if**:
+
+ * ``non-x86 cpu architecture``: because DMI data is buggy on some arches.
+
+* Is OpenStack **if** x86 architecture and **ANY** of the following:
+
+ * ``/proc/1/environ``: ``Nova-lxd`` contains
+ ``product_name=OpenStack Nova``.
+ * ``DMI product_name``: Either ``Openstack Nova`` or ``OpenStack Compute``.
+ * ``DMI chassis_asset_tag`` is ``HUAWEICLOUD``, ``OpenTelekomCloud``,
+ ``SAP CCloud VM``, ``OpenStack Nova`` (since 19.2) or
+ ``OpenStack Compute`` (since 19.2).
+
+Configuration
+=============
+
+The following configuration can be set for the datasource in system
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
+
+The settings that may be configured are as follows:
+
+``metadata_urls``
+-----------------
+
+This list of URLs will be searched for an OpenStack metadata service. The
+first entry that successfully returns a 200 response for ``<url>/openstack``
+will be selected.
+
+Default: ['http://169.254.169.254'])
+
+``max_wait``
+------------
+
+The maximum amount of clock time (in seconds) that should be spent searching
+``metadata_urls``. A value less than zero will result in only one request
+being made, to the first in the list.
+
+Default: -1
+
+``timeout``
+-----------
+
+The timeout value provided to ``urlopen`` for each individual http request.
+This is used both when selecting a ``metadata_url`` and when crawling the
+metadata service.
+
+Default: 10
+
+``retries``
+-----------
+
+The number of retries that should be attempted for an http request. This
+value is used only after ``metadata_url`` is selected.
+
+Default: 5
+
+``apply_network_config``
+------------------------
+
+A boolean specifying whether to configure the network for the instance based
+on :file:`network_data.json` provided by the metadata service. When False,
+only configure DHCP on the primary NIC for this instance.
+
+Default: True
+
+Example configuration
+=====================
+
+An example configuration with the default values is provided below:
+
+.. code-block:: yaml
+
+ datasource:
+ OpenStack:
+ metadata_urls: ["http://169.254.169.254"]
+ max_wait: -1
+ timeout: 10
+ retries: 5
+ apply_network_config: True
+
+
+Vendor Data
+===========
+
+The OpenStack metadata server can be configured to serve up vendor data,
+which is available to all instances for consumption. OpenStack vendor data is
+generally a JSON object.
+
+``Cloud-init`` will look for configuration in the ``cloud-init`` attribute
+of the vendor data JSON object. ``Cloud-init`` processes this configuration
+using the same handlers as user data, so any formats that work for user
+data should work for vendor data.
+
+For example, configuring the following as vendor data in OpenStack would
+upgrade packages and install ``htop`` on all instances:
+
+.. code-block:: json
+
+ {"cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - htop"}
+
+For more general information about how ``cloud-init`` handles vendor data,
+including how it can be disabled by users on instances, see our
+:ref:`explanation topic<vendordata>`.
+
+OpenStack can also be configured to provide "dynamic vendordata"
+which is provided by the DynamicJSON provider and appears under a
+different metadata path, :file:`/vendor_data2.json`.
+
+``Cloud-init`` will look for a ``cloud-init`` at the :file:`vendor_data2`
+path; if found, settings are applied after (and, hence, overriding) the
+settings from static vendor data. Both sets of vendor data can be overridden
+by user data.
+
+.. _OpenStack Metadata Service: https://docs.openstack.org/nova/latest/admin/metadata-service.html
diff --git a/doc/rtd/reference/datasources/oracle.rst b/doc/rtd/reference/datasources/oracle.rst
new file mode 100644
index 00000000..74bfb3e3
--- /dev/null
+++ b/doc/rtd/reference/datasources/oracle.rst
@@ -0,0 +1,53 @@
+.. _datasource_oracle:
+
+Oracle
+******
+
+This datasource reads metadata, vendor data and user data from
+`Oracle Compute Infrastructure`_ (OCI).
+
+Oracle platform
+===============
+
+OCI provides bare metal and virtual machines. In both cases, the platform
+identifies itself via DMI data in the chassis asset tag with the string
+``'OracleCloud.com'``.
+
+Oracle's platform provides a metadata service that mimics the ``2013-10-17``
+version of OpenStack metadata service. Initially, support for Oracle was done
+via the OpenStack datasource.
+
+``Cloud-init`` has a specific datasource for Oracle in order to:
+
+a. Allow and support the future growth of the OCI platform.
+b. Address small differences between OpenStack and Oracle metadata
+ implementation.
+
+Configuration
+=============
+
+The following configuration can be set for the datasource in system
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
+
+``configure_secondary_nics``
+----------------------------
+
+A boolean, defaulting to False. If set to True on an OCI Virtual Machine,
+``cloud-init`` will fetch networking metadata from Oracle's IMDS and use it
+to configure the non-primary network interface controllers in the system. If
+set to True on an OCI Bare Metal Machine, it will have no effect (though this
+may change in the future).
+
+Example configuration
+---------------------
+
+An example configuration with the default values is provided below:
+
+.. code-block:: yaml
+
+ datasource:
+ Oracle:
+ configure_secondary_nics: false
+
+.. _Oracle Compute Infrastructure: https://cloud.oracle.com/
diff --git a/doc/rtd/reference/datasources/ovf.rst b/doc/rtd/reference/datasources/ovf.rst
new file mode 100644
index 00000000..5a7af4fc
--- /dev/null
+++ b/doc/rtd/reference/datasources/ovf.rst
@@ -0,0 +1,12 @@
+.. _datasource_ovf:
+
+OVF
+***
+
+The OVF datasource provides a datasource for reading data from an
+`Open Virtualization Format`_ ISO transport.
+
+For further information see a full working example in ``cloud-init``'s
+source code tree in :file:`doc/sources/ovf`.
+
+.. _Open Virtualization Format: https://en.wikipedia.org/wiki/Open_Virtualization_Format
diff --git a/doc/rtd/reference/datasources/rbxcloud.rst b/doc/rtd/reference/datasources/rbxcloud.rst
new file mode 100644
index 00000000..44b30b3e
--- /dev/null
+++ b/doc/rtd/reference/datasources/rbxcloud.rst
@@ -0,0 +1,23 @@
+.. _datasource_rbx:
+
+Rbx Cloud
+*********
+
+The Rbx datasource consumes the metadata drive available on the `HyperOne`_
+and `Rootbox`_ platforms.
+
+This datasource supports network configurations, hostname, user accounts and
+user metadata.
+
+Metadata drive
+==============
+
+Drive metadata is a `FAT`_-formatted partition with the ``CLOUDMD`` or
+``cloudmd`` label on the system disk. Its contents are refreshed each time
+the virtual machine is restarted, if the partition exists. For more information
+see `HyperOne Virtual Machine docs`_.
+
+.. _HyperOne: http://www.hyperone.com/
+.. _Rootbox: https://rootbox.com/
+.. _HyperOne Virtual Machine docs: http://www.hyperone.com/
+.. _FAT: https://en.wikipedia.org/wiki/File_Allocation_Table
diff --git a/doc/rtd/reference/datasources/smartos.rst b/doc/rtd/reference/datasources/smartos.rst
new file mode 100644
index 00000000..fba87931
--- /dev/null
+++ b/doc/rtd/reference/datasources/smartos.rst
@@ -0,0 +1,181 @@
+.. _datasource_smartos:
+
+SmartOS Datasource
+******************
+
+This datasource finds metadata and user data from the SmartOS virtualisation
+platform (i.e., Joyent).
+
+Please see http://smartos.org/ for information about SmartOS.
+
+SmartOS platform
+================
+
+The SmartOS virtualisation platform uses metadata from the instance via the
+second serial console. On Linux, this is :file:`/dev/ttyS1`. The data is
+provided via a simple protocol:
+
+* Something queries for the data,
+* the console responds with the status, and
+* if "SUCCESS" returns until a single ".\n".
+
+New versions of the SmartOS tooling will include support for Base64-encoded
+data.
+
+Metadata channels
+=================
+
+``Cloud-init`` supports three modes of delivering user data and metadata via
+the flexible channels of SmartOS.
+
+1. User data is written to :file:`/var/db/user-data`:
+
+ - As per the spec, user data is for consumption by the end user, not
+ provisioning tools.
+ - ``Cloud-init`` ignores this channel, other than writing it to disk.
+ - Removal of the ``meta-data`` key means that :file:`/var/db/user-data`
+ gets removed.
+ - A backup of previous metadata is maintained as
+ :file:`/var/db/user-data.<timestamp>`. ``<timestamp>`` is the epoch time
+ when ``cloud-init`` ran.
+
+2. ``user-script`` is written to
+ :file:`/var/lib/cloud/scripts/per-boot/99_user_data`:
+
+ - This is executed each boot.
+ - A link is created to :file:`/var/db/user-script`.
+ - Previous versions of ``user-script`` is written to
+ :file:`/var/lib/cloud/scripts/per-boot.backup/99_user_script.<timestamp>.`
+ - <timestamp> is the epoch time when ``cloud-init`` ran.
+ - When the ``user-script`` metadata key goes missing, ``user-script`` is
+ removed from the file system, although a backup is maintained.
+ - If the script does not start with a shebang (i.e., it starts with
+ #!<executable>), or it is not an executable, ``cloud-init`` will add a
+ shebang of "#!/bin/bash".
+
+3. ``Cloud-init`` user data is treated like on other Clouds.
+
+ - This channel is used for delivering ``_all_ cloud-init`` instructions.
+ - Scripts delivered over this channel must be well formed (i.e., they must
+ have a shebang).
+
+``Cloud-init`` supports reading the traditional metadata fields supported by
+the SmartOS tools. These are:
+
+* ``root_authorized_keys``
+* ``hostname``
+* ``enable_motd_sys_info``
+* ``iptables_disable``
+
+.. note::
+ At this time, ``iptables_disable`` and ``enable_motd_sys_info`` are read
+ but are not actioned.
+
+Disabling ``user-script``
+=========================
+
+``Cloud-init`` uses the per-boot script functionality to handle the execution
+of the ``user-script``. If you want to prevent this, use a cloud-config of:
+
+.. code-block:: yaml
+
+ #cloud-config
+ cloud_final_modules:
+ - scripts-per-once
+ - scripts-per-instance
+ - scripts-user
+ - ssh-authkey-fingerprints
+ - keys-to-console
+ - phone-home
+ - final-message
+ - power-state-change
+
+Alternatively you can use the JSON patch method:
+
+.. code-block:: yaml
+
+ #cloud-config-jsonp
+ [
+ { "op": "replace",
+ "path": "/cloud_final_modules",
+ "value": ["scripts-per-once",
+ "scripts-per-instance",
+ "scripts-user",
+ "ssh-authkey-fingerprints",
+ "keys-to-console",
+ "phone-home",
+ "final-message",
+ "power-state-change"]
+ }
+ ]
+
+The default cloud-config includes "script-per-boot". ``Cloud-init`` will still
+ingest and write the user data, but will not execute it when you disable
+the per-boot script handling.
+
+The cloud-config needs to be delivered over the ``cloud-init:user-data``
+channel in order for ``cloud-init`` to ingest it.
+
+.. note::
+ Unless you have an explicit use-case, it is recommended that you do not
+ disable the per-boot script execution, especially if you are using
+ any of the life-cycle management features of SmartOS.
+
+Base64
+======
+
+The following are exempt from Base64 encoding, owing to the fact that they
+are provided by SmartOS:
+
+* ``root_authorized_keys``
+* ``enable_motd_sys_info``
+* ``iptables_disable``
+* ``user-data``
+* ``user-script``
+
+This list can be changed through the
+:ref:`datasource base configuration<base_config-Datasource>` variable
+``no_base64_decode``.
+
+This means that ``user-script``, ``user-data`` and other values can be Base64
+encoded. Since ``cloud-init`` can only guess whether or not something
+is truly Base64 encoded, the following metadata keys are hints as to whether
+or not to Base64 decode something:
+
+* ``base64_all``: Except for excluded keys, attempt to Base64 decode the
+ values. If the value fails to decode properly, it will be returned in its
+ text.
+* ``base64_keys``: A comma-delimited list of which keys are Base64 encoded.
+* ``b64-<key>``: For any key, if an entry exists in the metadata for
+ ``'b64-<key>'``, then ``'b64-<key>'`` is expected to be a plain-text boolean
+ indicating whether or not its value is encoded.
+* ``no_base64_decode``: This is a configuration setting
+ (i.e., :file:`/etc/cloud/cloud.cfg.d`) that sets which values should not
+ be Base64 decoded.
+
+``disk_aliases`` and ephemeral disk
+===================================
+
+By default, SmartOS only supports a single ephemeral disk. That disk is
+completely empty (un-partitioned, with no filesystem).
+
+The SmartOS datasource has built-in cloud-config which instructs the
+``disk_setup`` module to partition and format the ephemeral disk.
+
+You can control the ``disk_setup`` in 2 ways:
+
+1. Through the datasource config, you can change the 'alias' of ``ephermeral0``
+ to reference another device. The default is:
+
+ .. code-block::
+
+ 'disk_aliases': {'ephemeral0': '/dev/vdb'}
+
+ This means that anywhere ``disk_setup`` sees a device named 'ephemeral0',
+ then :file:`/dev/vdb` will be substituted.
+
+2. You can provide ``disk_setup`` or ``fs_setup`` data in ``user-data`` to
+ overwrite the datasource's built-in values.
+
+See :file:`doc/examples/cloud-config-disk-setup.txt` for information on
+``disk_setup``.
diff --git a/doc/rtd/reference/datasources/upcloud.rst b/doc/rtd/reference/datasources/upcloud.rst
new file mode 100644
index 00000000..21b95922
--- /dev/null
+++ b/doc/rtd/reference/datasources/upcloud.rst
@@ -0,0 +1,22 @@
+.. _datasource_upcloud:
+
+UpCloud
+*******
+
+The `UpCloud`_ datasource consumes information from UpCloud's `metadata
+service`_. This metadata service serves information about the
+running server via HTTP over the address ``169.254.169.254`` available in
+every DHCP-configured interface. The metadata API endpoints are fully
+described in `UpCloud API documentation`_.
+
+Providing user data
+===================
+
+When creating a server, user data is provided by specifying it as
+``user_data`` in the API or via the server creation tool in the control panel.
+User data is immutable during the server's lifetime, and can be removed by
+deleting the server.
+
+.. _UpCloud: https://upcloud.com/
+.. _metadata service: https://upcloud.com/community/tutorials/upcloud-metadata-service/
+.. _UpCloud API documentation: https://developers.upcloud.com/1.3/8-servers/#metadata-service
diff --git a/doc/rtd/reference/datasources/vmware.rst b/doc/rtd/reference/datasources/vmware.rst
new file mode 100644
index 00000000..5e060769
--- /dev/null
+++ b/doc/rtd/reference/datasources/vmware.rst
@@ -0,0 +1,451 @@
+.. _datasource_vmware:
+
+VMware
+******
+
+This datasource is for use with systems running on a VMware platform such as
+vSphere and currently supports the following data transports:
+
+* `Guest OS Customization`_
+* `GuestInfo keys`_
+
+The configuration method is dependent upon the transport.
+
+Guest OS customisation
+======================
+
+The following configuration can be set for this datasource in ``cloud-init``
+configuration (in :file:`/etc/cloud/cloud.cfg` or
+:file:`/etc/cloud/cloud.cfg.d/`).
+
+System configuration
+--------------------
+
+* ``disable_vmware_customization``: true (disable) or false (enable) the VMware
+ traditional Linux guest customisation. Traditional Linux guest customisation
+ is customising a Linux virtual machine with a
+ `traditional Linux customisation specification`_. Setting this configuration
+ to false is required to make sure this datasource is found in ``ds-identify``
+ when using Guest OS customisation transport.
+
+ Default: true
+
+Datasource configuration
+------------------------
+
+* ``allow_raw_data``: true (enable) or false (disable) the VMware customisation
+ using ``cloud-init`` metadata and user data directly. Since vSphere 7.0
+ Update 3 version, users can create a Linux customisation specification with
+ minimal ``cloud-init`` metadata and user data, and apply this specification
+ to a virtual machine. This datasource will parse the metadata and user data
+ and configure the virtual machine with them. See
+ `Guest customisation using cloud-init`_ for more information.
+
+ Default: true
+
+* ``vmware_cust_file_max_wait``: The maximum amount of clock time (in seconds)
+ that should be spent waiting for VMware customisation files.
+
+ Default: 15
+
+Configuration examples
+----------------------
+
+1. Create the :file:`/etc/cloud/cloud.cfg.d/99-vmware-guest-customization.cfg`
+ file with the following content, which will enable VMware customisation and
+ set the maximum waiting time for the VMware customisation file to 10
+ seconds:
+
+ .. code-block:: yaml
+
+ disable_vmware_customization: false
+ datasource:
+ VMware:
+ vmware_cust_file_max_wait: 10
+
+2. Create the :file:`/etc/cloud/cloud.cfg.d/99-vmware-guest-customization.cfg`
+ file with the following content, which will enable VMware customisation but
+ will only try to apply a traditional Linux Guest Customisation
+ configuration, and set the maximum waiting time for the VMware
+ customisation file to 10 seconds:
+
+ .. code-block:: yaml
+
+ disable_vmware_customization: false
+ datasource:
+ VMware:
+ allow_raw_data: false
+ vmware_cust_file_max_wait: 10
+
+VMware Tools configuration
+--------------------------
+
+`VMware Tools`_ is required for this datasource's configuration settings, as
+well as vCloud and vSphere admin configuration. Users can change the VMware
+Tools configuration options with the following command:
+
+.. code-block:: shell
+
+ vmware-toolbox-cmd config set <section> <key> <value>
+
+The following VMware Tools configuration option affects this datasource's
+behaviour when applying customisation configuration with custom scripts:
+
+* ``[deploypkg] enable-custom-scripts``: If this option is absent in VMware
+ Tools configuration, the custom script is disabled by default for security
+ reasons. Some VMware products could change this default behaviour (for
+ example: enabled by default) via customisation of the specification settings.
+
+ VMware admins can refer to `customization configuration`_ and set the
+ customisation specification settings.
+
+For more information, see `VMware vSphere Product Documentation`_ and specific
+VMware Tools configuration options.
+
+GuestInfo keys
+==============
+
+One method of providing meta, user, and vendor data is by setting the following
+key/value pairs on a VM's ``extraConfig`` `property`_:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Property
+ - Description
+ * - ``guestinfo.metadata``
+ - A YAML or JSON document containing the ``cloud-init`` metadata.
+ * - ``guestinfo.metadata.encoding``
+ - The encoding type for ``guestinfo.metadata``.
+ * - ``guestinfo.userdata``
+ - A YAML document containing the ``cloud-init`` user data.
+ * - ``guestinfo.userdata.encoding``
+ - The encoding type for ``guestinfo.userdata``.
+ * - ``guestinfo.vendordata``
+ - A YAML document containing the ``cloud-init`` vendor data.
+ * - ``guestinfo.vendordata.encoding``
+ - The encoding type for ``guestinfo.vendordata``.
+
+
+All ``guestinfo.*.encoding`` values may be set to ``base64`` or
+``gzip+base64``.
+
+Features
+========
+
+This section reviews several features available in this datasource.
+
+Instance data and lazy networks
+-------------------------------
+
+One of the hallmarks of ``cloud-init`` is
+:ref:`its use of instance-data and JINJA queries <instancedata-Using>` -- the
+ability to write queries in user and vendor data that reference runtime
+information present in :file:`/run/cloud-init/instance-data.json`. This works
+well when the metadata provides all of the information up front, such as the
+network configuration. For systems that rely on DHCP, however, this
+information may not be available when the metadata is persisted to disk.
+
+This datasource ensures that even if the instance is using DHCP to configure
+networking, the same details about the configured network are available in
+:file:`/run/cloud-init/instance-data.json` as if static networking was used.
+This information collected at runtime is easy to demonstrate by executing the
+datasource on the command line. From the root of this repository, run the
+following command:
+
+.. code-block:: bash
+
+ PYTHONPATH="$(pwd)" python3 cloudinit/sources/DataSourceVMware.py
+
+The above command will result in output similar to the below JSON:
+
+.. code-block:: json
+
+ {
+ "hostname": "akutz.localhost",
+ "local-hostname": "akutz.localhost",
+ "local-ipv4": "192.168.0.188",
+ "local_hostname": "akutz.localhost",
+ "network": {
+ "config": {
+ "dhcp": true
+ },
+ "interfaces": {
+ "by-ipv4": {
+ "172.0.0.2": {
+ "netmask": "255.255.255.255",
+ "peer": "172.0.0.2"
+ },
+ "192.168.0.188": {
+ "broadcast": "192.168.0.255",
+ "mac": "64:4b:f0:18:9a:21",
+ "netmask": "255.255.255.0"
+ }
+ },
+ "by-ipv6": {
+ "fd8e:d25e:c5b6:1:1f5:b2fd:8973:22f2": {
+ "flags": 208,
+ "mac": "64:4b:f0:18:9a:21",
+ "netmask": "ffff:ffff:ffff:ffff::/64"
+ }
+ },
+ "by-mac": {
+ "64:4b:f0:18:9a:21": {
+ "ipv4": [
+ {
+ "addr": "192.168.0.188",
+ "broadcast": "192.168.0.255",
+ "netmask": "255.255.255.0"
+ }
+ ],
+ "ipv6": [
+ {
+ "addr": "fd8e:d25e:c5b6:1:1f5:b2fd:8973:22f2",
+ "flags": 208,
+ "netmask": "ffff:ffff:ffff:ffff::/64"
+ }
+ ]
+ },
+ "ac:de:48:00:11:22": {
+ "ipv6": []
+ }
+ }
+ }
+ },
+ "wait-on-network": {
+ "ipv4": true,
+ "ipv6": "false"
+ }
+ }
+
+
+Redacting sensitive information (GuestInfo keys transport only)
+---------------------------------------------------------------
+
+Sometimes the ``cloud-init`` user data might contain sensitive information,
+and it may be desirable to have the ``guestinfo.userdata`` key (or other
+``guestinfo`` keys) redacted as soon as its data is read by the datasource.
+This is possible by adding the following to the metadata:
+
+.. code-block:: yaml
+
+ redact: # formerly named cleanup-guestinfo, which will also work
+ - userdata
+ - vendordata
+
+When the above snippet is added to the metadata, the datasource will iterate
+over the elements in the ``redact`` array and clear each of the keys. For
+example, when the ``guestinfo`` transport is used, the above snippet will cause
+the following commands to be executed:
+
+.. code-block:: shell
+
+ vmware-rpctool "info-set guestinfo.userdata ---"
+ vmware-rpctool "info-set guestinfo.userdata.encoding "
+ vmware-rpctool "info-set guestinfo.vendordata ---"
+ vmware-rpctool "info-set guestinfo.vendordata.encoding "
+
+Please note that keys are set to the valid YAML string ``---`` as it is not
+possible remove an existing key from the ``guestinfo`` key-space. A key's
+analogous encoding property will be set to a single white-space character,
+causing the datasource to treat the actual key value as plain-text, thereby
+loading it as an empty YAML doc (hence the aforementioned ``---``\ ).
+
+Reading the local IP addresses
+------------------------------
+
+This datasource automatically discovers the local IPv4 and IPv6 addresses for
+a guest operating system based on the default routes. However, when inspecting
+a VM externally, it's not possible to know what the *default* IP address is for
+the guest OS. That's why this datasource sets the discovered, local IPv4 and
+IPv6 addresses back in the ``guestinfo`` namespace as the following keys:
+
+* ``guestinfo.local-ipv4``
+* ``guestinfo.local-ipv6``
+
+It is possible that a host may not have any default, local IP addresses. It's
+also possible the reported, local addresses are link-local addresses. But these
+two keys may be used to discover what this datasource determined were the local
+IPv4 and IPv6 addresses for a host.
+
+Waiting on the network
+----------------------
+
+Sometimes ``cloud-init`` may bring up the network, but it will not finish
+coming online before the datasource's ``setup`` function is called, resulting
+in a :file:`/var/run/cloud-init/instance-data.json` file that does not have the
+correct network information. It is possible to instruct the datasource to wait
+until an IPv4 or IPv6 address is available before writing the instance data
+with the following metadata properties:
+
+.. code-block:: yaml
+
+ wait-on-network:
+ ipv4: true
+ ipv6: true
+
+If either of the above values are true, then the datasource will sleep for a
+second, check the network status, and repeat until one or both addresses from
+the specified families are available.
+
+Walkthrough of GuestInfo keys transport
+=======================================
+
+The following series of steps is a demonstration of how to configure a VM with
+this datasource using the GuestInfo keys transport:
+
+#. Create the metadata file for the VM. Save the following YAML to a file named
+ :file:`metadata.yaml`\:
+
+ .. code-block:: yaml
+
+ instance-id: cloud-vm
+ local-hostname: cloud-vm
+ network:
+ version: 2
+ ethernets:
+ nics:
+ match:
+ name: ens*
+ dhcp4: yes
+
+#. Create the userdata file :file:`userdata.yaml`\:
+
+ .. code-block:: yaml
+
+ #cloud-config
+
+ users:
+ - default
+ - name: akutz
+ primary_group: akutz
+ sudo: ALL=(ALL) NOPASSWD:ALL
+ groups: sudo, wheel
+ lock_passwd: true
+ ssh_authorized_keys:
+ - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDE0c5FczvcGSh/tG4iw+Fhfi/O5/EvUM/96js65tly4++YTXK1d9jcznPS5ruDlbIZ30oveCBd3kT8LLVFwzh6hepYTf0YmCTpF4eDunyqmpCXDvVscQYRXyasEm5olGmVe05RrCJSeSShAeptv4ueIn40kZKOghinGWLDSZG4+FFfgrmcMCpx5YSCtX2gvnEYZJr0czt4rxOZuuP7PkJKgC/mt2PcPjooeX00vAj81jjU2f3XKrjjz2u2+KIt9eba+vOQ6HiC8c2IzRkUAJ5i1atLy8RIbejo23+0P4N2jjk17QySFOVHwPBDTYb0/0M/4ideeU74EN/CgVsvO6JrLsPBR4dojkV5qNbMNxIVv5cUwIy2ThlLgqpNCeFIDLCWNZEFKlEuNeSQ2mPtIO7ETxEL2Cz5y/7AIuildzYMc6wi2bofRC8HmQ7rMXRWdwLKWsR0L7SKjHblIwarxOGqLnUI+k2E71YoP7SZSlxaKi17pqkr0OMCF+kKqvcvHAQuwGqyumTEWOlH6TCx1dSPrW+pVCZSHSJtSTfDW2uzL6y8k10MT06+pVunSrWo5LHAXcS91htHV1M1UrH/tZKSpjYtjMb5+RonfhaFRNzvj7cCE1f3Kp8UVqAdcGBTtReoE8eRUT63qIxjw03a7VwAyB2w+9cu1R9/vAo8SBeRqw== sakutz@gmail.com
+
+#. Please note this step requires that the VM be powered off. All of the
+ commands below use the VMware CLI tool, `govc`_.
+
+ Go ahead and assign the path to the VM to the environment variable ``VM``\:
+
+ .. code-block:: shell
+
+ export VM="/inventory/path/to/the/vm"
+
+#. Power off the VM:
+
+ .. raw:: html
+
+ <hr />
+
+ &#x26a0;&#xfe0f; <strong>First Boot Mode</strong>
+
+ To ensure the next power-on operation results in a first-boot scenario for
+ ``cloud-init``, it may be necessary to run the following command just before
+ powering off the VM:
+
+ .. code-block:: bash
+
+ cloud-init clean --logs --machine-id
+
+ Otherwise ``cloud-init`` may not run in first-boot mode. For more
+ information on how the boot mode is determined, please see the
+ :ref:`First Boot Documentation <boot-First_boot_determination>`.
+
+ .. raw:: html
+
+ <hr />
+
+ .. code-block:: shell
+
+ govc vm.power -off "${VM}"
+
+#. Export the environment variables that contain the ``cloud-init`` metadata
+ and user data:
+
+ .. code-block:: shell
+
+ export METADATA=$(gzip -c9 <metadata.yaml | { base64 -w0 2>/dev/null || base64; }) \
+ USERDATA=$(gzip -c9 <userdata.yaml | { base64 -w0 2>/dev/null || base64; })
+
+#. Assign the metadata and user data to the VM:
+
+ .. code-block:: shell
+
+ govc vm.change -vm "${VM}" \
+ -e guestinfo.metadata="${METADATA}" \
+ -e guestinfo.metadata.encoding="gzip+base64" \
+ -e guestinfo.userdata="${USERDATA}" \
+ -e guestinfo.userdata.encoding="gzip+base64"
+
+ .. note::
+ Please note the above commands include specifying the encoding for the
+ properties. This is important as it informs the datasource how to decode
+ the data for ``cloud-init``. Valid values for ``metadata.encoding`` and
+ ``userdata.encoding`` include:
+
+ * ``base64``
+ * ``gzip+base64``
+
+#. Power on the VM:
+
+ .. code-block:: shell
+
+ govc vm.power -on "${VM}"
+
+If all went according to plan, the CentOS box is:
+
+* Locked down, allowing SSH access only for the user in the user data.
+* Configured for a dynamic IP address via DHCP.
+* Has a hostname of ``cloud-vm``.
+
+Examples of common configurations
+=================================
+
+Setting the hostname
+--------------------
+
+The hostname is set by way of the metadata key ``local-hostname``.
+
+Setting the instance ID
+-----------------------
+
+The instance ID may be set by way of the metadata key ``instance-id``. However,
+if this value is absent then the instance ID is read from the file
+:file:`/sys/class/dmi/id/product_uuid`.
+
+Providing public SSH keys
+-------------------------
+
+The public SSH keys may be set by way of the metadata key ``public-keys-data``.
+Each newline-terminated string will be interpreted as a separate SSH public
+key, which will be placed in distro's default user's
+:file:`~/.ssh/authorized_keys`. If the value is empty or absent, then nothing
+will be written to :file:`~/.ssh/authorized_keys`.
+
+Configuring the network
+-----------------------
+
+The network is configured by setting the metadata key ``network`` with a value
+consistent with Network Config :ref:`Version 1 <network_config_v1>` or
+:ref:`Version 2 <network_config_v2>`, depending on the Linux distro's version
+of ``cloud-init``.
+
+The metadata key ``network.encoding`` may be used to indicate the format of
+the metadata key ``network``. Valid encodings are ``base64`` and
+``gzip+base64``.
+
+
+.. LINKS
+.. _Guest OS Customization: https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-58E346FF-83AE-42B8-BE58-253641D257BC.html
+.. _GuestInfo keys: https://github.com/vmware/govmomi/blob/master/govc/USAGE.md
+.. _traditional Linux customisation specification: https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-EB5F090E-723C-4470-B640-50B35D1EC016.html#GUID-9A5093A5-C54F-4502-941B-3F9C0F573A39__GUID-40C60643-A2EB-4B05-8927-B51AF7A6CC5E
+.. _Guest customisation using cloud-init: https://developer.vmware.com/docs/17020/vsphere-web-services-sdk-programming-guide--8-0-/GUID-75E27FA9-2E40-4CBF-BF3D-22DCFC8F11F7.html
+.. _VMware Tools: https://docs.vmware.com/en/VMware-Tools/index.html
+.. _customization configuration: https://github.com/canonical/cloud-init/blob/main/cloudinit/sources/helpers/vmware/imc/config.py
+.. _VMware vSphere Product Documentation: https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-EB5F090E-723C-4470-B640-50B35D1EC016.html#GUID-9A5093A5-C54F-4502-941B-3F9C0F573A39__GUID-40C60643-A2EB-4B05-8927-B51AF7A6CC5E
+.. _property: https://vdc-repo.vmware.com/vmwb-repository/dcr-public/723e7f8b-4f21-448b-a830-5f22fd931b01/5a8257bd-7f41-4423-9a73-03307535bd42/doc/vim.vm.ConfigInfo.html
+.. _govc: https://github.com/vmware/govmomi/blob/master/govc
+
diff --git a/doc/rtd/reference/datasources/vultr.rst b/doc/rtd/reference/datasources/vultr.rst
new file mode 100644
index 00000000..1115c29e
--- /dev/null
+++ b/doc/rtd/reference/datasources/vultr.rst
@@ -0,0 +1,32 @@
+.. _datasource_vultr:
+
+Vultr
+*****
+
+The `Vultr`_ datasource retrieves basic configuration values from the locally
+accessible metadata service. All data is served over HTTP from the address
+``169.254.169.254``. The endpoints are documented in the
+`metadata service documentation`_.
+
+Configuration
+=============
+
+Vultr's datasource can be configured as follows: ::
+
+ datasource:
+ Vultr:
+ url: 'http://169.254.169.254'
+ retries: 3
+ timeout: 2
+ wait: 2
+
+* ``url``: The URL used to acquire the metadata configuration.
+* ``retries``: Determines the number of times to attempt to connect to the
+ metadata service.
+* ``timeout``: Determines the timeout (in seconds) to wait for a response from
+ the metadata service.
+* ``wait``: Determines the timeout (in seconds) to wait before retrying after
+ accessible failure.
+
+.. _Vultr: https://www.vultr.com/
+.. _metadata service documentation: https://www.vultr.com/metadata/
diff --git a/doc/rtd/reference/datasources/zstack.rst b/doc/rtd/reference/datasources/zstack.rst
new file mode 100644
index 00000000..e1fefd21
--- /dev/null
+++ b/doc/rtd/reference/datasources/zstack.rst
@@ -0,0 +1,36 @@
+.. _datasource_zstack:
+
+ZStack
+******
+
+ZStack platform provides an AWS EC2 metadata service, but with different
+datasource identity. More information about ZStack can be found at
+`ZStack`_.
+
+Discovery
+=========
+
+To determine whether a VM is running on the ZStack platform, ``cloud-init``
+checks DMI information via ``dmidecode -s chassis-asset-tag``. If the output
+ends with ``.zstack.io``, it's running on the ZStack platform.
+
+Metadata
+--------
+
+The same way as with EC2, instance metadata can be queried at: ::
+
+ GET http://169.254.169.254/2009-04-04/meta-data/
+ instance-id
+ local-hostname
+
+User data
+---------
+
+The same way as with EC2, instance user data can be queried at: ::
+
+ GET http://169.254.169.254/2009-04-04/user-data/
+ meta_data.json
+ user_data
+ password
+
+.. _ZStack: https://www.zstack.io
diff --git a/doc/rtd/topics/examples.rst b/doc/rtd/reference/examples.rst
index 3f260947..c9829e49 100644
--- a/doc/rtd/topics/examples.rst
+++ b/doc/rtd/reference/examples.rst
@@ -1,6 +1,5 @@
.. _yaml_examples:
-*********************
Cloud config examples
*********************
@@ -11,7 +10,6 @@ Including users and groups
:language: yaml
:linenos:
-
Writing out arbitrary files
===========================
@@ -19,7 +17,6 @@ Writing out arbitrary files
:language: yaml
:linenos:
-
Adding a yum repository
=======================
@@ -27,8 +24,8 @@ Adding a yum repository
:language: yaml
:linenos:
-Configure an instances trusted CA certificates
-==============================================
+Configure an instance's trusted CA certificates
+===============================================
.. literalinclude:: ../../examples/cloud-config-ca-certs.txt
:language: yaml
@@ -48,14 +45,14 @@ Install and run `ansible-pull`
:language: yaml
:linenos:
-Configure Instance to be Managed by Ansible
+Configure instance to be managed by Ansible
===========================================
.. literalinclude:: ../../examples/cloud-config-ansible-managed.txt
:language: yaml
:linenos:
-Configure Instance to be An Ansible Controller
+Configure instance to be an Ansible controller
==============================================
.. literalinclude:: ../../examples/cloud-config-ansible-controller.txt
@@ -108,8 +105,8 @@ Adjust mount points mounted
:language: yaml
:linenos:
-Configure instances SSH keys
-============================
+``Configure instance's SSH keys``
+=================================
.. literalinclude:: ../../examples/cloud-config-ssh-keys.txt
:language: yaml
diff --git a/doc/rtd/reference/faq.rst b/doc/rtd/reference/faq.rst
new file mode 100644
index 00000000..46d37bb1
--- /dev/null
+++ b/doc/rtd/reference/faq.rst
@@ -0,0 +1,288 @@
+.. _faq:
+
+FAQ
+***
+
+How do I get help?
+==================
+
+Having trouble? We would like to help!
+
+- First go through this page with answers to common questions
+- Use the search bar at the upper left to search our documentation
+- Ask questions in the ``#cloud-init`` `IRC channel on Libera`_
+- Join and ask questions on the ``cloud-init`` `mailing list`_
+- Find a bug? Check out the :ref:`reporting_bugs` topic to find out how to
+ report one
+
+Where are the logs?
+===================
+
+``Cloud-init`` uses two files to log to:
+
+- :file:`/var/log/cloud-init-output.log`: Captures the output from each stage
+ of ``cloud-init`` when it runs.
+- :file:`/var/log/cloud-init.log`: Very detailed log with debugging output,
+ detailing each action taken.
+- :file:`/run/cloud-init`: contains logs about how ``cloud-init`` decided to
+ enable or disable itself, as well as what platforms/datasources were
+ detected. These logs are most useful when trying to determine what
+ ``cloud-init`` did or did not run.
+
+Be aware that each time a system boots, new logs are appended to the files in
+:file:`/var/log`. Therefore, the files may have information present from more
+than one boot.
+
+When reviewing these logs look for any errors or Python tracebacks to check
+for any errors.
+
+Where are the configuration files?
+==================================
+
+``Cloud-init`` config is provided in two places:
+
+- :file:`/etc/cloud/cloud.cfg`
+- :file:`/etc/cloud/cloud.cfg.d/*.cfg`
+
+These files can define the modules that run during instance initialisation,
+the datasources to evaluate on boot, as well as other settings.
+
+See the :ref:`configuration sources explanation<configuration>` and
+:ref:`configuration reference<base_config_reference>` pages for more details.
+
+Where are the data files?
+=========================
+
+Inside the :file:`/var/lib/cloud/` directory there are two important
+subdirectories:
+
+:file:`instance`
+----------------
+
+The :file:`/var/lib/cloud/instance` directory is a symbolic link that points
+to the most recently used :file:`instance-id` directory. This folder contains
+the information ``cloud-init`` received from datasources, including vendor and
+user data. This can be helpful to review to ensure the correct data was passed.
+
+It also contains the :file:`datasource` file that contains the full information
+about which datasource was identified and used to set up the system.
+
+Finally, the :file:`boot-finished` file is the last thing that
+``cloud-init`` does.
+
+:file:`data`
+------------
+
+The :file:`/var/lib/cloud/data` directory contain information related to the
+previous boot:
+
+* :file:`instance-id`: ID of the instance as discovered by ``cloud-init``.
+ Changing this file has no effect.
+* :file:`result.json`: JSON file that will show both the datasource used to
+ set up the instance, and whether any errors occurred.
+* :file:`status.json`: JSON file showing the datasource used, a breakdown of
+ all four modules, whether any errors occurred, and the start and stop times.
+
+What datasource am I using?
+===========================
+
+To correctly set up an instance, ``cloud-init`` must correctly identify the
+cloud that it is on. Therefore, knowing which datasource is used on an
+instance launch can aid in debugging.
+
+To find out which datasource is being used run the :command:`cloud-id` command:
+
+.. code-block:: shell-session
+
+ $ cloud-id
+
+This will tell you which datasource is being used, for example:
+
+.. code-block::
+
+ nocloud
+
+If the ``cloud-id`` is not what is expected, then running the
+:file:`ds-identify` script in debug mode and providing that in a bug can aid
+in resolving any issues:
+
+.. code-block:: shell-session
+
+ $ sudo DEBUG_LEVEL=2 DI_LOG=stderr /usr/lib/cloud-init/ds-identify --force
+
+The ``force`` parameter allows the command to be run again since the instance
+has already launched. The other options increase the verbosity of logging and
+put the logs to :file:`STDERR`.
+
+How can I re-run datasource detection and ``cloud-init``?
+=========================================================
+
+If a user is developing a new datasource or working on debugging an issue it
+may be useful to re-run datasource detection and the initial setup of
+``cloud-init``.
+
+To do this, force :file:`ds-identify` to re-run, clean up any logs, and
+re-run ``cloud-init``:
+
+.. code-block:: shell-session
+
+ $ sudo DI_LOG=stderr /usr/lib/cloud-init/ds-identify --force
+ $ sudo cloud-init clean --logs
+ $ sudo cloud-init init --local
+ $ sudo cloud-init init
+
+.. warning::
+
+ These commands will re-run ``cloud-init`` as if this were first boot of a
+ system: this will, at the very least, cycle SSH host keys and may do
+ substantially more. **Do not run these commands on production systems.**
+
+How can I debug my user data?
+=============================
+
+Two of the most common issues with user data, that also happens to be
+cloud-config is:
+
+1. Incorrectly formatted YAML
+2. First line does not contain ``#cloud-config``
+
+To verify your YAML, we do have a short script called `validate-yaml.py`_
+that can validate your user data offline.
+
+Another option is to run the following on an instance to debug user data
+provided to the system:
+
+.. code-block:: shell-session
+
+ $ cloud-init schema --system --annotate
+
+Why did ``cloud-init`` never complete?
+======================================
+
+To check if ``cloud-init`` is running still, run:
+
+.. code-block:: shell-session
+
+ $ cloud-init status
+
+To wait for ``cloud-init`` to complete, run:
+
+.. code-block:: shell-session
+
+ $ cloud-init status --wait
+
+There are a number of reasons that ``cloud-init`` might never complete. This
+list is not exhaustive, but attempts to enumerate potential causes:
+
+External reasons
+----------------
+
+- Failed dependent services in the boot.
+- Bugs in the kernel or drivers.
+- Bugs in external userspace tools that are called by ``cloud-init``.
+
+Internal reasons
+----------------
+
+- A command in ``bootcmd`` or ``runcmd`` that never completes (e.g., running
+ :command:`cloud-init status --wait` will wait forever on itself and never
+ complete).
+- Non-standard configurations that disable timeouts or set extremely high
+ values ("never" is used in a loose sense here).
+
+Failing to complete on ``systemd``
+----------------------------------
+
+``Cloud-init`` consists of multiple services on ``systemd``. If a service
+that ``cloud-init`` depends on stalls, ``cloud-init`` will not continue.
+If reporting a bug related to ``cloud-init`` failing to complete on
+``systemd``, please make sure to include the following logs.
+
+.. code-block:: shell-session
+
+ $ systemd-analyze critical-chain cloud-init.target
+ $ journalctl --boot=-1
+ $ systemctl --failed
+
+``autoinstall``, ``preruncmd``, ``postruncmd``
+==============================================
+
+Since ``cloud-init`` ignores top level user data ``cloud-config`` keys, other
+projects such as `Juju`_ and `Subiquity autoinstaller`_ use a YAML-formatted
+config that combines ``cloud-init``'s user data cloud-config YAML format with
+their custom YAML keys. Since ``cloud-init`` ignores unused top level keys,
+these combined YAML configurations may be valid ``cloud-config`` files,
+however keys such as ``autoinstall``, ``preruncmd``, and ``postruncmd`` are
+not used by ``cloud-init`` to configure anything.
+
+Please direct bugs and questions about other projects that use ``cloud-init``
+to their respective support channels. For Subiquity autoinstaller that is via
+IRC (``#ubuntu-server`` on Libera) or Discourse. For Juju support see their
+`discourse page`_.
+
+Where can I learn more?
+=======================
+
+Below are some videos, blog posts, and white papers about ``cloud-init`` from a
+variety of sources.
+
+Videos:
+
+- `cloud-init - The Good Parts`_
+- `Perfect Proxmox Template with Cloud Image and Cloud Init`_
+ [proxmox, cloud-init, template]
+- `cloud-init - Building clouds one Linux box at a time (Video)`_
+- `Metadata and cloud-init`_
+- `Introduction to cloud-init`_
+
+Blog Posts:
+
+- `cloud-init - The cross-cloud Magic Sauce (PDF)`_
+- `cloud-init - Building clouds one Linux box at a time (PDF)`_
+- `The beauty of cloud-init`_
+- `Cloud-init Getting Started`_ [fedora, libvirt, cloud-init]
+- `Build Azure Devops Agents With Linux cloud-init for Dotnet Development`_
+ [terraform, azure, devops, docker, dotnet, cloud-init]
+- `Cloud-init Getting Started`_ [fedora, libvirt, cloud-init]
+- `Setup Neovim cloud-init Completion`_
+ [neovim, yaml, Language Server Protocol, jsonschema, cloud-init]
+
+Events:
+
+- `cloud-init Summit 2019`_
+- `cloud-init Summit 2018`_
+- `cloud-init Summit 2017`_
+
+
+Whitepapers:
+
+- `Utilising cloud-init on Microsoft Azure (Whitepaper)`_
+- `Cloud Instance Initialization with cloud-init (Whitepaper)`_
+
+.. _mailing list: https://launchpad.net/~cloud-init
+.. _IRC channel on Libera: https://kiwiirc.com/nextclient/irc.libera.chat/cloud-init
+.. _validate-yaml.py: https://github.com/canonical/cloud-init/blob/main/tools/validate-yaml.py
+.. _Juju: https://ubuntu.com/blog/topics/juju
+.. _discourse page: https://discourse.charmhub.io
+
+.. _cloud-init - The Good Parts: https://www.youtube.com/watch?v=2_m6EUo6VOI
+.. _Utilising cloud-init on Microsoft Azure (Whitepaper): https://ubuntu.com/engage/azure-cloud-init-whitepaper
+.. _Cloud Instance Initialization with cloud-init (Whitepaper): https://ubuntu.com/blog/cloud-instance-initialisation-with-cloud-init
+
+.. _cloud-init - The cross-cloud Magic Sauce (PDF): https://events.linuxfoundation.org/wp-content/uploads/2017/12/cloud-init-The-cross-cloud-Magic-Sauce-Scott-Moser-Chad-Smith-Canonical.pdf
+.. _cloud-init - Building clouds one Linux box at a time (Video): https://www.youtube.com/watch?v=1joQfUZQcPg
+.. _cloud-init - Building clouds one Linux box at a time (PDF): https://web.archive.org/web/20181111020605/https://annex.debconf.org/debconf-share/debconf17/slides/164-cloud-init_Building_clouds_one_Linux_box_at_a_time.pdf
+.. _Metadata and cloud-init: https://www.youtube.com/watch?v=RHVhIWifVqU
+.. _The beauty of cloud-init: https://web.archive.org/web/20180830161317/http://brandon.fuller.name/archives/2011/05/02/06.40.57/
+.. _Introduction to cloud-init: http://www.youtube.com/watch?v=-zL3BdbKyGY
+.. _Build Azure Devops Agents With Linux cloud-init for Dotnet Development: https://codingsoul.org/2022/04/25/build-azure-devops-agents-with-linux-cloud-init-for-dotnet-development/
+.. _Perfect Proxmox Template with Cloud Image and Cloud Init: https://www.youtube.com/watch?v=shiIi38cJe4
+.. _Cloud-init Getting Started: https://blog.while-true-do.io/cloud-init-getting-started/
+.. _Setup Neovim cloud-init Completion: https://phoenix-labs.xyz/blog/setup-neovim-cloud-init-completion/
+
+.. _cloud-init Summit 2019: https://powersj.io/post/cloud-init-summit19/
+.. _cloud-init Summit 2018: https://powersj.io/post/cloud-init-summit18/
+.. _cloud-init Summit 2017: https://powersj.io/post/cloud-init-summit17/
+.. _Subiquity autoinstaller: https://ubuntu.com/server/docs/install/autoinstall
+.. _juju_project: https://discourse.charmhub.io/t/model-config-cloudinit-userdata/512
+.. _discourse page: https://discourse.charmhub.io
diff --git a/doc/rtd/reference/index.rst b/doc/rtd/reference/index.rst
new file mode 100644
index 00000000..5610490b
--- /dev/null
+++ b/doc/rtd/reference/index.rst
@@ -0,0 +1,21 @@
+Reference
+*********
+
+Our reference section contains support information for ``cloud-init``.
+This includes details on the network requirements, API definitions, support
+matrices and so on.
+
+-----
+
+.. toctree::
+ :maxdepth: 1
+
+ modules.rst
+ examples.rst
+ cli.rst
+ availability.rst
+ faq.rst
+ merging.rst
+ datasources.rst
+ network-config.rst
+ base_config_reference.rst
diff --git a/doc/rtd/reference/merging.rst b/doc/rtd/reference/merging.rst
new file mode 100644
index 00000000..62efffdb
--- /dev/null
+++ b/doc/rtd/reference/merging.rst
@@ -0,0 +1,292 @@
+.. _merging_user_data:
+
+Merging user data sections
+**************************
+
+The ability to merge user data sections is a feature that was implemented by
+popular request. It was identified that there should be a way to specify how
+cloud-config YAML "dictionaries" provided as user data are handled when there
+are multiple YAML files to be merged together (e.g., when performing an
+#include).
+
+The previous merging algorithm was very simple and would only overwrite
+(and not append). So, it was decided to create a new and improved way to merge
+dictionaries (and their contained objects) together in a customisable way,
+thus allowing users who provide cloud-config user data to determine exactly
+how their objects will be merged.
+
+For example:
+
+.. code-block:: yaml
+
+ #cloud-config (1)
+ runcmd:
+ - bash1
+ - bash2
+
+ #cloud-config (2)
+ runcmd:
+ - bash3
+ - bash4
+
+The previous way of merging the two objects above would result in a final
+cloud-config object that contains the following:
+
+.. code-block:: yaml
+
+ #cloud-config (merged)
+ runcmd:
+ - bash3
+ - bash4
+
+Typically this is not what users want - instead they would prefer:
+
+.. code-block:: yaml
+
+ #cloud-config (merged)
+ runcmd:
+ - bash1
+ - bash2
+ - bash3
+ - bash4
+
+This change makes it easier to combine the various cloud-config objects you
+have into a more useful list. In this way, we reduce the duplication necessary
+to accomplish the same result with the previous method.
+
+Built-in mergers
+================
+
+``Cloud-init`` provides merging for the following built-in types:
+
+- :command:`Dict`
+- :command:`List`
+- :command:`String`
+
+``Dict``
+--------
+
+The :command:`Dict` merger has the following options, which control what is
+done with values contained within the config.
+
+- :command:`allow_delete`: Existing values not present in the new value can be
+ deleted. Defaults to ``False``.
+- :command:`no_replace`: Do not replace an existing value if one is already
+ present. Enabled by default.
+- :command:`replace`: Overwrite existing values with new ones.
+
+``List``
+--------
+
+The :command:`List` merger has the following options, which control what is
+done with the values contained within the config.
+
+- :command:`append`: Add new value to the end of the list. Defaults to
+ ``False``.
+- :command:`prepend`: Add new values to the start of the list. Defaults to
+ ``False``.
+- :command:`no_replace`: Do not replace an existing value if one is already
+ present. Enabled by default.
+- :command:`replace`: Overwrite existing values with new ones.
+
+String
+------
+
+The :command:`Str` merger has the following options, which control what is
+done with the values contained within the config.
+
+- :command:`append`: Add new value to the end of the string. Defaults to
+ False.
+
+Common options
+--------------
+
+These are the common options for all merge types, which control how recursive
+merging is done on other types.
+
+- :command:`recurse_dict`: If ``True``, merge the new values of the
+ dictionary. Defaults to ``True``.
+- :command:`recurse_list`: If ``True``, merge the new values of the list.
+ Defaults to ``False``.
+- :command:`recurse_array`: Alias for ``recurse_list``.
+- :command:`recurse_str`: If ``True``, merge the new values of the string.
+ Defaults to False.
+
+Customisation
+=============
+
+Because the above merging algorithm may not always be desired (just as the
+previous merging algorithm was not always the preferred one), the concept of
+customised merging was introduced through `merge classes`.
+
+A `merge class` is a class definition providing functions that can be used
+to merge a given type with another given type.
+
+An example of one of these `merging classes` is the following:
+
+.. code-block:: python
+
+ class Merger:
+ def __init__(self, merger, opts):
+ self._merger = merger
+ self._overwrite = 'overwrite' in opts
+
+ # This merging algorithm will attempt to merge with
+ # another dictionary, on encountering any other type of object
+ # it will not merge with said object, but will instead return
+ # the original value
+ #
+ # On encountering a dictionary, it will create a new dictionary
+ # composed of the original and the one to merge with, if 'overwrite'
+ # is enabled then keys that exist in the original will be overwritten
+ # by keys in the one to merge with (and associated values). Otherwise
+ # if not in overwrite mode the 2 conflicting keys themselves will
+ # be merged.
+ def _on_dict(self, value, merge_with):
+ if not isinstance(merge_with, (dict)):
+ return value
+ merged = dict(value)
+ for (k, v) in merge_with.items():
+ if k in merged:
+ if not self._overwrite:
+ merged[k] = self._merger.merge(merged[k], v)
+ else:
+ merged[k] = v
+ else:
+ merged[k] = v
+ return merged
+
+As you can see, there is an ``_on_dict`` method here that will be given a
+source value, and a value to merge with. The result will be the merged object.
+
+This code itself is called by another merging class which "directs" the
+merging to happen by analysing the object types to merge, and attempting to
+find a known object that will merge that type. An example of this can be found
+in the :file:`mergers/__init__.py` file (see ``LookupMerger`` and
+``UnknownMerger``).
+
+So, following the typical ``cloud-init`` approach of allowing source code to
+be downloaded and used dynamically, it is possible for users to inject their
+own merging files to handle specific types of merging as they choose (the
+basic ones included will handle lists, dicts, and strings). Note how each
+merge can have options associated with it, which affect how the merging is
+performed. For example, a dictionary merger can be told to overwrite instead
+of attempting to merge, or a string merger can be told to append strings
+instead of discarding other strings to merge with.
+
+How to activate
+===============
+
+There are a few ways to activate the merging algorithms, and to customise them
+for your own usage.
+
+1. The first way involves the usage of MIME messages in ``cloud-init`` to
+ specify multi-part documents (this is one way in which multiple
+ cloud-config can be joined together into a single cloud-config). Two new
+ headers are looked for, both of which can define the way merging is done
+ (the first header to exist "wins"). These new headers (in lookup order) are
+ ``'Merge-Type'`` and ``'X-Merge-Type'``. The value should be a string which
+ will satisfy the new merging format definition (see below for this format).
+
+2. The second way is to specify the `merge type` in the body of the
+ cloud-config dictionary. There are two ways to specify this; either as a
+ string, or as a dictionary (see format below). The keys that are looked up
+ for this definition are the following (in order): ``'merge_how'``,
+ ``'merge_type'``.
+
+String format
+-------------
+
+The following string format is expected: ::
+
+ classname1(option1,option2)+classname2(option3,option4)....
+
+The ``class name`` will be connected to class names used when looking for
+the class that can be used to merge, and options provided will be given to the
+class upon construction of that class.
+
+The following example shows the default string that gets used when none is
+otherwise provided: ::
+
+ list()+dict()+str()
+
+Dictionary format
+-----------------
+
+A dictionary can be used when it specifies the same information as the
+string format (i.e., the second option above). For example:
+
+.. code-block:: python
+
+ {'merge_how': [{'name': 'list', 'settings': ['append']},
+ {'name': 'dict', 'settings': ['no_replace', 'recurse_list']},
+ {'name': 'str', 'settings': ['append']}]}
+
+This would be the dictionary equivalent of the default string format.
+
+Specifying multiple types, and what this does
+=============================================
+
+Now you may be asking yourself: "What exactly happens if I specify a
+``merge-type`` header or dictionary for every cloud-config I provide?"
+
+The answer is that when merging, a stack of ``'merging classes'`` is kept. The
+first one in the stack is the default merging class. This set of mergers
+will be used when the first cloud-config is merged with the initial empty
+cloud-config dictionary. If the cloud-config that was just merged provided a
+set of merging classes (via the above formats) then those merging classes will
+be pushed onto the stack. Now if there is a second cloud-config to be merged
+then the merging classes from the cloud-config before the first will be used
+(not the default) and so on. In this way a cloud-config can decide how it will
+merge with a cloud-config dictionary coming after it.
+
+Other uses
+==========
+
+In addition to being used for merging user data sections, the default merging
+algorithm for merging :file:`'conf.d'` YAML files (which form an initial YAML
+config for ``cloud-init``) was also changed to use this mechanism, to take
+advantage of the full benefits (and customisation) here as well. Other places
+that used the previous merging are also, similarly, now extensible (metadata
+merging, for example).
+
+Note, however, that merge algorithms are not used *across* configuration types.
+As was the case before merging was implemented, user data will overwrite
+:file:`'conf.d'` configuration without merging.
+
+Example cloud-config
+====================
+
+A common request is to include multiple ``runcmd`` directives in different
+files and merge all of the commands together. To achieve this, we must modify
+the default merging to allow for dictionaries to join list values.
+
+The first config:
+
+.. code-block:: yaml
+
+ #cloud-config
+ merge_how:
+ - name: list
+ settings: [append]
+ - name: dict
+ settings: [no_replace, recurse_list]
+
+ runcmd:
+ - bash1
+ - bash2
+
+The second config:
+
+.. code-block:: yaml
+
+ #cloud-config
+ merge_how:
+ - name: list
+ settings: [append]
+ - name: dict
+ settings: [no_replace, recurse_list]
+
+ runcmd:
+ - bash3
+ - bash4
diff --git a/doc/rtd/topics/modules.rst b/doc/rtd/reference/modules.rst
index 209cf6e8..dc3a6c59 100644
--- a/doc/rtd/topics/modules.rst
+++ b/doc/rtd/reference/modules.rst
@@ -1,7 +1,6 @@
.. _modules:
-
-Module Reference
+Module reference
****************
.. automodule:: cloudinit.config.cc_ansible
@@ -13,6 +12,9 @@ Module Reference
.. automodule:: cloudinit.config.cc_ca_certs
.. automodule:: cloudinit.config.cc_chef
.. automodule:: cloudinit.config.cc_disable_ec2_metadata
+
+.. _mod-disk_setup:
+
.. automodule:: cloudinit.config.cc_disk_setup
.. automodule:: cloudinit.config.cc_fan
.. automodule:: cloudinit.config.cc_final_message
@@ -27,6 +29,9 @@ Module Reference
.. automodule:: cloudinit.config.cc_mcollective
.. automodule:: cloudinit.config.cc_migrator
.. automodule:: cloudinit.config.cc_mounts
+
+.. _mod-ntp:
+
.. automodule:: cloudinit.config.cc_ntp
.. automodule:: cloudinit.config.cc_package_update_upgrade_install
.. automodule:: cloudinit.config.cc_phone_home
@@ -36,6 +41,9 @@ Module Reference
.. automodule:: cloudinit.config.cc_resolv_conf
.. automodule:: cloudinit.config.cc_rh_subscription
.. automodule:: cloudinit.config.cc_rightscale_userdata
+
+.. _mod-rsyslog:
+
.. automodule:: cloudinit.config.cc_rsyslog
.. _mod-runcmd:
@@ -49,6 +57,9 @@ Module Reference
.. automodule:: cloudinit.config.cc_scripts_vendor
.. automodule:: cloudinit.config.cc_seed_random
.. automodule:: cloudinit.config.cc_set_hostname
+
+.. _mod-set_passwords:
+
.. automodule:: cloudinit.config.cc_set_passwords
.. automodule:: cloudinit.config.cc_snap
.. automodule:: cloudinit.config.cc_spacewalk
@@ -68,4 +79,3 @@ Module Reference
.. automodule:: cloudinit.config.cc_write_files
.. automodule:: cloudinit.config.cc_yum_add_repo
.. automodule:: cloudinit.config.cc_zypper_add_repo
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/network-config-format-eni.rst b/doc/rtd/reference/network-config-format-eni.rst
index 94fa0f9e..f89fdb46 100644
--- a/doc/rtd/topics/network-config-format-eni.rst
+++ b/doc/rtd/reference/network-config-format-eni.rst
@@ -1,20 +1,21 @@
.. _network_config_eni:
-Network Configuration ENI (Legacy)
-----------------------------------
+Network configuration ENI (legacy)
+**********************************
-`Cloud-init`_ supports reading and writing network config in the ``ENI``
+``Cloud-init`` supports reading and writing network config in the ``ENI``
format which is consumed by the ``ifupdown`` tool to parse and apply network
configuration.
-As an input format this is **legacy**. In cases where ENI format is available
-and another format is also available, it will prefer to use the other format.
+As an input format this is **legacy**. In cases where ENI format is available
+and another format is also available, ``cloud-init`` will prefer to use the
+other, newer format.
+
This can happen in either :ref:`datasource_nocloud` or
:ref:`datasource_openstack` datasources.
Please reference existing `documentation`_ for the
-``/etc/network/interfaces(5)`` format.
+:file:`/etc/network/interfaces(5)` format.
.. _Cloud-init: https://launchpad.net/cloud-init
.. _documentation: http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html
-.. vi: textwidth=79
diff --git a/doc/rtd/reference/network-config-format-v1.rst b/doc/rtd/reference/network-config-format-v1.rst
new file mode 100644
index 00000000..0475df9d
--- /dev/null
+++ b/doc/rtd/reference/network-config-format-v1.rst
@@ -0,0 +1,647 @@
+.. _network_config_v1:
+
+Networking config Version 1
+***************************
+
+This network configuration format lets users customise their instance's
+networking interfaces by assigning subnet configuration, virtual device
+creation (bonds, bridges, VLANs) routes and DNS configuration.
+
+Required elements of a `network config Version 1` are ``config`` and
+``version``.
+
+``Cloud-init`` will read this format from :ref:`base_config_reference`.
+
+For example, the following could be present in
+:file:`/etc/cloud/cloud.cfg.d/custom-networking.cfg`:
+
+.. code-block:: yaml
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: eth0
+ subnets:
+ - type: dhcp
+
+The :ref:`datasource_nocloud` datasource can also provide ``cloud-init``
+networking configuration in this format.
+
+Configuration types
+===================
+
+Within the network ``config`` portion, users include a list of configuration
+types. The current list of support ``type`` values are as follows:
+
+- ``physical``: Physical
+- ``bond``: Bond
+- ``bridge``: Bridge
+- ``vlan``: VLAN
+- ``nameserver``: Nameserver
+- ``route``: Route
+
+Physical, Bond, Bridge and VLAN types may also include IP configuration under
+the key ``subnets``.
+
+- ``subnets``: Subnet/IP
+
+Physical
+--------
+
+The ``physical`` type configuration represents a "physical" network device,
+typically Ethernet-based. At least one of these entries is required for
+external network connectivity. Type ``physical`` requires only one key:
+``name``. A ``physical`` device may contain some or all of the following
+keys:
+
+``name: <desired device name>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A device's name must be less than 15 characters. Names exceeding the maximum
+will be truncated. This is a limitation of the Linux kernel network-device
+structure.
+
+``mac_address: <MAC Address>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The MAC Address is a device unique identifier that most Ethernet-based network
+devices possess. Specifying a MAC Address is optional.
+Letters must be lowercase.
+
+.. note::
+ It is best practice to "quote" all MAC addresses, since an unquoted MAC
+ address might be incorrectly interpreted as an integer in `YAML`_.
+
+.. note::
+ ``Cloud-init`` will handle the persistent mapping between a device's
+ ``name`` and the ``mac_address``.
+
+``mtu: <MTU SizeBytes>``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The MTU key represents a device's Maximum Transmission Unit, which is the
+largest size packet or frame, specified in octets (eight-bit bytes), that can
+be sent in a packet- or frame-based network. Specifying ``mtu`` is optional.
+
+.. note::
+ The possible supported values of a device's MTU are not available at
+ configuration time. It's possible to specify a value too large or to
+ small for a device, and may be ignored by the device.
+
+Physical example
+^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ # Simple network adapter
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ # Second nic with Jumbo frames
+ - type: physical
+ name: jumbo0
+ mac_address: 'aa:11:22:33:44:55'
+ mtu: 9000
+ # 10G pair
+ - type: physical
+ name: gbe0
+ mac_address: 'cd:11:22:33:44:00'
+ - type: physical
+ name: gbe1
+ mac_address: 'cd:11:22:33:44:02'
+
+Bond
+----
+
+A ``bond`` type will configure a Linux software Bond with one or more network
+devices. A ``bond`` type requires the following keys:
+
+``name: <desired device name>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A device's name must be less than 15 characters. Names exceeding the maximum
+will be truncated. This is a limitation of the Linux kernel network-device
+structure.
+
+``mac_address: <MAC Address>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When specifying MAC Address on a bond this value will be assigned to the bond
+device and may be different than the MAC address of any of the underlying
+bond interfaces. Specifying a MAC Address is optional. If ``mac_address`` is
+not present, then the bond will use one of the MAC Address values from one of
+the bond interfaces.
+
+.. note::
+ It is best practice to "quote" all MAC addresses, since an unquoted MAC
+ address might be incorrectly interpreted as an integer in `YAML`_.
+
+``bond_interfaces: <List of network device names>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``bond_interfaces`` key accepts a list of network device ``name`` values
+from the configuration. This list may be empty.
+
+``mtu: <MTU SizeBytes>``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The MTU key represents a device's Maximum Transmission Unit, the largest size
+packet or frame, specified in octets (eight-bit bytes), that can be sent in a
+packet- or frame-based network. Specifying ``mtu`` is optional.
+
+.. note::
+ The possible supported values of a device's MTU are not available at
+ configuration time. It's possible to specify a value too large or to
+ small for a device, and may be ignored by the device.
+
+``params: <Dictionary of key: value bonding parameter pairs>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The ``params`` key in a bond holds a dictionary of bonding parameters.
+This dictionary may be empty. For more details on what the various bonding
+parameters mean please read the Linux Kernel :file:`Bonding.txt`.
+
+Valid ``params`` keys are:
+
+ - ``active_slave``: Set bond attribute
+ - ``ad_actor_key``: Set bond attribute
+ - ``ad_actor_sys_prio``: Set bond attribute
+ - ``ad_actor_system``: Set bond attribute
+ - ``ad_aggregator``: Set bond attribute
+ - ``ad_num_ports``: Set bond attribute
+ - ``ad_partner_key``: Set bond attribute
+ - ``ad_partner_mac``: Set bond attribute
+ - ``ad_select``: Set bond attribute
+ - ``ad_user_port_key``: Set bond attribute
+ - ``all_slaves_active``: Set bond attribute
+ - ``arp_all_targets``: Set bond attribute
+ - ``arp_interval``: Set bond attribute
+ - ``arp_ip_target``: Set bond attribute
+ - ``arp_validate``: Set bond attribute
+ - ``downdelay``: Set bond attribute
+ - ``fail_over_mac``: Set bond attribute
+ - ``lacp_rate``: Set bond attribute
+ - ``lp_interval``: Set bond attribute
+ - ``miimon``: Set bond attribute
+ - ``mii_status``: Set bond attribute
+ - ``min_links``: Set bond attribute
+ - ``mode``: Set bond attribute
+ - ``num_grat_arp``: Set bond attribute
+ - ``num_unsol_na``: Set bond attribute
+ - ``packets_per_slave``: Set bond attribute
+ - ``primary``: Set bond attribute
+ - ``primary_reselect``: Set bond attribute
+ - ``queue_id``: Set bond attribute
+ - ``resend_igmp``: Set bond attribute
+ - ``slaves``: Set bond attribute
+ - ``tlb_dynamic_lb``: Set bond attribute
+ - ``updelay``: Set bond attribute
+ - ``use_carrier``: Set bond attribute
+ - ``xmit_hash_policy``: Set bond attribute
+
+Bond example
+^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ # Simple network adapter
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ # 10G pair
+ - type: physical
+ name: gbe0
+ mac_address: 'cd:11:22:33:44:00'
+ - type: physical
+ name: gbe1
+ mac_address: 'cd:11:22:33:44:02'
+ - type: bond
+ name: bond0
+ bond_interfaces:
+ - gbe0
+ - gbe1
+ params:
+ bond-mode: active-backup
+
+Bridge
+------
+
+Type ``bridge`` requires the following keys:
+
+- ``name``: Set the name of the bridge.
+- ``bridge_interfaces``: Specify the ports of a bridge via their ``name``.
+ This list may be empty.
+- ``params``: A list of bridge params. For more details, please read the
+ ``bridge-utils-interfaces`` manpage.
+
+Valid keys are:
+
+ - ``bridge_ageing``: Set the bridge's ageing value.
+ - ``bridge_bridgeprio``: Set the bridge device network priority.
+ - ``bridge_fd``: Set the bridge's forward delay.
+ - ``bridge_hello``: Set the bridge's hello value.
+ - ``bridge_hw``: Set the bridge's MAC address.
+ - ``bridge_maxage``: Set the bridge's maxage value.
+ - ``bridge_maxwait``: Set how long network scripts should wait for the
+ bridge to be up.
+ - ``bridge_pathcost``: Set the cost of a specific port on the bridge.
+ - ``bridge_portprio``: Set the priority of a specific port on the bridge.
+ - ``bridge_ports``: List of devices that are part of the bridge.
+ - ``bridge_stp``: Set spanning tree protocol on or off.
+ - ``bridge_waitport``: Set amount of time in seconds to wait on specific
+ ports to become available.
+
+Bridge example
+^^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ # Simple network adapter
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ # Second nic with Jumbo frames
+ - type: physical
+ name: jumbo0
+ mac_address: 'aa:11:22:33:44:55'
+ mtu: 9000
+ - type: bridge
+ name: br0
+ bridge_interfaces:
+ - jumbo0
+ params:
+ bridge_ageing: 250
+ bridge_bridgeprio: 22
+ bridge_fd: 1
+ bridge_hello: 1
+ bridge_maxage: 10
+ bridge_maxwait: 0
+ bridge_pathcost:
+ - jumbo0 75
+ bridge_pathprio:
+ - jumbo0 28
+ bridge_stp: 'off'
+ bridge_maxwait:
+ - jumbo0 0
+
+VLAN
+----
+
+Type ``vlan`` requires the following keys:
+
+- ``name``: Set the name of the VLAN
+- ``vlan_link``: Specify the underlying link via its ``name``.
+- ``vlan_id``: Specify the VLAN numeric id.
+
+The following optional keys are supported:
+
+``mtu: <MTU SizeBytes>``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The MTU key represents a device's Maximum Transmission Unit, the largest size
+packet or frame, specified in octets (eight-bit bytes), that can be sent in a
+packet- or frame-based network. Specifying ``mtu`` is optional.
+
+.. note::
+ The possible supported values of a device's MTU are not available at
+ configuration time. It's possible to specify a value too large or to
+ small for a device and may be ignored by the device.
+
+VLAN example
+^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ # Physical interfaces.
+ - type: physical
+ name: eth0
+ mac_address: 'c0:d6:9f:2c:e8:80'
+ # VLAN interface.
+ - type: vlan
+ name: eth0.101
+ vlan_link: eth0
+ vlan_id: 101
+ mtu: 1500
+
+Nameserver
+----------
+
+Users can specify a ``nameserver`` type. Nameserver dictionaries include
+the following keys:
+
+- ``address``: List of IPv4 or IPv6 address of nameservers.
+- ``search``: List of hostnames to include in the :file:`resolv.conf` search
+ path.
+- ``interface``: Optional. Ties the nameserver definition to the specified
+ interface. The value specified here must match the ``name`` of an interface
+ defined in this config. If unspecified, this nameserver will be considered
+ a global nameserver.
+
+Nameserver example
+^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ subnets:
+ - type: static
+ address: 192.168.23.14/27
+ gateway: 192.168.23.1
+ - type: nameserver
+ interface: interface0 # Ties nameserver to interface0 only
+ address:
+ - 192.168.23.2
+ - 8.8.8.8
+ search:
+ - exemplary
+
+Route
+-----
+
+Users can include static routing information as well. A ``route`` dictionary
+has the following keys:
+
+- ``destination``: IPv4 network address with CIDR netmask notation.
+- ``gateway``: IPv4 gateway address with CIDR netmask notation.
+- ``metric``: Integer which sets the network metric value for this route.
+
+Route example
+^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ subnets:
+ - type: static
+ address: 192.168.23.14/24
+ gateway: 192.168.23.1
+ - type: route
+ destination: 192.168.24.0/24
+ gateway: 192.168.24.1
+ metric: 3
+
+Subnet/IP
+---------
+
+For any network device (one of the "config types") users can define a list of
+``subnets`` which contain ip configuration dictionaries. Multiple subnet
+entries will create interface aliases, allowing a single interface to use
+different ip configurations.
+
+Valid keys for ``subnets`` include the following:
+
+- ``type``: Specify the subnet type.
+- ``control``: Specify 'manual', 'auto' or 'hotplug'. Indicates how the
+ interface will be handled during boot.
+- ``address``: IPv4 or IPv6 address. It may include CIDR netmask notation.
+- ``netmask``: IPv4 subnet mask in dotted format or CIDR notation.
+- ``gateway``: IPv4 address of the default gateway for this subnet.
+- ``dns_nameservers``: Specify a list of IPv4 dns server IPs to end up in
+ :file:`resolv.conf`.
+- ``dns_search``: Specify a list of search paths to be included in
+ :file:`resolv.conf`.
+- ``routes``: Specify a list of routes for a given interface.
+
+Subnet types are one of the following:
+
+- ``dhcp4``: Configure this interface with IPv4 dhcp.
+- ``dhcp``: Alias for ``dhcp4``.
+- ``dhcp6``: Configure this interface with IPv6 dhcp.
+- ``static``: Configure this interface with a static IPv4.
+- ``static6``: Configure this interface with a static IPv6.
+- ``ipv6_dhcpv6-stateful``: Configure this interface with ``dhcp6``.
+- ``ipv6_dhcpv6-stateless``: Configure this interface with SLAAC and DHCP.
+- ``ipv6_slaac``: Configure address with SLAAC.
+
+When making use of ``dhcp`` or either of the ``ipv6_dhcpv6`` types,
+no additional configuration is needed in the subnet dictionary.
+
+Using ``ipv6_dhcpv6-stateless`` or ``ipv6_slaac`` allows the IPv6 address to be
+automatically configured with StateLess Address AutoConfiguration (`SLAAC`_).
+SLAAC requires support from the network, so verify that your cloud or network
+offering has support before trying it out. With ``ipv6_dhcpv6-stateless``,
+DHCPv6 is still used to fetch other subnet details such as gateway or DNS
+servers. If you only want to discover the address, use ``ipv6_slaac``.
+
+Subnet DHCP example
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ subnets:
+ - type: dhcp
+
+Subnet static example
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ subnets:
+ - type: static
+ address: 192.168.23.14/27
+ gateway: 192.168.23.1
+ dns_nameservers:
+ - 192.168.23.2
+ - 8.8.8.8
+ dns_search:
+ - exemplary.maas
+
+Multiple subnet example
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The following will result in an ``interface0`` using DHCP and ``interface0:1``
+using the static subnet configuration:
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ subnets:
+ - type: dhcp
+ - type: static
+ address: 192.168.23.14/27
+ gateway: 192.168.23.1
+ dns_nameservers:
+ - 192.168.23.2
+ - 8.8.8.8
+ dns_search:
+ - exemplary
+
+Subnet with routes example
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - type: physical
+ name: interface0
+ mac_address: '00:11:22:33:44:55'
+ subnets:
+ - type: dhcp
+ - type: static
+ address: 10.184.225.122
+ netmask: 255.255.255.252
+ routes:
+ - gateway: 10.184.225.121
+ netmask: 255.240.0.0
+ network: 10.176.0.0
+ - gateway: 10.184.225.121
+ netmask: 255.240.0.0
+ network: 10.208.0.0
+
+
+Multi-layered configurations
+============================
+
+Complex networking sometimes uses layers of configuration. The syntax allows
+users to build those layers one at a time. All of the virtual network devices
+supported allow specifying an underlying device by their ``name`` value.
+
+Bonded VLAN example
+-------------------
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ # 10G pair
+ - type: physical
+ name: gbe0
+ mac_address: 'cd:11:22:33:44:00'
+ - type: physical
+ name: gbe1
+ mac_address: 'cd:11:22:33:44:02'
+ # Bond.
+ - type: bond
+ name: bond0
+ bond_interfaces:
+ - gbe0
+ - gbe1
+ params:
+ bond-mode: 802.3ad
+ bond-lacp-rate: fast
+ # A Bond VLAN.
+ - type: vlan
+ name: bond0.200
+ vlan_link: bond0
+ vlan_id: 200
+ subnets:
+ - type: dhcp4
+
+Multiple VLAN example
+---------------------
+
+.. code-block::
+
+ network:
+ version: 1
+ config:
+ - id: eth0
+ mac_address: 'd4:be:d9:a8:49:13'
+ mtu: 1500
+ name: eth0
+ subnets:
+ - address: 10.245.168.16/21
+ dns_nameservers:
+ - 10.245.168.2
+ gateway: 10.245.168.1
+ type: static
+ type: physical
+ - id: eth1
+ mac_address: 'd4:be:d9:a8:49:15'
+ mtu: 1500
+ name: eth1
+ subnets:
+ - address: 10.245.188.2/24
+ dns_nameservers: []
+ type: static
+ type: physical
+ - id: eth1.2667
+ mtu: 1500
+ name: eth1.2667
+ subnets:
+ - address: 10.245.184.2/24
+ dns_nameservers: []
+ type: static
+ type: vlan
+ vlan_id: 2667
+ vlan_link: eth1
+ - id: eth1.2668
+ mtu: 1500
+ name: eth1.2668
+ subnets:
+ - address: 10.245.185.1/24
+ dns_nameservers: []
+ type: static
+ type: vlan
+ vlan_id: 2668
+ vlan_link: eth1
+ - id: eth1.2669
+ mtu: 1500
+ name: eth1.2669
+ subnets:
+ - address: 10.245.186.1/24
+ dns_nameservers: []
+ type: static
+ type: vlan
+ vlan_id: 2669
+ vlan_link: eth1
+ - id: eth1.2670
+ mtu: 1500
+ name: eth1.2670
+ subnets:
+ - address: 10.245.187.2/24
+ dns_nameservers: []
+ type: static
+ type: vlan
+ vlan_id: 2670
+ vlan_link: eth1
+ - address: 10.245.168.2
+ search:
+ - dellstack
+ type: nameserver
+
+.. _SLAAC: https://tools.ietf.org/html/rfc4862
+
+.. _YAML: https://yaml.org/type/int.html
diff --git a/doc/rtd/topics/network-config-format-v2.rst b/doc/rtd/reference/network-config-format-v2.rst
index 924ccf87..7469524b 100644
--- a/doc/rtd/topics/network-config-format-v2.rst
+++ b/doc/rtd/reference/network-config-format-v2.rst
@@ -1,21 +1,22 @@
.. _network_config_v2:
-Networking Config Version 2
-===========================
+Networking config Version 2
+***************************
-Cloud-init's support for Version 2 network config is a subset of the
-version 2 format defined for the `netplan`_ tool. Cloud-init supports
-both reading and writing of Version 2; the latter support requires a
-distro with `netplan`_ present.
+``Cloud-init``'s support for Version 2 network config is a subset of the
+Version 2 format defined for the `Netplan`_ tool. ``Cloud-init`` supports
+both reading and writing of Version 2. Writing support requires a
+distro with Netplan present.
-.. _Netplan Passthrough:
+.. _Netplan_passthrough:
-Netplan Passthrough
--------------------
+Netplan passthrough
+===================
-On a system with netplan present, cloud-init will pass Version 2 configuration
-through to netplan without modification. On such systems, you do not need to
-limit yourself to the below subset of netplan's configuration format.
+On a system with Netplan present, ``cloud-init`` will pass Version 2
+configuration through to Netplan without modification. On such systems, you do
+not need to limit yourself to the below subset of Netplan's configuration
+format.
.. warning::
If you are writing or generating network configuration that may be used on
@@ -23,39 +24,37 @@ limit yourself to the below subset of netplan's configuration format.
this document, or you will see network configuration failures on
non-netplan systems.
-Version 2 Configuration Format
-------------------------------
+Version 2 configuration format
+==============================
-The ``network`` key has at least two required elements. First
-it must include ``version: 2`` and one or more of possible device
-``types``.
+The ``network`` key has at least two required elements. First, it must include
+``version: 2`` and one or more of possible device ``types``.
-Cloud-init will read this format from :ref:`base_config_reference`.
+``Cloud-init`` will read this format from :ref:`base_config_reference`.
For example the following could be present in
-``/etc/cloud/cloud.cfg.d/custom-networking.cfg``::
+:file:`/etc/cloud/cloud.cfg.d/custom-networking.cfg`: ::
network:
version: 2
ethernets: []
It may also be provided in other locations including the
-:ref:`datasource_nocloud`, see :ref:`network_config` for other places.
+:ref:`datasource_nocloud`. See :ref:`network_config` for other places.
Supported device ``types`` values are as follows:
-- Ethernets (``ethernets``)
-- Bonds (``bonds``)
-- Bridges (``bridges``)
-- VLANs (``vlans``)
-
-Each type block contains device definitions as a map where the keys (called
-"configuration IDs"). Each entry under the ``types`` may include IP and/or
-device configuration.
+- ``ethernets``: Ethernets
+- ``bonds``: Bonds
+- ``bridges``: Bridges
+- ``vlans``: VLANs
+Each ``type`` block contains device definitions as a map (where the keys are
+called "configuration IDs"). Each entry under the ``types`` may include IP
+and/or device configuration.
Device configuration IDs
-------------------------
+========================
The key names below the per-device-type definition maps (like ``ethernets:``)
are called "ID"s. They must be unique throughout the entire set of
@@ -66,132 +65,142 @@ currently being defined.
There are two physically/structurally different classes of device definitions,
and the ID field has a different interpretation for each:
-Physical devices (Examples: ethernet, wifi):
- These can dynamically come and go between
- reboots and even during runtime (hotplugging). In the generic case, they
- can be selected by ``match:`` rules on desired properties, such as
- name/name pattern, MAC address, driver, or device paths. In general these
- will match any number of devices (unless they refer to properties which are
- unique such as the full path or MAC address), so without further knowledge
- about the hardware these will always be considered as a group.
-
- It is valid to specify no match rules at all, in which case the ID field is
- simply the interface name to be matched. This is mostly useful if you want
- to keep simple cases simple, and it's how network device configuration has
- been done for a long time.
-
- If there are ``match``: rules, then the ID field is a purely opaque name
- which is only being used for references from definitions of compound
- devices in the config.
-
-Virtual devices (Examples: veth, bridge, bond):
- These are fully under the control of the
- config file(s) and the network stack. I. e. these devices are being created
- instead of matched. Thus ``match:`` and ``set-name:`` are not applicable for
- these, and the ID field is the name of the created virtual device.
+Physical devices (e.g., ethernet, wifi)
+---------------------------------------
+
+These can dynamically come and go between reboots and even during runtime
+(hotplugging). In the generic case, they can be selected by ``match:``
+rules on desired properties, such as name/name pattern, MAC address,
+driver, or device paths. In general these will match any number of
+devices (unless they refer to properties which are unique such as the full
+path or MAC address), so without further knowledge about the hardware,
+these will always be considered as a group.
+
+It is valid to specify no match rules at all, in which case the ID field is
+simply the interface name to be matched. This is mostly useful if you want
+to keep simple cases simple, and it's how network device configuration has
+been done for a long time.
+
+If there are ``match:`` rules, then the ID field is a purely opaque name
+which is only being used for references from definitions of compound
+devices in the config.
+
+Virtual devices (e.g., veth, bridge, bond)
+------------------------------------------
+
+These are fully under the control of the config file(s) and the network
+stack, i.e., these devices are being created instead of matched. Thus
+``match:`` and ``set-name:`` are not applicable for these, and the ID field
+is the name of the created virtual device.
Common properties for physical device types
--------------------------------------------
+===========================================
-**match**: *<(mapping)>*
+``match: <(mapping)>``
+----------------------
This selects a subset of available physical devices by various hardware
properties. The following configuration will then apply to all matching
devices, as soon as they appear. *All* specified properties must match.
The following properties for creating matches are supported:
-**name**: *<(scalar)>*
+``name: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^
Current interface name. Globs are supported, and the primary use case
for matching on names, as selecting one fixed name can be more easily
achieved with having no ``match:`` at all and just using the ID (see
-above). Note that currently only networkd supports globbing,
-NetworkManager does not.
+above). Note that currently only ``networkd`` supports globbing,
+``NetworkManager`` does not.
-**macaddress**: *<(scalar)>*
+Example: ::
-Device's MAC address in the form xx:xx:xx:xx:xx:xx. Globs are not allowed.
-Letters must be lowercase.
+ # all cards on second PCI bus
+ match:
+ name: enp2*
-.. note::
+``macaddress: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
- MAC addresses must be strings. As MAC addresses which consist of only the
- digits 0-9 (i.e. no hex a-f) can be interpreted as a base 60 integer per
- the `YAML 1.1 spec`_ it is best practice to quote all MAC addresses to ensure
- they are parsed as strings regardless of value.
+Device's MAC address in the form xx:xx:xx:xx:xx:xx. Globs are not allowed.
+Letters must be lowercase.
-.. _YAML 1.1 spec: https://yaml.org/type/int.html
+Example: ::
-**driver**: *<(scalar)>*
+ # fixed MAC address
+ match:
+ macaddress: "11:22:33:aa:bb:ff"
-Kernel driver name, corresponding to the ``DRIVER`` udev property. Globs are
-supported. Matching on driver is *only* supported with networkd.
+.. note::
+ It is best practice to "quote" all MAC addresses, since an unquoted MAC
+ address might be incorrectly interpreted as an integer in `YAML`_.
-**Examples**::
+``driver: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^
- # all cards on second PCI bus
- match:
- name: enp2*
+Kernel driver name, corresponding to the ``DRIVER`` udev property. Globs are
+supported. Matching on driver is *only* supported with ``networkd``.
- # fixed MAC address
- match:
- macaddress: 11:22:33:aa:bb:ff
+Example: ::
# first card of driver ``ixgbe``
match:
driver: ixgbe
name: en*s0
-**set-name**: *<(scalar)>*
+``set-name: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^
When matching on unique properties such as path or MAC, or with additional
-assumptions such as "there will only ever be one wifi device",
-match rules can be written so that they only match one device. Then this
-property can be used to give that device a more specific/desirable/nicer
-name than the default from udev’s ifnames. Any additional device that
-satisfies the match rules will then fail to get renamed and keep the
-original kernel name (and dmesg will show an error).
+assumptions such as "there will only ever be one wifi device", match rules
+can be written so that they only match one device. Then this property can be
+used to give that device a more specific/desirable/nicer name than the default
+from udev’s ``ifnames``. Any additional device that satisfies the match rules
+will then fail to get renamed and keep the original kernel name (and dmesg
+will show an error).
-**wakeonlan**: *<(bool)>*
+``wakeonlan: <(bool)>``
+^^^^^^^^^^^^^^^^^^^^^^^
Enable wake on LAN. Off by default.
-
Common properties for all device types
---------------------------------------
+======================================
-**renderer**: *<(scalar)>*
+``renderer: <(scalar)>``
+------------------------
Use the given networking backend for this definition. Currently supported are
``networkd`` and ``NetworkManager``. This property can be specified globally
-in ``networks:``, for a device type (in e. g. ``ethernets:``) or
-for a particular device definition. Default is ``networkd``.
+in ``networks:``, for a device type (e.g., in ``ethernets:``) or for a
+particular device definition. Default is ``networkd``.
.. note::
+ ``Cloud-init`` only supports networkd backend if rendering ``version2``
+ config to the instance.
- Cloud-init only supports networkd backend if rendering version2 config
- to the instance.
-
-**dhcp4**: *<(bool)>*
+``dhcp4: <(bool)>``
+^^^^^^^^^^^^^^^^^^^
Enable DHCP for IPv4. Off by default.
-**dhcp6**: *<(bool)>*
+``dhcp6: <(bool)>``
+^^^^^^^^^^^^^^^^^^^
Enable DHCP for IPv6. Off by default.
-**dhcp4-overrides** and **dhcp6-overrides**: *<(mapping)>*
+``dhcp4-overrides and dhcp6-overrides: <(mapping)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-DHCP behavior overrides. Overrides will only have an effect if
-the corresponding DHCP type is enabled. Refer to `netplan#dhcp-overrides`_
+DHCP behaviour overrides. Overrides will only have an effect if
+the corresponding DHCP type is enabled. Refer to `Netplan#dhcp-overrides`_
for more documentation.
.. note::
+ These properties are only consumed on ``netplan`` and ``networkd``
+ renderers.
- These properties are only consumed on ``netplan`` and ``networkd``
- renderers.
-
-The ``netplan`` renderer :ref:`passes through <Netplan Passthrough>`
+The ``netplan`` renderer :ref:`passes through <Netplan_passthrough>`
everything and the ``networkd`` renderer consumes the following sub-properties:
* ``hostname`` *
@@ -205,7 +214,6 @@ everything and the ``networkd`` renderer consumes the following sub-properties:
* ``use-routes`` *
.. note::
-
Sub-properties marked with a ``*`` are unsupported for ``dhcp6-overrides``
when used with the ``networkd`` renderer.
@@ -222,32 +230,36 @@ Example: ::
use-ntp: false
use-routes: false
-**addresses**: *<(sequence of scalars)>*
+``addresses: <(sequence of scalars)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Add static addresses to the interface in addition to the ones received
-through DHCP or RA. Each sequence entry is in CIDR notation, i. e. of the
-form ``addr/prefixlen`` . ``addr`` is an IPv4 or IPv6 address as recognized
-by ``inet_pton``(3) and ``prefixlen`` the number of bits of the subnet.
+through DHCP or RA. Each sequence entry is in CIDR notation, i.e., of the
+form ``addr/prefixlen``. ``addr`` is an IPv4 or IPv6 address as recognised
+by ``inet_pton(3)`` and ``prefixlen`` the number of bits of the subnet.
Example: ``addresses: [192.168.14.2/24, 2001:1::1/64]``
-**gateway4**: or **gateway6**: *<(scalar)>*
+``gateway4: or gateway6: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Deprecated, see `netplan#default-routes`_.
+Deprecated, see `Netplan#default-routes`_.
Set default gateway for IPv4/6, for manual address configuration. This
requires setting ``addresses`` too. Gateway IPs must be in a form
-recognized by ``inet_pton(3)``
+recognised by ``inet_pton(3)``
Example for IPv4: ``gateway4: 172.16.0.1``
Example for IPv6: ``gateway6: 2001:4::1``
-**mtu**: *<MTU SizeBytes>*
+``mtu: <MTU SizeBytes>``
+^^^^^^^^^^^^^^^^^^^^^^^^
The MTU key represents a device's Maximum Transmission Unit, the largest size
packet or frame, specified in octets (eight-bit bytes), that can be sent in a
-packet- or frame-based network. Specifying ``mtu`` is optional.
+packet- or frame-based network. Specifying ``mtu`` is optional.
-**nameservers**: *<(mapping)>*
+``nameservers: <(mapping)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set DNS servers and search domains, for manual address configuration. There
are two supported fields: ``addresses:`` is a list of IPv4 or IPv6 addresses
@@ -259,10 +271,11 @@ Example: ::
search: [lab, home]
addresses: [8.8.8.8, FEDC::1]
-**routes**: *<(sequence of mapping)>*
+``routes: <(sequence of mapping)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Add device specific routes. Each mapping includes a ``to``, ``via`` key
-with an IPv4 or IPv6 address as value. ``metric`` is an optional value.
+Add device specific routes. Each mapping includes a ``to``, ``via`` key
+with an IPv4 or IPv6 address as value. ``metric`` is an optional value.
Example: ::
@@ -272,14 +285,16 @@ Example: ::
metric: 3
Ethernets
-~~~~~~~~~
+---------
+
Ethernet device definitions do not support any specific properties beyond the
common ones described above.
Bonds
-~~~~~
+-----
-**interfaces** *<(sequence of scalars)>*
+``interfaces: <(sequence of scalars)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All devices matching this ID list will be added to the bond.
@@ -293,60 +308,70 @@ Example: ::
bond0:
interfaces: [switchports]
-**parameters**: *<(mapping)>*
+``parameters: <(mapping)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Customization parameters for special bonding options. Time values are
+Customisation parameters for special bonding options. Time values are
specified in seconds unless otherwise specified.
-**mode**: *<(scalar)>*
+``mode: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^
Set the bonding mode used for the interfaces. The default is
``balance-rr`` (round robin). Possible values are ``balance-rr``,
``active-backup``, ``balance-xor``, ``broadcast``, ``802.3ad``,
``balance-tlb``, and ``balance-alb``.
-**lacp-rate**: *<(scalar)>*
+``lacp-rate: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^
Set the rate at which LACPDUs are transmitted. This is only useful
in 802.3ad mode. Possible values are ``slow`` (30 seconds, default),
and ``fast`` (every second).
-**mii-monitor-interval**: *<(scalar)>*
+``mii-monitor-interval: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Specifies the interval for MII monitoring (verifying if an interface
of the bond has carrier). The default is ``0``; which disables MII
monitoring.
-**min-links**: *<(scalar)>*
+``min-links: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^
The minimum number of links up in a bond to consider the bond
interface to be up.
-**transmit-hash-policy**: <*(scalar)>*
+``transmit-hash-policy: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Specifies the transmit hash policy for the selection of slaves. This
is only useful in balance-xor, 802.3ad and balance-tlb modes.
Possible values are ``layer2``, ``layer3+4``, ``layer2+3``,
``encap2+3``, and ``encap3+4``.
-**ad-select**: <*(scalar)>*
+``ad-select: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^
Set the aggregation selection mode. Possible values are ``stable``,
``bandwidth``, and ``count``. This option is only used in 802.3ad mode.
-**all-slaves-active**: <*(bool)>*
+``all-slaves-active: <(bool)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the bond should drop duplicate frames received on inactive ports,
set this option to ``false``. If they should be delivered, set this
option to ``true``. The default value is false, and is the desirable
-behavior in most situations.
+behaviour in most situations.
-**arp-interval**: <*(scalar)>*
+``arp-interval: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set the interval value for how frequently ARP link monitoring should
happen. The default value is ``0``, which disables ARP monitoring.
-**arp-ip-targets**: <*(sequence of scalars)>*
+``arp-ip-targets: <(sequence of scalars)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IPs of other hosts on the link which should be sent ARP requests in
order to validate that a slave is up. This option is only used when
@@ -355,36 +380,42 @@ address must be given for ARP link monitoring to function. Only IPv4
addresses are supported. You can specify up to 16 IP addresses. The
default value is an empty list.
-**arp-validate**: <*(scalar)>*
+``arp-validate: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Configure how ARP replies are to be validated when using ARP link
monitoring. Possible values are ``none``, ``active``, ``backup``,
and ``all``.
-**arp-all-targets**: <*(scalar)>*
+``arp-all-targets: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Specify whether to use any ARP IP target being up as sufficient for
a slave to be considered up; or if all the targets must be up. This
is only used for ``active-backup`` mode when ``arp-validate`` is
enabled. Possible values are ``any`` and ``all``.
-**up-delay**: <*(scalar)>*
+``up-delay: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^
Specify the delay before enabling a link once the link is physically
up. The default value is ``0``.
-**down-delay**: <*(scalar)>*
+``down-delay: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
Specify the delay before disabling a link once the link has been
lost. The default value is ``0``.
-**fail-over-mac-policy**: <*(scalar)>*
+``fail-over-mac-policy: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set whether to set all slaves to the same MAC address when adding
them to the bond, or how else the system should handle MAC addresses.
The possible values are ``none``, ``active``, and ``follow``.
-**gratuitous-arp**: <*(scalar)>*
+``gratuitous-arp: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Specify how many ARP packets to send after failover. Once a link is
up on a new slave, a notification is sent and possibly repeated if
@@ -392,7 +423,8 @@ this value is set to a number greater than ``1``. The default value
is ``1`` and valid values are between ``1`` and ``255``. This only
affects ``active-backup`` mode.
-**packets-per-slave**: <*(scalar)>*
+``packets-per-slave: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In ``balance-rr`` mode, specifies the number of packets to transmit
on a slave before switching to the next. When this value is set to
@@ -400,25 +432,28 @@ on a slave before switching to the next. When this value is set to
``0`` and ``65535``. The default value is ``1``. This setting is
only used in ``balance-rr`` mode.
-**primary-reselect-policy**: <*(scalar)>*
+``primary-reselect-policy: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Set the reselection policy for the primary slave. On failure of the
active slave, the system will use this policy to decide how the new
active slave will be chosen and how recovery will be handled. The
possible values are ``always``, ``better``, and ``failure``.
-**learn-packet-interval**: <*(scalar)>*
+``learn-packet-interval: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Specify the interval between sending learning packets to each slave.
+Specify the interval between sending Learning packets to each slave.
The value range is between ``1`` and ``0x7fffffff``. The default
value is ``1``. This option only affects ``balance-tlb`` and
``balance-alb`` modes.
Bridges
-~~~~~~~
+-------
-**interfaces**: <*(sequence of scalars)>*
+``interfaces: <(sequence of scalars)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All devices matching this ID list will be added to the bridge.
@@ -432,66 +467,73 @@ Example: ::
br0:
interfaces: [switchports]
-**parameters**: <*(mapping)>*
+``parameters: <(mapping)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Customization parameters for special bridging options. Time values are
-specified in seconds unless otherwise specified.
+Customisation parameters for special bridging options. Time values are
+specified in seconds unless otherwise stated.
-**ageing-time**: <*(scalar)>*
+``ageing-time: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Set the period of time to keep a MAC address in the forwarding
-database after a packet is received.
+Set the period of time to keep a MAC address in the forwarding database after
+a packet is received.
-**priority**: <*(scalar)>*
+``priority: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^
-Set the priority value for the bridge. This value should be an
-number between ``0`` and ``65535``. Lower values mean higher
-priority. The bridge with the higher priority will be elected as
-the root bridge.
+Set the priority value for the bridge. This value should be a number between
+``0`` and ``65535``. Lower values mean higher priority. The bridge with the
+higher priority will be elected as the root bridge.
-**forward-delay**: <*(scalar)>*
+``forward-delay: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Specify the period of time the bridge will remain in Listening and
Learning states before getting to the Forwarding state. This value
-should be set in seconds for the systemd backend, and in milliseconds
-for the NetworkManager backend.
+should be set in seconds for the ``systemd`` backend, and in milliseconds
+for the ``NetworkManager`` backend.
-**hello-time**: <*(scalar)>*
+``hello-time: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
Specify the interval between two hello packets being sent out from
the root and designated bridges. Hello packets communicate
information about the network topology.
-**max-age**: <*(scalar)>*
+``max-age: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^
Set the maximum age of a hello packet. If the last hello packet is
older than that value, the bridge will attempt to become the root
bridge.
-**path-cost**: <*(scalar)>*
+``path-cost: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^^^^^^
Set the cost of a path on the bridge. Faster interfaces should have
a lower cost. This allows a finer control on the network topology
so that the fastest paths are available whenever possible.
-**stp**: <*(bool)>*
+``stp: <(bool)>``
+^^^^^^^^^^^^^^^^^
Define whether the bridge should use Spanning Tree Protocol. The
default value is "true", which means that Spanning Tree should be
used.
-
VLANs
-~~~~~
+-----
-**id**: <*(scalar)>*
+``id: <(scalar)>``
+^^^^^^^^^^^^^^^^^^
VLAN ID, a number between 0 and 4094.
-**link**: <*(scalar)>*
+``link: <(scalar)>``
+^^^^^^^^^^^^^^^^^^^^
-ID of the underlying device definition on which this VLAN gets
-created.
+ID of the underlying device definition on which this VLAN gets created.
Example: ::
@@ -509,9 +551,10 @@ Example: ::
Examples
---------
-Configure an ethernet device with networkd, identified by its name, and enable
-DHCP: ::
+========
+
+Configure an ethernet device with ``networkd``, identified by its name, and
+enable DHCP: ::
network:
version: 2
@@ -572,7 +615,7 @@ This is a complex example which shows most available features: ::
link: id0
dhcp4: yes
-.. _netplan: https://netplan.io
-.. _netplan#default-routes: https://netplan.io/reference#default-routes
-.. _netplan#dhcp-overrides: https://netplan.io/reference#dhcp-overrides
-.. vi: textwidth=79
+.. _Netplan: https://netplan.io
+.. _YAML: https://yaml.org/type/int.html
+.. _Netplan#default-routes: https://netplan.io/reference#default-routes
+.. _Netplan#dhcp-overrides: https://netplan.io/reference#dhcp-overrides
diff --git a/doc/rtd/reference/network-config.rst b/doc/rtd/reference/network-config.rst
new file mode 100644
index 00000000..5a2386d7
--- /dev/null
+++ b/doc/rtd/reference/network-config.rst
@@ -0,0 +1,317 @@
+.. _network_config:
+
+Network configuration
+*********************
+
+Default behaviour
+=================
+
+``Cloud-init`` searches for network configuration in order of increasing
+precedence; each item overriding the previous.
+
+- **Datasource**: For example, OpenStack may provide network config in the
+ MetaData Service.
+- **System config**: A ``network:`` entry in :file:`/etc/cloud/cloud.cfg.d/*`
+ configuration files.
+- **Kernel command line**: ``ip=`` or
+ ``network-config=<Base64 encoded YAML config string>``
+
+User data cannot change an instance's network configuration. In the absence
+of network configuration in any of the above sources, ``cloud-init`` will
+write out a network configuration that will issue a DHCP request on a "first"
+network interface.
+
+.. note::
+
+ The ``network-config`` value is expected to be a Base64 encoded YAML string
+ in :ref:`network_config_v1` or :ref:`network_config_v2` format. Optionally,
+ it can be compressed with ``gzip`` prior to Base64 encoding.
+
+Disabling network configuration
+===============================
+
+Users may disable ``cloud-init``'s network configuration capability and rely
+on other methods, such as embedded configuration or other customisations.
+
+``cloud-init`` supports the following methods for disabling ``cloud-init``.
+
+Kernel command line
+-------------------
+
+``Cloud-init`` will check for the parameter ``network-config=disabled``,
+which will automatically disable any network configuration.
+
+Example disabling kernel command line entry: ::
+
+ network-config=disabled
+
+Cloud config
+------------
+
+In the combined ``cloud-init`` configuration dictionary, merged from
+:file:`/etc/cloud/cloud.cfg` and :file:`/etc/cloud/cloud.cfg.d/*`: ::
+
+ network:
+ config: disabled
+
+If ``cloud-init``'s networking config has not been disabled, and no other
+network information is found, then it will proceed to generate a fallback
+networking configuration.
+
+Disabling network activation
+============================
+
+Some datasources may not be initialised until after the network has been
+brought up. In this case, ``cloud-init`` will attempt to bring up the
+interfaces specified by the datasource metadata using a network activator
+discovered by `cloudinit.net.activators.select_activators`_.
+
+This behaviour can be disabled in the ``cloud-init`` configuration dictionary,
+merged from :file:`/etc/cloud/cloud.cfg` and
+:file:`/etc/cloud/cloud.cfg.d/*`: ::
+
+ disable_network_activation: true
+
+Fallback network configuration
+==============================
+
+``Cloud-init`` will attempt to determine which, of any attached network
+devices, is most likely to have a connection and then generate a network
+configuration to issue a DHCP request on that interface.
+
+``Cloud-init`` runs during early boot and does not expect composed network
+devices (such as Bridges) to be available. ``Cloud-init`` does not consider
+the following interface devices as likely "first" network interfaces for
+fallback configuration; they are filtered out from being selected.
+
+- **loopback**: ``name=lo``
+- **Virtual Ethernet**: ``name=veth*``
+- **Software Bridges**: ``type=bridge``
+- **Software VLANs**: ``type=vlan``
+
+``Cloud-init`` will prefer network interfaces that indicate they are connected
+via the Linux ``carrier`` flag being set. If no interfaces are marked as
+connected, then all unfiltered interfaces are potential connections.
+
+Of the potential interfaces, ``cloud-init`` will attempt to pick the "right"
+interface given the information it has available.
+
+Finally, after selecting the "right" interface, a configuration is generated
+and applied to the system.
+
+.. note::
+ PhotonOS disables fallback networking configuration by default, leaving
+ network unrendered when no other network config is provided.
+ If fallback config is still desired on PhotonOS, it can be enabled by
+ providing ``disable_fallback_netcfg: false`` in
+ :file:`/etc/cloud/cloud.cfg:sys_config` settings.
+
+Network configuration sources
+=============================
+
+``Cloud-init`` accepts a number of different network configuration formats in
+support of different cloud substrates. The datasource for these clouds in
+``cloud-init`` will detect and consume datasource-specific network
+configuration formats for use when writing an instance's network
+configuration.
+
+The following datasources optionally provide network configuration:
+
+- :ref:`datasource_config_drive`
+
+ - `OpenStack Metadata Service Network`_
+ - :ref:`network_config_eni`
+
+- :ref:`datasource_digital_ocean`
+
+ - `DigitalOcean JSON metadata`_
+
+- :ref:`datasource_nocloud`
+
+ - :ref:`network_config_v1`
+ - :ref:`network_config_v2`
+ - :ref:`network_config_eni`
+
+- :ref:`datasource_opennebula`
+
+ - :ref:`network_config_eni`
+
+- :ref:`datasource_openstack`
+
+ - :ref:`network_config_eni`
+ - `OpenStack Metadata Service Network`_
+
+- :ref:`datasource_smartos`
+
+ - `SmartOS JSON Metadata`_
+
+- :ref:`datasource_upcloud`
+
+ - `UpCloud JSON metadata`_
+
+- :ref:`datasource_vultr`
+
+ - `Vultr JSON metadata`_
+
+For more information on network configuration formats:
+
+.. toctree::
+ :maxdepth: 1
+
+ network-config-format-eni.rst
+ network-config-format-v1.rst
+ network-config-format-v2.rst
+
+
+Network configuration outputs
+=============================
+
+``Cloud-init`` converts various forms of user-supplied or automatically
+generated configuration into an internal network configuration state. From
+this state, ``cloud-init`` delegates rendering of the configuration to
+distro-supported formats. The following ``renderers`` are supported in
+``cloud-init``:
+
+NetworkManager
+--------------
+
+`NetworkManager`_ is the standard Linux network configuration tool suite. It
+supports a wide range of networking setups. Configuration is typically stored
+in :file:`/etc/NetworkManager`.
+
+It is the default for a number of Linux distributions; notably Fedora,
+CentOS/RHEL, and their derivatives.
+
+ENI
+---
+
+:file:`/etc/network/interfaces` or ``ENI`` is supported by the ``ifupdown``
+package found in Alpine Linux, Debian and Ubuntu.
+
+Netplan
+-------
+
+Introduced in Ubuntu 16.10 (Yakkety Yak), `Netplan`_ has been the default
+network configuration tool in Ubuntu since 17.10 (Artful Aardvark). Netplan
+consumes :ref:`network_config_v2` input and renders network configuration for
+supported backends such as ``systemd-networkd`` and ``NetworkManager``.
+
+Sysconfig
+---------
+
+Sysconfig format is used by RHEL, CentOS, Fedora and other derivatives.
+
+NetBSD, OpenBSD, FreeBSD
+------------------------
+
+Network renders supporting BSD releases, which typically write configuration
+to :file:`/etc/rc.conf`. Unique to BSD renderers is that each renderer also
+calls something akin to `FreeBSD.start_services`_ which will invoke applicable
+network services to setup the network, making network activators unneeded
+for BSD flavors at the moment.
+
+Network output policy
+=====================
+
+The default policy for selecting a network ``renderer`` (in order of
+preference) is as follows:
+
+- ENI
+- Sysconfig
+- Netplan
+- NetworkManager
+- FreeBSD
+- NetBSD
+- OpenBSD
+- Networkd
+
+The default policy for selecting a network ``activator`` (in order of
+preference) is as follows:
+
+- **ENI**: using ``ifup``, ``ifdown`` to manage device setup/teardown
+- **Netplan**: using ``netplan apply`` to manage device setup/teardown
+- **NetworkManager**: using ``nmcli`` to manage device setup/teardown
+- **Networkd**: using ``ip`` to manage device setup/teardown
+
+When applying the policy, ``cloud-init`` checks if the current instance has the
+correct binaries and paths to support the renderer. The first renderer that
+can be used is selected. Users may override the network renderer policy by
+supplying an updated configuration in cloud-config. ::
+
+ system_info:
+ network:
+ renderers: ['netplan', 'network-manager', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd']
+ activators: ['eni', 'netplan', 'network-manager', 'networkd']
+
+Network configuration tools
+===========================
+
+``Cloud-init`` contains one tool used to test input/output conversion between
+formats. The :file:`tools/net-convert.py` in the ``cloud-init`` source
+repository is helpful in examining expected output for a given input format.
+
+CLI Interface:
+
+.. code-block:: shell-session
+
+ $ tools/net-convert.py --help
+
+Example output:
+
+.. code-block::
+
+ usage: net-convert.py [-h] --network-data PATH --kind
+ {eni,network_data.json,yaml} -d PATH [-m name,mac]
+ --output-kind {eni,netplan,sysconfig}
+
+ optional arguments:
+ -h, --help show this help message and exit
+ --network-data PATH, -p PATH
+ --kind {eni,network_data.json,yaml}, -k {eni,network_data.json,yaml}
+ -d PATH, --directory PATH
+ directory to place output in
+ -m name,mac, --mac name,mac
+ interface name to mac mapping
+ --output-kind {eni,netplan,sysconfig}, -ok {eni,netplan,sysconfig}
+
+Example of converting V2 to sysconfig:
+
+.. code-block:: shell-session
+
+ $ tools/net-convert.py --network-data v2.yaml --kind yaml \
+ --output-kind sysconfig -d target
+ $ cat target/etc/sysconfig/network-scripts/ifcfg-eth*
+
+Example output:
+
+.. code-block::
+
+ # Created by cloud-init on instance boot automatically, do not edit.
+ #
+ BOOTPROTO=static
+ DEVICE=eth7
+ IPADDR=192.168.1.5/255.255.255.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no
+ # Created by cloud-init on instance boot automatically, do not edit.
+ #
+ BOOTPROTO=dhcp
+ DEVICE=eth9
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no
+
+
+.. _Cloud-init: https://launchpad.net/cloud-init
+.. _NetworkManager: https://networkmanager.dev
+.. _Netplan: https://netplan.io/
+.. _DigitalOcean JSON metadata: https://developers.digitalocean.com/documentation/metadata/
+.. _OpenStack Metadata Service Network: https://specs.openstack.org/openstack/nova-specs/specs/liberty/implemented/metadata-service-network-info.html
+.. _SmartOS JSON Metadata: https://eng.joyent.com/mdata/datadict.html
+.. _UpCloud JSON metadata: https://developers.upcloud.com/1.3/8-servers/#metadata-service
+.. _Vultr JSON metadata: https://www.vultr.com/metadata/
+.. _cloudinit.net.activators.select_activators: https://github.com/canonical/cloud-init/blob/main/cloudinit/net/activators.py#L279
+.. _FreeBSD.start_services: https://github.com/canonical/cloud-init/blob/main/cloudinit/net/freebsd.py#L28
diff --git a/doc/rtd/topics/boot.rst b/doc/rtd/topics/boot.rst
deleted file mode 100644
index ba9bd40b..00000000
--- a/doc/rtd/topics/boot.rst
+++ /dev/null
@@ -1,246 +0,0 @@
-.. _boot_stages:
-
-Boot Stages
-***********
-
-In order to be able to provide the functionality that it does, cloud-init
-must be integrated into the boot in fairly controlled way. There are five
-stages to boot:
-
-1. Generator
-2. Local
-3. Network
-4. Config
-5. Final
-
-Generator
-=========
-
-When booting under systemd, a
-`generator <https://www.freedesktop.org/software/systemd/man/systemd.generator.html>`_
-will run that determines if cloud-init.target should be included in the boot
-goals. By default, this generator will enable cloud-init. It will not enable
-cloud-init if either:
-
- * The file ``/etc/cloud/cloud-init.disabled`` exists
- * The kernel command line as found in ``/proc/cmdline`` contains
- ``cloud-init=disabled``. When running in a container, the kernel command
- line is not honored, but cloud-init will read an environment variable named
- ``KERNEL_CMDLINE`` in its place.
-
-Again, these mechanisms for disabling cloud-init at runtime currently only
-exist in systemd.
-
-Local
-=====
-
-+------------------+----------------------------------------------------------+
-| systemd service | ``cloud-init-local.service`` |
-+---------+--------+----------------------------------------------------------+
-| runs | as soon as possible with ``/`` mounted read-write |
-+---------+--------+----------------------------------------------------------+
-| blocks | as much of boot as possible, *must* block network |
-+---------+--------+----------------------------------------------------------+
-| modules | none |
-+---------+--------+----------------------------------------------------------+
-
-The purpose of the local stage is to:
-
- * locate "local" data sources.
- * apply networking configuration to the system (including "Fallback")
-
-In most cases, this stage does not do much more than that. It finds the
-datasource and determines the network configuration to be used. That
-network configuration can come from:
-
- * **datasource**: cloud provided network configuration via metadata
- * **fallback**: cloud-init's fallback networking consists of rendering the
- equivalent to "dhcp on eth0", which was historically the most popular
- mechanism for network configuration of a guest
- * **none**: network configuration can be disabled by writing the file
- ``/etc/cloud/cloud.cfg`` with the content:
- ``network: {config: disabled}``
-
-If this is an instance's first boot, then the selected network configuration
-is rendered. This includes clearing of all previous (stale) configuration
-including persistent device naming with old mac addresses.
-
-This stage must block network bring-up or any stale configuration that might
-have already been applied. Otherwise, that could have negative effects such
-as DHCP hooks or broadcast of an old hostname. It would also put the system
-in an odd state to recover from, as it may then have to restart network
-devices.
-
-Cloud-init then exits and expects for the continued boot of the operating
-system to bring network configuration up as configured.
-
-**Note**: In the past, local data sources have been only those that were
-available without network (such as 'ConfigDrive'). However, as seen in
-the recent additions to the DigitalOcean datasource, even data sources
-that require a network can operate at this stage.
-
-Network
-=======
-
-+------------------+----------------------------------------------------------+
-| systemd service | ``cloud-init.service`` |
-+---------+--------+----------------------------------------------------------+
-| runs | after local stage and configured networking is up |
-+---------+--------+----------------------------------------------------------+
-| blocks | as much of remaining boot as possible |
-+---------+--------+----------------------------------------------------------+
-| modules | *cloud_init_modules* in ``/etc/cloud/cloud.cfg`` |
-+---------+--------+----------------------------------------------------------+
-
-This stage requires all configured networking to be online, as it will fully
-process any user-data that is found. Here processing means:
-
- * retrieve any ``#include`` or ``#include-once`` (recursively) including http
- * decompress any compressed content
- * run any part-handler found.
-
-This stage runs the ``disk_setup`` and ``mounts`` modules which may partition
-and format disks and configure mount points (such as in ``/etc/fstab``).
-Those modules cannot run earlier as they may receive configuration input
-from sources only available via network. For example, a user may have
-provided user-data in a network resource that describes how local mounts
-should be done.
-
-On some clouds, such as Azure, this stage will create filesystems to be
-mounted, including ones that have stale (previous instance) references in
-``/etc/fstab``. As such, entries ``/etc/fstab`` other than those necessary for
-cloud-init to run should not be done until after this stage.
-
-A part-handler will run at this stage, as will boot-hooks including
-cloud-config ``bootcmd``. The user of this functionality has to be aware
-that the system is in the process of booting when their code runs.
-
-Config
-======
-
-+------------------+----------------------------------------------------------+
-| systemd service | ``cloud-config.service`` |
-+---------+--------+----------------------------------------------------------+
-| runs | after network |
-+---------+--------+----------------------------------------------------------+
-| blocks | nothing |
-+---------+--------+----------------------------------------------------------+
-| modules | *cloud_config_modules* in ``/etc/cloud/cloud.cfg`` |
-+---------+--------+----------------------------------------------------------+
-
-This stage runs config modules only. Modules that do not really have an
-effect on other stages of boot are run here, including ``runcmd``.
-
-Final
-=====
-
-+------------------+----------------------------------------------------------+
-| systemd service | ``cloud-final.service`` |
-+---------+--------+----------------------------------------------------------+
-| runs | as final part of boot (traditional "rc.local") |
-+---------+--------+----------------------------------------------------------+
-| blocks | nothing |
-+---------+--------+----------------------------------------------------------+
-| modules | *cloud_final_modules* in ``/etc/cloud/cloud.cfg`` |
-+---------+--------+----------------------------------------------------------+
-
-This stage runs as late in boot as possible. Any scripts that a user is
-accustomed to running after logging into a system should run correctly here.
-Things that run here include:
-
- * package installations
- * configuration management plugins (ansible, puppet, chef, salt-minion)
- * user-defined scripts (i.e. shell scripts passed as user-data)
-
-For scripts external to cloud-init looking to wait until cloud-init is
-finished, the ``cloud-init status --wait`` subcommand can help block external
-scripts until cloud-init is done without having to write your own systemd
-units dependency chains. See :ref:`cli_status` for more info.
-
-First Boot Determination
-========================
-
-cloud-init has to determine whether or not the current boot is the first boot
-of a new instance or not, so that it applies the appropriate configuration. On
-an instance's first boot, it should run all "per-instance" configuration,
-whereas on a subsequent boot it should run only "per-boot" configuration. This
-section describes how cloud-init performs this determination, as well as why it
-is necessary.
-
-When it runs, cloud-init stores a cache of its internal state for use across
-stages and boots.
-
-If this cache is present, then cloud-init has run on this system before.
-[#not-present]_ There are two cases where this could occur. Most commonly,
-the instance has been rebooted, and this is a second/subsequent boot.
-Alternatively, the filesystem has been attached to a *new* instance, and this
-is an instance's first boot. The most obvious case where this happens is when
-an instance is launched from an image captured from a launched instance.
-
-By default, cloud-init attempts to determine which case it is running in by
-checking the instance ID in the cache against the instance ID it determines at
-runtime. If they do not match, then this is an instance's first boot;
-otherwise, it's a subsequent boot. Internally, cloud-init refers to this
-behavior as ``check``.
-
-This behavior is required for images captured from launched instances to
-behave correctly, and so is the default which generic cloud images ship with.
-However, there are cases where it can cause problems. [#problems]_ For these
-cases, cloud-init has support for modifying its behavior to trust the instance
-ID that is present in the system unconditionally. This means that cloud-init
-will never detect a new instance when the cache is present, and it follows that
-the only way to cause cloud-init to detect a new instance (and therefore its
-first boot) is to manually remove cloud-init's cache. Internally, this
-behavior is referred to as ``trust``.
-
-To configure which of these behaviors to use, cloud-init exposes the
-``manual_cache_clean`` configuration option. When ``false`` (the default),
-cloud-init will ``check`` and clean the cache if the instance IDs do not match
-(this is the default, as discussed above). When ``true``, cloud-init will
-``trust`` the existing cache (and therefore not clean it).
-
-Manual Cache Cleaning
-=====================
-
-cloud-init ships a command for manually cleaning the cache: ``cloud-init
-clean``. See :ref:`cli_clean`'s documentation for further details.
-
-Reverting ``manual_cache_clean`` Setting
-========================================
-
-Currently there is no support for switching an instance that is launched with
-``manual_cache_clean: true`` from ``trust`` behavior to ``check`` behavior,
-other than manually cleaning the cache.
-
-.. warning:: If you want to capture an instance that is currently in ``trust``
- mode as an image for launching other instances, you **must** manually clean
- the cache. If you do not do so, then instances launched from the captured
- image will all detect their first boot as a subsequent boot of the captured
- instance, and will not apply any per-instance configuration.
-
- This is a functional issue, but also a potential security one: cloud-init is
- responsible for rotating SSH host keys on first boot, and this will not
- happen on these instances.
-
-.. [#not-present] It follows that if this cache is not present, cloud-init has
- not run on this system before, so this is unambiguously this instance's
- first boot.
-
-.. [#problems] A couple of ways in which this strict reliance on the presence
- of a datasource has been observed to cause problems:
-
- * If a cloud's metadata service is flaky and cloud-init cannot obtain the
- instance ID locally on that platform, cloud-init's instance ID
- determination will sometimes fail to determine the current instance ID,
- which makes it impossible to determine if this is an instance's first or
- subsequent boot (`#1885527`_).
- * If cloud-init is used to provision a physical appliance or device and an
- attacker can present a datasource to the device with a different instance
- ID, then cloud-init's default behavior will detect this as an instance's
- first boot and reset the device using the attacker's configuration
- (this has been observed with the NoCloud datasource in `#1879530`_).
-
-.. _#1885527: https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1885527
-.. _#1879530: https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1879530
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/cli.rst b/doc/rtd/topics/cli.rst
deleted file mode 100644
index 463ac38c..00000000
--- a/doc/rtd/topics/cli.rst
+++ /dev/null
@@ -1,405 +0,0 @@
-.. _cli:
-
-CLI Interface
-*************
-
-For the latest list of subcommands and arguments use cloud-init's ``--help``
-option. This can be used against cloud-init itself or any of its subcommands.
-
-.. code-block:: shell-session
-
- $ cloud-init --help
-
-Example output:
-
-.. code-block::
-
- usage: cloud-init [-h] [--version] [--file FILES] [--debug] [--force]
- {init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status,schema} ...
-
- options:
- -h, --help show this help message and exit
- --version, -v Show program's version number and exit.
- --file FILES, -f FILES
- Use additional yaml configuration files.
- --debug, -d Show additional pre-action logging (default: False).
- --force Force running even if no datasource is found (use at your own risk).
-
- Subcommands:
- {init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status,schema}
- init Initialize cloud-init and perform initial modules.
- modules Activate modules using a given configuration key.
- single Run a single module.
- query Query standardized instance metadata from the command line.
- dhclient-hook Run the dhclient hook to record network info.
- features List defined features.
- analyze Devel tool: Analyze cloud-init logs and data.
- devel Run development tools.
- collect-logs Collect and tar all cloud-init debug info.
- clean Remove logs and artifacts so cloud-init can re-run.
- status Report cloud-init status or wait on completion.
- schema Validate cloud-config files using jsonschema.
-
-
-The rest of this document will give an overview of each of the subcommands.
-
-
-.. _cli_analyze:
-
-analyze
-=======
-
-Get detailed reports of where cloud-init spends its time during the boot
-process. For more complete reference see :ref:`analyze`.
-
-Possible subcommands include:
-
-* *blame*: report ordered by most costly operations
-* *dump*: machine-readable JSON dump of all cloud-init tracked events
-* *show*: show time-ordered report of the cost of operations during each
- boot stage
-* *boot*: show timestamps from kernel initialization, kernel finish
- initialization, and cloud-init start
-
-
-.. _cli_clean:
-
-clean
-=====
-
-Remove cloud-init artifacts from ``/var/lib/cloud`` to simulate a clean
-instance. On reboot, cloud-init will re-run all stages as it did on first boot.
-
-* ``--logs``: optionally remove all cloud-init log files in ``/var/log/``
-* ``--reboot``: reboot the system after removing artifacts
-* ``--machine-id``: Remove ``/etc/machine-id`` on this image. Best practice
- when cloning a golden image to ensure that the next boot of that image
- auto-generates an unique machine ID. `More details on machine-id`_.
-
-
-.. _cli_collect_logs:
-
-collect-logs
-============
-
-Collect and tar cloud-init generated logs, data files, and system
-information for triage. This subcommand is integrated with apport.
-
-Logs collected include:
-
- * ``/var/log/cloud-init.log``
- * ``/var/log/cloud-init-output.log``
- * ``/run/cloud-init``
- * ``/var/lib/cloud/instance/user-data.txt``
- * cloud-init package version
- * ``dmesg`` output
- * journalctl output
-
-.. note::
-
- Ubuntu users can file bugs with ``ubuntu-bug cloud-init`` to
- automatically attach these logs to a bug report
-
-
-.. _cli_devel:
-
-devel
-=====
-
-Collection of development tools under active development. These tools will
-likely be promoted to top-level subcommands when stable.
-
-Do **NOT** rely on the output of these commands as they can and will change.
-
-Current subcommands:
-
- * ``net-convert``: manually use cloud-init's network format conversion, useful
- for testing configuration or testing changes to the network conversion logic
- itself.
- * ``render``: use cloud-init's jinja template render to
- process **#cloud-config** or **custom-scripts**, injecting any variables
- from ``/run/cloud-init/instance-data.json``. It accepts a user-data file
- containing the jinja template header ``## template: jinja`` and renders
- that content with any instance-data.json variables present.
- * ``hotplug-hook``: respond to newly added system devices by retrieving
- updated system metadata and bringing up/down the corresponding device.
- This command is intended to be called via a systemd service and is
- not considered user-accessible except for debugging purposes.
-
-
-.. _cli_features:
-
-features
-========
-
-Print out each feature supported. If cloud-init does not have the
-features subcommand, it also does not support any features described in
-this document.
-
-.. code-block:: shell-session
-
- $ cloud-init features
-
-Example output:
-
-.. code-block::
-
- NETWORK_CONFIG_V1
- NETWORK_CONFIG_V2
-
-
-.. _cli_init:
-
-init
-====
-
-Generally run by OS init systems to execute cloud-init's stages
-*init* and *init-local*. See :ref:`boot_stages` for more info.
-Can be run on the commandline, but is generally gated to run only once
-due to semaphores in ``/var/lib/cloud/instance/sem/`` and
-``/var/lib/cloud/sem``.
-
-* ``--local``: run *init-local* stage instead of *init*
-
-
-.. _cli_modules:
-
-modules
-=======
-
-Generally run by OS init systems to execute *modules:config* and
-*modules:final* boot stages. This executes cloud config :ref:`modules`
-configured to run in the init, config and final stages. The modules are
-declared to run in various boot stages in the file
-``/etc/cloud/cloud.cfg`` under keys:
-
-* *cloud_init_modules*
-* *cloud_config_modules*
-* *cloud_final_modules*
-
-Can be run on the command line, but each module is gated to run only once due
-to semaphores in ``/var/lib/cloud/``.
-
-* ``--mode [init|config|final]``: run ``modules:init``, ``modules:config`` or
- `modules:final` cloud-init stages. See :ref:`boot_stages` for more info.
-
-
-.. _cli_query:
-
-query
-=====
-
-Query standardized cloud instance metadata crawled by cloud-init and stored
-in ``/run/cloud-init/instance-data.json``. This is a convenience command-line
-interface to reference any cached configuration metadata that cloud-init
-crawls when booting the instance. See :ref:`instance_metadata` for more info.
-
-* ``--all``: dump all available instance data as json which can be queried
-* ``--instance-data``: optional path to a different instance-data.json file
- to source for queries
-* ``--list-keys``: list available query keys from cached instance data
-* ``--format``: a string that will use jinja-template syntax to render a
- string replacing
-* ``<varname>``: a dot-delimited variable path into the instance-data.json
- object
-
-Below demonstrates how to list all top-level query keys that are standardized
-aliases:
-
-.. code-block:: shell-session
-
- $ cloud-init query --list-keys
-
-Example output:
-
-.. code-block::
-
- _beta_keys
- availability_zone
- base64_encoded_keys
- cloud_name
- ds
- instance_id
- local_hostname
- platform
- public_ssh_keys
- region
- sensitive_keys
- subplatform
- userdata
- v1
- vendordata
-
-Here are a few examples of how to query standardized metadata from clouds:
-
-.. code-block:: shell-session
-
- $ cloud-init query v1.cloud_name
-
-Example output:
-
-.. code-block::
-
- aws # or openstack, azure, gce etc.
-
-Any standardized instance-data under a <v#> key is aliased as a top-level key
-for convenience:
-
-.. code-block:: shell-session
-
- $ cloud-init query cloud_name
-
-Example output:
-
-.. code-block::
-
- aws # or openstack, azure, gce etc.
-
-One can also query datasource-specific metadata on EC2, e.g.:
-
-.. code-block:: shell-session
-
- $ cloud-init query ds.meta_data.public_ipv4
-
-
-.. note::
-
- The standardized instance data keys under **v#** are guaranteed not to change
- behavior or format. If using top-level convenience aliases for any
- standardized instance data keys, the most value (highest **v#**) of that key
- name is what is reported as the top-level value. So these aliases act as a
- 'latest'.
-
-This data can then be formatted to generate custom strings or data. For
-example, we can generate a custom hostname fqdn based on instance-id, cloud and
-region:
-
-.. code-block:: shell-session
-
- $ cloud-init query --format 'custom-{{instance_id}}.{{region}}.{{v1.cloud_name}}.com'
-
-.. code-block::
-
- custom-i-0e91f69987f37ec74.us-east-2.aws.com
-
-
-.. _cli_schema:
-
-schema
-======
-
-Validate cloud-config files using jsonschema.
-
-* ``-h, --help``: show this help message and exit
-* ``-c CONFIG_FILE, --config-file CONFIG_FILE``: Path of the cloud-config yaml
- file to validate
-* ``--system``: Validate the system cloud-config userdata
-* ``-d DOCS [DOCS ...], --docs DOCS [DOCS ...]``: Print schema module docs.
- Choices: all or space-delimited cc_names.
-* ``--annotate``: Annotate existing cloud-config file with errors
-
-The following example checks a config file and annotates the config file with
-errors on stdout.
-
-.. code-block:: shell-session
-
- $ cloud-init schema -c ./config.yml --annotate
-
-
-.. _cli_single:
-
-single
-======
-
-Attempt to run a single named cloud config module.
-
-* ``--name``: the cloud-config module name to run
-* ``--frequency``: module frequency for this run.
- One of (always|once-per-instance|once)
-* ``--report``: enable reporting
-
-The following example re-runs the cc_set_hostname module ignoring the module
-default frequency of once-per-instance:
-
-.. code-block:: shell-session
-
- $ cloud-init single --name set_hostname --frequency always
-
-.. note::
-
- Mileage may vary trying to re-run each cloud-config module, as
- some are not idempotent.
-
-
-.. _cli_status:
-
-status
-======
-
-Report whether cloud-init is running, done, disabled or errored. Exits
-non-zero if an error is detected in cloud-init.
-
-* ``--long``: detailed status information
-* ``--wait``: block until cloud-init completes
-* ``--format [yaml|json|tabular]``: machine-readable JSON or YAML detailed
- output
-
-The ``status`` command can be used simply as follows:
-
-.. code-block:: shell-session
-
- $ cloud-init status
-
-Which shows whether cloud-init is currently running, done, disabled, or in
-error, as in this example output:
-
-.. code-block::
-
- status: running
-
-The ``--long`` option, shown below, provides a more verbose output.
-
-.. code-block:: shell-session
-
- $ cloud-init status --long
-
-Example output when cloud-init is running:
-
-.. code-block::
-
- status: running
- time: Fri, 26 Jan 2018 21:39:43 +0000
- detail:
- Running in stage: init-local
-
-Example output when cloud-init is done:
-
-.. code-block::
-
- status: done
- boot_status_code: enabled-by-generator
- last_update: Tue, 16 Aug 2022 19:12:58 +0000
- detail:
- DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net]
-
-The detailed output can be shown in machine-readable JSON or YAML with the
-``format`` option, for example:
-
-.. code-block:: shell-session
-
- $ cloud-init status --format=json
-
-Which would produce the following example output:
-
-.. code-block::
-
- {
- "boot_status_code": "enabled-by-generator",
- "datasource": "nocloud",
- "detail": "DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net]",
- "errors": [],
- "last_update": "Tue, 16 Aug 2022 19:12:58 +0000",
- "status": "done"
- }
-
-.. _More details on machine-id: https://www.freedesktop.org/software/systemd/man/machine-id.html
diff --git a/doc/rtd/topics/configuration.rst b/doc/rtd/topics/configuration.rst
deleted file mode 100644
index 19d053c5..00000000
--- a/doc/rtd/topics/configuration.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-.. _configuration:
-
-Configuration Sources
-*********************
-
-Internally, cloud-init builds a single configuration that is then referenced
-throughout the life of cloud-init. The configuration is built from multiple
-sources such that if a key is defined in multiple sources, the higher priority
-source overwrites the lower priority source.
-
-Base Configuration
-==================
-
-From lowest priority to highest, configuration sources are:
-
-* **Hardcoded config**: Config_ that lives within the source of cloud-init
- and cannot be changed.
-* **Configuration directory**: Anything defined in ``/etc/cloud/cloud.cfg`` and
- ``/etc/cloud/cloud.cfg.d``.
-* **Runtime config**: Anything defined in ``/run/cloud-init/cloud.cfg``.
-* **Kernel command line**: On the kernel command line, anything found between
- ``cc:`` and ``end_cc`` will be interpreted as cloud-config user data.
-
-These four sources make up the base configuration.
-
-Vendor and User Data
-====================
-Added to the base configuration are:
-
-* **Vendor data**: :ref:`Data<vendordata>` provided by the datasource
-* **User data**: :ref:`Data<user_data_formats>` also provided by
- the datasource
-
-These get fetched from the datasource and are defined at instance launch.
-
-.. note::
- While much of what is defined in the base configuration can be overridden by
- vendor data and user data, base configuration sources do not conform to
- :ref:`#cloud-config<topics/format:Cloud Config Data>`
-
-Network Configuration
-=====================
-Network configuration happens independently from other cloud-init
-configuration. See :ref:`network configuration documentation<network_config>`
-for more information.
-
-Specifying Configuration
-==========================
-
-End users
----------
-Pass :ref:`user data<user_data_formats>` to the cloud provider.
-Every platform supporting cloud-init will provide a method of supplying
-user data. If you're unsure how to do this, reference the documentation
-provided by the cloud platform you're on. Additionally, there may be
-related cloud-init documentation in the :ref:`datasource<datasources>`
-section.
-
-Once an instance has been initialized, the user data may not be edited.
-It is sourced directly from the cloud, so even if you find a local file
-that contains user data, it will likely be overwritten next boot.
-
-Distro Providers
-----------------
-Modify the base config. This often involves submitting a PR to modify
-the base `cloud.cfg template`_, which is used to customize
-`/etc/cloud/cloud.cfg` per distro. Additionally, a file can be added to
-``/etc/cloud/cloud.cfg.d`` to override a piece of the base configuration.
-
-Cloud Providers
----------------
-Pass vendor data. This is the preferred method for clouds to provide
-their own customization. In some cases, it may make sense to modify the
-base config in the same manner as distro providers on cloud-supported
-images.
-
-
-.. _Config: https://github.com/canonical/cloud-init/blob/b861ea8a5e1fd0eb33096f60f54eeff42d80d3bd/cloudinit/settings.py#L22
-.. _cloud.cfg template: https://github.com/canonical/cloud-init/blob/main/config/cloud.cfg.tmpl
diff --git a/doc/rtd/topics/datasources.rst b/doc/rtd/topics/datasources.rst
deleted file mode 100644
index 0867564d..00000000
--- a/doc/rtd/topics/datasources.rst
+++ /dev/null
@@ -1,114 +0,0 @@
-.. _datasources:
-
-Datasources
-***********
-
-Datasources are sources of configuration data for cloud-init that typically
-come from the user (i.e. userdata) or come from the cloud that created the
-configuration drive (i.e. metadata). Typical userdata would include files,
-YAML, and shell scripts while typical metadata would include server name,
-instance id, display name and other cloud specific details.
-
-Since there are multiple ways to provide this data (each cloud solution seems
-to prefer its own way) internally a datasource abstract class was created to
-allow for a single way to access the different cloud systems methods to provide
-this data through the typical usage of subclasses.
-
-Any metadata processed by cloud-init's datasources is persisted as
-``/run/cloud-init/instance-data.json``. Cloud-init provides tooling to quickly
-introspect some of that data. See :ref:`instance_metadata` for more
-information.
-
-Known Sources
-=============
-
-The following is a list of documents for each supported datasource:
-
-.. toctree::
- :titlesonly:
-
- datasources/aliyun.rst
- datasources/altcloud.rst
- datasources/ec2.rst
- datasources/azure.rst
- datasources/cloudsigma.rst
- datasources/cloudstack.rst
- datasources/configdrive.rst
- datasources/digitalocean.rst
- datasources/e24cloud.rst
- datasources/exoscale.rst
- datasources/fallback.rst
- datasources/gce.rst
- datasources/lxd.rst
- datasources/maas.rst
- datasources/nocloud.rst
- datasources/opennebula.rst
- datasources/openstack.rst
- datasources/oracle.rst
- datasources/ovf.rst
- datasources/rbxcloud.rst
- datasources/smartos.rst
- datasources/upcloud.rst
- datasources/vmware.rst
- datasources/vultr.rst
- datasources/zstack.rst
- datasources/nwcs.rst
-
-Creation
-========
-
-The datasource objects have a few touch points with cloud-init. If you
-are interested in adding a new datasource for your cloud platform you will
-need to take care of the following items:
-
-* **Identify a mechanism for positive identification of the platform**:
- It is good practice for a cloud platform to positively identify itself
- to the guest. This allows the guest to make educated decisions based
- on the platform on which it is running. On the x86 and arm64 architectures,
- many clouds identify themselves through DMI data. For example,
- Oracle's public cloud provides the string 'OracleCloud.com' in the
- DMI chassis-asset field.
-
- cloud-init enabled images produce a log file with details about the
- platform. Reading through this log in ``/run/cloud-init/ds-identify.log``
- may provide the information needed to uniquely identify the platform.
- If the log is not present, you can generate it by running from source
- ``./tools/ds-identify`` or the installed location
- ``/usr/lib/cloud-init/ds-identify``.
-
- The mechanism used to identify the platform will be required for the
- ds-identify and datasource module sections below.
-
-* **Add datasource module ``cloudinit/sources/DataSource<CloudPlatform>.py``**:
- It is suggested that you start by copying one of the simpler datasources
- such as DataSourceHetzner.
-
-* **Add tests for datasource module**:
- Add a new file with some tests for the module to
- ``cloudinit/sources/test_<yourplatform>.py``. For example see
- ``cloudinit/sources/tests/test_oracle.py``
-
-* **Update ds-identify**: In systemd systems, ds-identify is used to detect
- which datasource should be enabled or if cloud-init should run at all.
- You'll need to make changes to ``tools/ds-identify``.
-
-* **Add tests for ds-identify**: Add relevant tests in a new class to
- ``tests/unittests/test_ds_identify.py``. You can use ``TestOracle`` as an
- example.
-
-* **Add your datasource name to the builtin list of datasources:** Add
- your datasource module name to the end of the ``datasource_list``
- entry in ``cloudinit/settings.py``.
-
-* **Add your cloud platform to apport collection prompts:** Update the
- list of cloud platforms in ``cloudinit/apport.py``. This list will be
- provided to the user who invokes ``ubuntu-bug cloud-init``.
-
-* **Enable datasource by default in ubuntu packaging branches:**
- Ubuntu packaging branches contain a template file
- ``debian/cloud-init.templates`` that ultimately sets the default
- datasource_list when installed via package. This file needs updating when
- the commit gets into a package.
-
-* **Add documentation for your datasource**: You should add a new
- file in ``doc/datasources/<cloudplatform>.rst``
diff --git a/doc/rtd/topics/datasources/azure.rst b/doc/rtd/topics/datasources/azure.rst
deleted file mode 100644
index 345c2c1b..00000000
--- a/doc/rtd/topics/datasources/azure.rst
+++ /dev/null
@@ -1,125 +0,0 @@
-.. _datasource_azure:
-
-Azure
-=====
-
-This datasource finds metadata and user-data from the Azure cloud platform.
-
-
-The Azure cloud platform provides initial data to an instance via an attached
-CD formatted in UDF. That CD contains a 'ovf-env.xml' file that provides some
-information. Additional information is obtained via interaction with the
-"endpoint".
-
-
-IMDS
-----
-Azure provides the `instance metadata service (IMDS)
-<https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service>`_
-which is a REST service on ``169.254.169.254`` providing additional
-configuration information to the instance. Cloud-init uses the IMDS for:
-
-- network configuration for the instance which is applied per boot
-- a preprovisioing gate which blocks instance configuration until Azure fabric
- is ready to provision
-- retrieving SSH public keys. Cloud-init will first try to utilize SSH keys
- returned from IMDS, and if they are not provided from IMDS then it will
- fallback to using the OVF file provided from the CD-ROM. There is a large
- performance benefit to using IMDS for SSH key retrieval, but in order to
- support environments where IMDS is not available then we must continue to
- all for keys from OVF
-
-
-Configuration
--------------
-The following configuration can be set for the datasource in system
-configuration (in ``/etc/cloud/cloud.cfg`` or ``/etc/cloud/cloud.cfg.d/``).
-
-The settings that may be configured are:
-
- * **apply_network_config**: Boolean set to True to use network configuration
- described by Azure's IMDS endpoint instead of fallback network config of
- dhcp on eth0. Default is True. For Ubuntu 16.04 or earlier, default is
- False.
- * **data_dir**: Path used to read metadata files and write crawled data.
- * **disk_aliases**: A dictionary defining which device paths should be
- interpreted as ephemeral images. See cc_disk_setup module for more info.
-
-Configuration for the datasource can also be read from a
-``dscfg`` entry in the ``LinuxProvisioningConfigurationSet``. Content in
-dscfg node is expected to be base64 encoded yaml content, and it will be
-merged into the 'datasource: Azure' entry.
-
-An example configuration with the default values is provided below:
-
-.. code-block:: yaml
-
- datasource:
- Azure:
- apply_network_config: true
- data_dir: /var/lib/waagent
- disk_aliases:
- ephemeral0: /dev/disk/cloud/azure_resource
-
-
-Userdata
---------
-Userdata is provided to cloud-init inside the ovf-env.xml file. Cloud-init
-expects that user-data will be provided as base64 encoded value inside the
-text child of a element named ``UserData`` or ``CustomData`` which is a direct
-child of the ``LinuxProvisioningConfigurationSet`` (a sibling to ``UserName``)
-If both ``UserData`` and ``CustomData`` are provided behavior is undefined on
-which will be selected.
-
-In the example below, user-data provided is 'this is my userdata'
-
-Example:
-
-.. code-block:: xml
-
- <wa:ProvisioningSection>
- <wa:Version>1.0</wa:Version>
- <LinuxProvisioningConfigurationSet
- xmlns="http://schemas.microsoft.com/windowsazure"
- xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
- <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
- <HostName>myHost</HostName>
- <UserName>myuser</UserName>
- <UserPassword/>
- <CustomData>dGhpcyBpcyBteSB1c2VyZGF0YQ===</CustomData>
- <dscfg>eyJhZ2VudF9jb21tYW5kIjogWyJzdGFydCIsICJ3YWxpbnV4YWdlbnQiXX0=</dscfg>
- <DisableSshPasswordAuthentication>true</DisableSshPasswordAuthentication>
- <SSH>
- <PublicKeys>
- <PublicKey>
- <Fingerprint>6BE7A7C3C8A8F4B123CCA5D0C2F1BE4CA7B63ED7</Fingerprint>
- <Path>this-value-unused</Path>
- </PublicKey>
- </PublicKeys>
- </SSH>
- </LinuxProvisioningConfigurationSet>
- </wa:ProvisioningSection>
-
-hostname
---------
-When the user launches an instance, they provide a hostname for that instance.
-The hostname is provided to the instance in the ovf-env.xml file as
-``HostName``.
-
-Whatever value the instance provides in its dhcp request will resolve in the
-domain returned in the 'search' request.
-
-A generic image will already have a hostname configured. The ubuntu
-cloud images have 'ubuntu' as the hostname of the system, and the
-initial dhcp request on eth0 is not guaranteed to occur after the
-datasource code has been run. So, on first boot, that initial value
-will be sent in the dhcp request and *that* value will resolve.
-
-In order to make the ``HostName`` provided in the ovf-env.xml resolve,
-a dhcp request must be made with the new value. cloud-init handles
-this by setting the hostname in the DataSource's 'get_data' method via
-'``hostname $HostName``', and then bouncing the interface. This
-behavior can be configured or disabled in the datasource config. See
-'Configuration' above.
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/cloudsigma.rst b/doc/rtd/topics/datasources/cloudsigma.rst
deleted file mode 100644
index dee665a4..00000000
--- a/doc/rtd/topics/datasources/cloudsigma.rst
+++ /dev/null
@@ -1,42 +0,0 @@
-.. _datasource_cloudsigma:
-
-CloudSigma
-==========
-
-This datasource finds metadata and user-data from the `CloudSigma`_ cloud
-platform. Data transfer occurs through a virtual serial port of the
-`CloudSigma`_'s VM and the presence of network adapter is **NOT** a
-requirement, See `server context`_ in the public documentation for more
-information.
-
-
-Setting a hostname
-------------------
-By default the name of the server will be applied as a hostname on the first
-boot.
-
-
-Providing user-data
--------------------
-
-You can provide user-data to the VM using the dedicated `meta field`_ in the
-`server context`_ ``cloudinit-user-data``. By default *cloud-config* format is
-expected there and the ``#cloud-config`` header could be omitted. However
-since this is a raw-text field you could provide any of the valid `config
-formats`_.
-
-You have the option to encode your user-data using Base64. In order to do that
-you have to add the ``cloudinit-user-data`` field to the ``base64_fields``.
-The latter is a comma-separated field with all the meta fields whit base64
-encoded values.
-
-If your user-data does not need an internet connection you can create a `meta
-field`_ in the `server context`_ ``cloudinit-dsmode`` and set "local" as
-value. If this field does not exist the default value is "net".
-
-
-.. _CloudSigma: http://cloudsigma.com/
-.. _server context: http://cloudsigma-docs.readthedocs.org/en/latest/server_context.html
-.. _meta field: http://cloudsigma-docs.readthedocs.org/en/latest/meta.html
-.. _config formats: http://cloudinit.readthedocs.org/en/latest/topics/format.html
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/cloudstack.rst b/doc/rtd/topics/datasources/cloudstack.rst
deleted file mode 100644
index 93633308..00000000
--- a/doc/rtd/topics/datasources/cloudstack.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-.. _datasource_cloudstack:
-
-CloudStack
-==========
-
-`Apache CloudStack`_ expose user-data, meta-data, user password and account
-SSH key thru the Virtual-Router. The datasource obtains the VR address via
-dhcp lease information given to the instance.
-For more details on meta-data and user-data,
-refer the `CloudStack Administrator Guide`_.
-
-URLs to access user-data and meta-data from the Virtual Machine.
-`data-server.` is a well-known hostname provided by the CloudStack virtual
-router that points to the next UserData server (which is usually also
-the virtual router).
-
-.. code-block:: bash
-
- http://data-server./latest/user-data
- http://data-server./latest/meta-data
- http://data-server./latest/meta-data/{metadata type}
-
-If `data-server.` cannot be resolved, cloud-init will try to obtain the
-virtual router's address from the system's DHCP leases. If that fails,
-it will use the system's default gateway.
-
-Configuration
--------------
-The following configuration can be set for the datasource in system
-configuration (in `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d/`).
-
-The settings that may be configured are:
-
- * **max_wait**: the maximum amount of clock time in seconds that should be
- spent searching metadata_urls. A value less than zero will result in only
- one request being made, to the first in the list. (default: 120)
- * **timeout**: the timeout value provided to urlopen for each individual http
- request. This is used both when selecting a metadata_url and when crawling
- the metadata service. (default: 50)
-
-An example configuration with the default values is provided below:
-
-.. code-block:: yaml
-
- datasource:
- CloudStack:
- max_wait: 120
- timeout: 50
-
-
-.. _Apache CloudStack: http://cloudstack.apache.org/
-.. _CloudStack Administrator Guide: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/virtual_machines.html#user-data-and-meta-data
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/configdrive.rst b/doc/rtd/topics/datasources/configdrive.rst
deleted file mode 100644
index 777597c2..00000000
--- a/doc/rtd/topics/datasources/configdrive.rst
+++ /dev/null
@@ -1,133 +0,0 @@
-.. _datasource_config_drive:
-
-Config Drive
-============
-
-The configuration drive datasource supports the `OpenStack`_ configuration
-drive disk.
-
- See `the config drive extension`_ and `metadata introduction`_ in the public
- documentation for more information.
-
-By default, cloud-init does *always* consider this source to be a full-fledged
-datasource. Instead, the typical behavior is to assume it is really only
-present to provide networking information. Cloud-init will copy off the
-network information, apply it to the system, and then continue on. The "full"
-datasource could then be found in the EC2 metadata service. If this is not the
-case then the files contained on the located drive must provide equivalents to
-what the EC2 metadata service would provide (which is typical of the version 2
-support listed below)
-
-.. dropdown:: Version 1 (Deprecated)
-
- **Note:** Version 1 is legacy and should be considered deprecated.
- Version 2 has been supported in OpenStack since 2012.2 (Folsom).
-
- The following criteria are required to as a config drive:
-
- 1. Must be formatted with `vfat`_ filesystem
- 2. Must contain *one* of the following files
-
- ::
-
- /etc/network/interfaces
- /root/.ssh/authorized_keys
- /meta.js
-
- ``/etc/network/interfaces``
-
- This file is laid down by nova in order to pass static networking
- information to the guest. Cloud-init will copy it off of the
- config-drive and into /etc/network/interfaces (or convert it to RH
- format) as soon as it can, and then attempt to bring up all network
- interfaces.
-
- ``/root/.ssh/authorized_keys``
-
- This file is laid down by nova, and contains the ssk keys that were
- provided to nova on instance creation (nova-boot --key ....)
-
- ``/meta.js``
-
- meta.js is populated on the config-drive in response to the user
- passing "meta flags" (nova boot --meta key=value ...). It is
- expected to be json formatted.
-
-
-Version 2
----------
-
-The following criteria are required to as a config drive:
-
-1. Must be formatted with `vfat`_ or `iso9660`_ filesystem
- or have a *filesystem* label of **config-2** or **CONFIG-2**
-2. The files that will typically be present in the config drive are:
-
-::
-
- openstack/
- - 2012-08-10/ or latest/
- - meta_data.json
- - user_data (not mandatory)
- - content/
- - 0000 (referenced content files)
- - 0001
- - ....
- ec2
- - latest/
- - meta-data.json (not mandatory)
-
-Keys and values
----------------
-
-Cloud-init's behavior can be modified by keys found in the meta.js (version 1
-only) file in the following ways.
-
-::
-
- dsmode:
- values: local, net, pass
- default: pass
-
-
-This is what indicates if configdrive is a final data source or not.
-By default it is 'pass', meaning this datasource should not be read.
-Set it to 'local' or 'net' to stop cloud-init from continuing on to
-search for other data sources after network config.
-
-The difference between 'local' and 'net' is that local will not require
-networking to be up before user-data actions (or boothooks) are run.
-
-::
-
- instance-id:
- default: iid-dsconfigdrive
-
-This is utilized as the metadata's instance-id. It should generally
-be unique, as it is what is used to determine "is this a new instance".
-
-::
-
- public-keys:
- default: None
-
-If present, these keys will be used as the public keys for the
-instance. This value overrides the content in authorized_keys.
-
-Note: it is likely preferable to provide keys via user-data
-
-::
-
- user-data:
- default: None
-
-This provides cloud-init user-data. See :ref:`examples <yaml_examples>` for
-what all can be present here.
-
-.. _OpenStack: http://www.openstack.org/
-.. _metadata introduction: https://docs.openstack.org/nova/latest/user/metadata.html#config-drives
-.. _python-novaclient: https://github.com/openstack/python-novaclient
-.. _iso9660: https://en.wikipedia.org/wiki/ISO_9660
-.. _vfat: https://en.wikipedia.org/wiki/File_Allocation_Table
-.. _the config drive extension: https://docs.openstack.org/nova/latest/admin/config-drive.html
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/digitalocean.rst b/doc/rtd/topics/datasources/digitalocean.rst
deleted file mode 100644
index 801841c1..00000000
--- a/doc/rtd/topics/datasources/digitalocean.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-.. _datasource_digital_ocean:
-
-DigitalOcean
-============
-
-The `DigitalOcean`_ datasource consumes the content served from DigitalOcean's
-`metadata service`_. This metadata service serves information about the
-running droplet via HTTP over the link local address 169.254.169.254. The
-metadata API endpoints are fully described at
-`https://developers.digitalocean.com/metadata/
-<https://developers.digitalocean.com/metadata/>`_.
-
-Configuration
--------------
-
-DigitalOcean's datasource can be configured as follows:
-
- datasource:
- DigitalOcean:
- retries: 3
- timeout: 2
-
-- *retries*: Determines the number of times to attempt to connect to the
- metadata service
-- *timeout*: Determines the timeout in seconds to wait for a response from the
- metadata service
-
-.. _DigitalOcean: http://digitalocean.com/
-.. _metadata service: https://developers.digitalocean.com/metadata/
-.. _Full documentation: https://developers.digitalocean.com/metadata/
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/e24cloud.rst b/doc/rtd/topics/datasources/e24cloud.rst
deleted file mode 100644
index 2af6634b..00000000
--- a/doc/rtd/topics/datasources/e24cloud.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-.. _datasource_e24cloud:
-
-E24Cloud
-========
-`E24Cloud <https://www.e24cloud.com/en/>`_ platform provides an AWS Ec2 metadata
-service clone. It identifies itself to guests using the dmi
-system-manufacturer (/sys/class/dmi/id/sys_vendor).
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/ec2.rst b/doc/rtd/topics/datasources/ec2.rst
deleted file mode 100644
index bbc4ee4e..00000000
--- a/doc/rtd/topics/datasources/ec2.rst
+++ /dev/null
@@ -1,141 +0,0 @@
-.. _datasource_ec2:
-
-Amazon EC2
-==========
-
-The EC2 datasource is the oldest and most widely used datasource that
-cloud-init supports. This datasource interacts with a *magic* ip that is
-provided to the instance by the cloud provider. Typically this ip is
-``169.254.169.254`` of which at this ip a http server is provided to the
-instance so that the instance can make calls to get instance userdata and
-instance metadata.
-
-Metadata is accessible via the following URL:
-
-::
-
- GET http://169.254.169.254/2009-04-04/meta-data/
- ami-id
- ami-launch-index
- ami-manifest-path
- block-device-mapping/
- hostname
- instance-id
- instance-type
- local-hostname
- local-ipv4
- placement/
- public-hostname
- public-ipv4
- public-keys/
- reservation-id
- security-groups
-
-Userdata is accessible via the following URL:
-
-::
-
- GET http://169.254.169.254/2009-04-04/user-data
- 1234,fred,reboot,true | 4512,jimbo, | 173,,,
-
-Note that there are multiple EC2 Metadata versions of this data provided
-to instances. cloud-init will attempt to use the most recent API version it
-supports in order to get latest API features and instance-data. If a given
-API version is not exposed to the instance, those API features will be
-unavailable to the instance.
-
-
-+----------------+----------------------------------------------------------+
-+ EC2 version | supported instance-data/feature |
-+================+==========================================================+
-+ **2021-03-23** | Required for Instance tag support. This feature must be |
-| | enabled individually on each instance. See the |
-| | `EC2 tags user guide`_. |
-+----------------+----------------------------------------------------------+
-| **2016-09-02** | Required for secondary IP address support. |
-+----------------+----------------------------------------------------------+
-| **2009-04-04** | Minimum supports EC2 API version for meta-data and |
-| | user-data. |
-+----------------+----------------------------------------------------------+
-
-
-To see which versions are supported from your cloud provider use the following
-URL:
-
-::
-
- GET http://169.254.169.254/
- 1.0
- 2007-01-19
- 2007-03-01
- 2007-08-29
- 2007-10-10
- 2007-12-15
- 2008-02-01
- 2008-09-01
- 2009-04-04
- ...
- latest
-
-
-
-Configuration
--------------
-The following configuration can be set for the datasource in system
-configuration (in `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d/`).
-
-The settings that may be configured are:
-
- * **metadata_urls**: This list of urls will be searched for an EC2
- metadata service. The first entry that successfully returns a 200 response
- for <url>/<version>/meta-data/instance-id will be selected.
- (default: ['http://169.254.169.254', 'http://[fd00:ec2::254]',
- 'http://instance-data:8773']).
- * **max_wait**: the maximum amount of clock time in seconds that should be
- spent searching metadata_urls. A value less than zero will result in only
- one request being made, to the first in the list. (default: 120)
- * **timeout**: the timeout value provided to urlopen for each individual http
- request. This is used both when selecting a metadata_url and when crawling
- the metadata service. (default: 50)
- * **apply_full_imds_network_config**: Boolean (default: True) to allow
- cloud-init to configure any secondary NICs and secondary IPs described by
- the metadata service. All network interfaces are configured with DHCP (v4)
- to obtain an primary IPv4 address and route. Interfaces which have a
- non-empty 'ipv6s' list will also enable DHCPv6 to obtain a primary IPv6
- address and route. The DHCP response (v4 and v6) return an IP that matches
- the first element of local-ipv4s and ipv6s lists respectively. All
- additional values (secondary addresses) in the static ip lists will be
- added to interface.
-
-An example configuration with the default values is provided below:
-
-.. code-block:: yaml
-
- datasource:
- Ec2:
- metadata_urls: ["http://169.254.169.254:80", "http://instance-data:8773"]
- max_wait: 120
- timeout: 50
- apply_full_imds_network_config: true
-
-Notes
------
- * There are 2 types of EC2 instances network-wise: VPC ones (Virtual Private
- Cloud) and Classic ones (also known as non-VPC). One major difference
- between them is that Classic instances have their MAC address changed on
- stop/restart operations, so cloud-init will recreate the network config
- file for EC2 Classic instances every boot. On VPC instances this file is
- generated only in the first boot of the instance.
- The check for the instance type is performed by is_classic_instance()
- method.
-
- * For EC2 instances with multiple network interfaces (NICs) attached, dhcp4
- will be enabled to obtain the primary private IPv4 address of those NICs.
- Wherever dhcp4 or dhcp6 is enabled for a NIC, a dhcp route-metric will be
- added with the value of ``<device-number + 1> * 100`` to ensure dhcp
- routes on the primary NIC are preferred to any secondary NICs.
- For example: the primary NIC will have a DHCP route-metric of 100,
- the next NIC will be 200.
-
-.. _EC2 tags user guide: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/exoscale.rst b/doc/rtd/topics/datasources/exoscale.rst
deleted file mode 100644
index e5e946de..00000000
--- a/doc/rtd/topics/datasources/exoscale.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-.. _datasource_exoscale:
-
-Exoscale
-========
-
-This datasource supports reading from the metadata server used on the
-`Exoscale platform <https://exoscale.com>`_.
-
-Use of the Exoscale datasource is recommended to benefit from new features of
-the Exoscale platform.
-
-The datasource relies on the availability of a compatible metadata server
-(``http://169.254.169.254`` is used by default) and its companion password
-server, reachable at the same address (by default on port 8080).
-
-Crawling of metadata
---------------------
-
-The metadata service and password server are crawled slightly differently:
-
- * The "metadata service" is crawled every boot.
- * The password server is also crawled every boot (the Exoscale datasource
- forces the password module to run with "frequency always").
-
-In the password server case, the following rules apply in order to enable the
-"restore instance password" functionality:
-
- * If a password is returned by the password server, it is then marked "saved"
- by the cloud-init datasource. Subsequent boots will skip setting the
- password (the password server will return "saved_password").
- * When the instance password is reset (via the Exoscale UI), the password
- server will return the non-empty password at next boot, therefore causing
- cloud-init to reset the instance's password.
-
-Configuration
--------------
-
-Users of this datasource are discouraged from changing the default settings
-unless instructed to by Exoscale support.
-
-The following settings are available and can be set for the
-:ref:`datasource base configuration<datasource_base_config>`
-(in `/etc/cloud/cloud.cfg.d/`).
-
-The settings available are:
-
- * **metadata_url**: The URL for the metadata service (defaults to
- ``http://169.254.169.254``)
- * **api_version**: The API version path on which to query the instance
- metadata (defaults to ``1.0``)
- * **password_server_port**: The port (on the metadata server) on which the
- password server listens (defaults to ``8080``).
- * **timeout**: the timeout value provided to urlopen for each individual http
- request. (defaults to ``10``)
- * **retries**: The number of retries that should be done for an http request
- (defaults to ``6``)
-
-
-An example configuration with the default values is provided below:
-
-.. code-block:: yaml
-
- datasource:
- Exoscale:
- metadata_url: "http://169.254.169.254"
- api_version: "1.0"
- password_server_port: 8080
- timeout: 10
- retries: 6
diff --git a/doc/rtd/topics/datasources/fallback.rst b/doc/rtd/topics/datasources/fallback.rst
deleted file mode 100644
index 03658f54..00000000
--- a/doc/rtd/topics/datasources/fallback.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-.. _datasource_fallback:
-
-Fallback/None
-=============
-
-This is the fallback datasource when no other datasource can be selected. It
-is the equivalent of a empty datasource in that it provides a empty string as
-userdata and a empty dictionary as metadata. It is useful for testing as well
-as for when you do not have a need to have an actual datasource to meet your
-instance requirements (ie you just want to run modules that are not concerned
-with any external data). It is typically put at the end of the datasource
-search list so that if all other datasources are not matched, then this one
-will be so that the user is not left with an inaccessible instance.
-
-**Note:** the instance id that this datasource provides is
-``iid-datasource-none``.
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/nocloud.rst b/doc/rtd/topics/datasources/nocloud.rst
deleted file mode 100644
index 67a4ea67..00000000
--- a/doc/rtd/topics/datasources/nocloud.rst
+++ /dev/null
@@ -1,191 +0,0 @@
-.. _datasource_nocloud:
-
-NoCloud
-=======
-
-The data source ``NoCloud`` allows the user to provide user-data and meta-data
-to the instance without running a network service (or even without having a
-network at all).
-
-You can provide meta-data and user-data to a local vm boot via files on a
-`vfat`_ or `iso9660`_ filesystem. The filesystem volume label must be
-``cidata`` or ``CIDATA``.
-
-Alternatively, you can provide meta-data via kernel command line or SMBIOS
-"serial number" option. The data must be passed in the form of a string:
-
-::
-
- ds=nocloud[;key=val;key=val]
-
-or
-
-::
-
- ds=nocloud-net[;key=val;key=val]
-
-The permitted keys are:
-
-- ``h`` or ``local-hostname``
-- ``i`` or ``instance-id``
-- ``s`` or ``seedfrom``
-
-With ``ds=nocloud``, the ``seedfrom`` value must start with ``/`` or
-``file://``. With ``ds=nocloud-net``, the ``seedfrom`` value must start
-with ``http://`` or ``https://`` and end with a trailing ``/``.
-
-Cloud-init performs variable expansion of the seedfrom URL for any DMI kernel
-variables present in ``/sys/class/dmi/id`` (kenv on FreeBSD).
-Your ``seedfrom`` URL can contain variable names of the format
-``__dmi.varname__`` to indicate to cloud-init NoCloud datasource that
-dmi.varname should be expanded to the value of the DMI system attribute wanted.
-
-.. list-table:: Available DMI variables for expansion in ``seedfrom`` URL
- :widths: 35 35 30
- :header-rows: 0
-
- * - ``dmi.baseboard-asset-tag``
- - ``dmi.baseboard-manufacturer``
- - ``dmi.baseboard-version``
- * - ``dmi.bios-release-date``
- - ``dmi.bios-vendor``
- - ``dmi.bios-version``
- * - ``dmi.chassis-asset-tag``
- - ``dmi.chassis-manufacturer``
- - ``dmi.chassis-serial-number``
- * - ``dmi.chassis-version``
- - ``dmi.system-manufacturer``
- - ``dmi.system-product-name``
- * - ``dmi.system-serial-number``
- - ``dmi.system-uuid``
- - ``dmi.system-version``
-
-
-For example, passing this option to QEMU
-
-::
-
- -smbios type=1,serial=ds=nocloud-net;s=http://10.10.0.1:8000/__dmi.chassis-serial-number__/
-
-causes NoCloud to fetch the full meta-data from a URL based on YOUR_SERIAL_NUMBER as seen in `/sys/class/dmi/id/chassis_serial_number` (kenv on FreeBSD) from http://10.10.0.1:8000/YOUR_SERIAL_NUMBER/meta-data
-after the network initialization is complete.
-
-These user-data and meta-data files are required as separate files at the same
-base URL.
-
-::
-
- /user-data
- /meta-data
-
-Both files are required to be present for it to be considered a valid seed ISO.
-
-Basically, user-data is simply :ref:`user data<user_data_formats>` and
-meta-data is a YAML formatted file representing what you'd find in the EC2
-metadata service.
-
-You may also optionally provide a vendor-data file as a separate file adhering
-to :ref:`user data formats<user_data_formats>` in the same base URL.
-
-::
-
- /vendor-data
-
-Given a disk ubuntu cloud image in 'disk.img', you can create a
-sufficient disk by following the example below.
-
-::
-
- ## 1) create user-data and meta-data files that will be used
- ## to modify image on first boot
- $ echo -e "instance-id: iid-local01\nlocal-hostname: cloudimg" > meta-data
- $ echo -e "#cloud-config\npassword: passw0rd\nchpasswd: { expire: False }\nssh_pwauth: True\n" > user-data
-
- ## 2a) create a disk to attach with some user-data and meta-data
- $ genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
-
- ## 2b) alternatively, create a vfat filesystem with same files
- ## $ truncate --size 2M seed.iso
- ## $ mkfs.vfat -n cidata seed.iso
-
- ## 2b) option 1: mount and copy files
- ## $ sudo mount -t vfat seed.iso /mnt
- ## $ sudo cp user-data meta-data /mnt
- ## $ sudo umount /mnt
-
- ## 2b) option 2: the mtools package provides mcopy, which can access vfat
- ## filesystems without mounting them
- ## $ mcopy -oi seed.iso user-data meta-data
-
- ## 3) create a new qcow image to boot, backed by your original image
- $ qemu-img create -f qcow2 -b disk.img -F qcow2 boot-disk.img
-
- ## 4) boot the image and login as 'ubuntu' with password 'passw0rd'
- ## note, passw0rd was set as password through the user-data above,
- ## there is no password set on these images.
- $ kvm -m 256 \
- -net nic -net user,hostfwd=tcp::2222-:22 \
- -drive file=boot-disk.img,if=virtio \
- -drive driver=raw,file=seed.iso,if=virtio
-
-**Note:** that the instance-id provided (``iid-local01`` above) is what is used
-to determine if this is "first boot". So if you are making updates to
-user-data you will also have to change that, or start the disk fresh.
-
-Also, you can inject an ``/etc/network/interfaces`` file by providing the
-content for that file in the ``network-interfaces`` field of metadata.
-
-Example metadata:
-
-::
-
- instance-id: iid-abcdefg
- network-interfaces: |
- iface eth0 inet static
- address 192.168.1.10
- network 192.168.1.0
- netmask 255.255.255.0
- broadcast 192.168.1.255
- gateway 192.168.1.254
- hostname: myhost
-
-
-Network configuration can also be provided to cloud-init in either
-:ref:`network_config_v1` or :ref:`network_config_v2` by providing that
-YAML formatted data in a file named ``network-config``. If found,
-this file will override a ``network-interfaces`` file.
-
-See an example below. Note specifically that this file does not
-have a top level ``network`` key as it is already assumed to
-be network configuration based on the filename.
-
-.. code-block:: yaml
-
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: "52:54:00:12:34:00"
- subnets:
- - type: static
- address: 192.168.1.10
- netmask: 255.255.255.0
- gateway: 192.168.1.254
-
-
-.. code-block:: yaml
-
- version: 2
- ethernets:
- interface0:
- match:
- macaddress: "52:54:00:12:34:00"
- set-name: interface0
- addresses:
- - 192.168.1.10/255.255.255.0
- gateway4: 192.168.1.254
-
-
-.. _iso9660: https://en.wikipedia.org/wiki/ISO_9660
-.. _vfat: https://en.wikipedia.org/wiki/File_Allocation_Table
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/nwcs.rst b/doc/rtd/topics/datasources/nwcs.rst
deleted file mode 100644
index 2b6543d3..00000000
--- a/doc/rtd/topics/datasources/nwcs.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-.. _datasource_nwcs:
-
-NWCS
-=====
-
-The NWCS datasource retrieves basic configuration values from the locally
-accessible metadata service. All data is served over HTTP from the address
-169.254.169.254.
-
-Configuration
--------------
-
-NWCS' datasource can be configured as follows:
-
- datasource:
- NWCS:
- url: 'http://169.254.169.254'
- retries: 3
- timeout: 2
- wait: 2
-
-- *url*: The URL used to acquire the metadata configuration from
-- *retries*: Determines the number of times to attempt to connect to the
- metadata service
-- *timeout*: Determines the timeout in seconds to wait for a response from the
- metadata service
-- *wait*: Determines the timeout in seconds to wait before retrying after
- accessible failure
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/openstack.rst b/doc/rtd/topics/datasources/openstack.rst
deleted file mode 100644
index 286b2f44..00000000
--- a/doc/rtd/topics/datasources/openstack.rst
+++ /dev/null
@@ -1,93 +0,0 @@
-.. _datasource_openstack:
-
-OpenStack
-=========
-
-This datasource supports reading data from the
-`OpenStack Metadata Service
-<https://docs.openstack.org/nova/latest/admin/metadata-service.html>`_.
-
-Discovery
--------------
-To determine whether a platform looks like it may be OpenStack, cloud-init
-checks the following environment attributes as a potential OpenStack platform:
-
- * Maybe OpenStack if:
-
- * **non-x86 cpu architecture**: because DMI data is buggy on some arches
- * Is OpenStack **if x86 architecture and ANY** of the following:
-
- * **/proc/1/environ**: Nova-lxd contains *product_name=OpenStack Nova*
- * **DMI product_name**: Either *Openstack Nova* or *OpenStack Compute*
- * **DMI chassis_asset_tag** is *HUAWEICLOUD*, *OpenTelekomCloud*,
- *SAP CCloud VM*, *OpenStack Nova* (since 19.2) or
- *OpenStack Compute* (since 19.2)
-
-Configuration
--------------
-The following configuration can be set for the datasource in system
-configuration (in `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d/`).
-
-The settings that may be configured are:
-
- * **metadata_urls**: This list of urls will be searched for an OpenStack
- metadata service. The first entry that successfully returns a 200 response
- for <url>/openstack will be selected. (default: ['http://169.254.169.254'])
- * **max_wait**: the maximum amount of clock time in seconds that should be
- spent searching metadata_urls. A value less than zero will result in only
- one request being made, to the first in the list. (default: -1)
- * **timeout**: the timeout value provided to urlopen for each individual http
- request. This is used both when selecting a metadata_url and when crawling
- the metadata service. (default: 10)
- * **retries**: The number of retries that should be done for an http request.
- This value is used only after metadata_url is selected. (default: 5)
- * **apply_network_config**: A boolean specifying whether to configure the
- network for the instance based on network_data.json provided by the
- metadata service. When False, only configure dhcp on the primary nic for
- this instances. (default: True)
-
-An example configuration with the default values is provided below:
-
-.. code-block:: yaml
-
- datasource:
- OpenStack:
- metadata_urls: ["http://169.254.169.254"]
- max_wait: -1
- timeout: 10
- retries: 5
- apply_network_config: True
-
-
-Vendor Data
------------
-
-The OpenStack metadata server can be configured to serve up vendor data
-which is available to all instances for consumption. OpenStack vendor
-data is, generally, a JSON object.
-
-cloud-init will look for configuration in the ``cloud-init`` attribute
-of the vendor data JSON object. cloud-init processes this configuration
-using the same handlers as user data, so any formats that work for user
-data should work for vendor data.
-
-For example, configuring the following as vendor data in OpenStack would
-upgrade packages and install ``htop`` on all instances:
-
-.. code-block:: json
-
- {"cloud-init": "#cloud-config\npackage_upgrade: True\npackages:\n - htop"}
-
-For more general information about how cloud-init handles vendor data,
-including how it can be disabled by users on instances, see
-:doc:`/topics/vendordata`.
-
-OpenStack can also be configured to provide 'dynamic vendordata'
-which is provided by the DynamicJSON provider and appears under a
-different metadata path, /vendor_data2.json.
-
-Cloud-init will look for a ``cloud-init`` at the vendor_data2 path; if found,
-settings are applied after (and, hence, overriding) the settings from static
-vendor data. Both sets of vendor data can be overridden by user data.
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/oracle.rst b/doc/rtd/topics/datasources/oracle.rst
deleted file mode 100644
index 4b4b23b2..00000000
--- a/doc/rtd/topics/datasources/oracle.rst
+++ /dev/null
@@ -1,49 +0,0 @@
-.. _datasource_oracle:
-
-Oracle
-======
-
-This datasource reads metadata, vendor-data and user-data from
-`Oracle Compute Infrastructure`_ (OCI).
-
-Oracle Platform
----------------
-OCI provides bare metal and virtual machines. In both cases,
-the platform identifies itself via DMI data in the chassis asset tag
-with the string 'OracleCloud.com'.
-
-Oracle's platform provides a metadata service that mimics the 2013-10-17
-version of OpenStack metadata service. Initially support for Oracle
-was done via the OpenStack datasource.
-
-Cloud-init has a specific datasource for Oracle in order to:
- a. allow and support future growth of the OCI platform.
- b. address small differences between OpenStack and Oracle metadata
- implementation.
-
-
-Configuration
--------------
-
-The following configuration can be set for the datasource in system
-configuration (in ``/etc/cloud/cloud.cfg`` or ``/etc/cloud/cloud.cfg.d/``).
-
-The settings that may be configured are:
-
-* **configure_secondary_nics**: A boolean, defaulting to False. If set
- to True on an OCI Virtual Machine, cloud-init will fetch networking
- metadata from Oracle's IMDS and use it to configure the non-primary
- network interface controllers in the system. If set to True on an
- OCI Bare Metal Machine, it will have no effect (though this may
- change in the future).
-
-An example configuration with the default values is provided below:
-
-.. code-block:: yaml
-
- datasource:
- Oracle:
- configure_secondary_nics: false
-
-.. _Oracle Compute Infrastructure: https://cloud.oracle.com/
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/ovf.rst b/doc/rtd/topics/datasources/ovf.rst
deleted file mode 100644
index 9f248476..00000000
--- a/doc/rtd/topics/datasources/ovf.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-.. _datasource_ovf:
-
-OVF
-===
-
-The OVF Datasource provides a datasource for reading data from
-on an `Open Virtualization Format
-<https://en.wikipedia.org/wiki/Open_Virtualization_Format>`_ ISO
-transport.
-
-For further information see a full working example in cloud-init's
-source code tree in doc/sources/ovf
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/rbxcloud.rst b/doc/rtd/topics/datasources/rbxcloud.rst
deleted file mode 100644
index cbbf6900..00000000
--- a/doc/rtd/topics/datasources/rbxcloud.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-.. _datasource_rbx:
-
-Rbx Cloud
-=========
-
-The Rbx datasource consumes the metadata drive available on platform
-`HyperOne`_ and `Rootbox`_ platform.
-
-Datasource supports, in particular, network configurations, hostname,
-user accounts and user metadata.
-
-Metadata drive
---------------
-
-Drive metadata is a `FAT`_-formatted partition with the ```CLOUDMD``` or
-```cloudmd``` label on the system disk. Its contents are refreshed each time
-the virtual machine is restarted, if the partition exists. For more information
-see `HyperOne Virtual Machine docs`_.
-
-.. _HyperOne: http://www.hyperone.com/
-.. _Rootbox: https://rootbox.com/
-.. _HyperOne Virtual Machine docs: http://www.hyperone.com/
-.. _FAT: https://en.wikipedia.org/wiki/File_Allocation_Table
diff --git a/doc/rtd/topics/datasources/smartos.rst b/doc/rtd/topics/datasources/smartos.rst
deleted file mode 100644
index 85bc7eff..00000000
--- a/doc/rtd/topics/datasources/smartos.rst
+++ /dev/null
@@ -1,170 +0,0 @@
-.. _datasource_smartos:
-
-SmartOS Datasource
-==================
-
-This datasource finds metadata and user-data from the SmartOS virtualization
-platform (i.e. Joyent).
-
-Please see http://smartos.org/ for information about SmartOS.
-
-SmartOS Platform
-----------------
-The SmartOS virtualization platform uses meta-data to the instance via the
-second serial console. On Linux, this is /dev/ttyS1. The data is a provided
-via a simple protocol: something queries for the data, the console responds
-with the status and if "SUCCESS" returns until a single ".\n".
-
-New versions of the SmartOS tooling will include support for base64 encoded
-data.
-
-Meta-data channels
-------------------
-
-Cloud-init supports three modes of delivering user/meta-data via the flexible
-channels of SmartOS.
-
-* user-data is written to /var/db/user-data
-
- - per the spec, user-data is for consumption by the end-user, not
- provisioning tools
- - cloud-init entirely ignores this channel other than writing it to disk
- - removal of the meta-data key means that /var/db/user-data gets removed
- - a backup of previous meta-data is maintained as
- /var/db/user-data.<timestamp>. <timestamp> is the epoch time when
- cloud-init ran
-
-* user-script is written to /var/lib/cloud/scripts/per-boot/99_user_data
-
- - this is executed each boot
- - a link is created to /var/db/user-script
- - previous versions of the user-script is written to
- /var/lib/cloud/scripts/per-boot.backup/99_user_script.<timestamp>.
- - <timestamp> is the epoch time when cloud-init ran.
- - when the 'user-script' meta-data key goes missing, the user-script is
- removed from the file system, although a backup is maintained.
- - if the script does not start with a shebang (i.e. starts with
- #!<executable>), then or is not an executable, cloud-init will add a
- shebang of "#!/bin/bash"
-
-* cloud-init:user-data is treated like on other Clouds.
-
- - this channel is used for delivering _all_ cloud-init instructions
- - scripts delivered over this channel must be well formed (i.e. must have
- a shebang)
-
-Cloud-init supports reading the traditional meta-data fields supported by the
-SmartOS tools. These are:
-
- * root_authorized_keys
- * hostname
- * enable_motd_sys_info
- * iptables_disable
-
-Note: At this time iptables_disable and enable_motd_sys_info are read but
- are not actioned.
-
-Disabling user-script
----------------------
-
-Cloud-init uses the per-boot script functionality to handle the execution
-of the user-script. If you want to prevent this use a cloud-config of:
-
-.. code-block:: yaml
-
- #cloud-config
- cloud_final_modules:
- - scripts-per-once
- - scripts-per-instance
- - scripts-user
- - ssh-authkey-fingerprints
- - keys-to-console
- - phone-home
- - final-message
- - power-state-change
-
-Alternatively you can use the json patch method
-
-.. code-block:: yaml
-
- #cloud-config-jsonp
- [
- { "op": "replace",
- "path": "/cloud_final_modules",
- "value": ["scripts-per-once",
- "scripts-per-instance",
- "scripts-user",
- "ssh-authkey-fingerprints",
- "keys-to-console",
- "phone-home",
- "final-message",
- "power-state-change"]
- }
- ]
-
-The default cloud-config includes "script-per-boot". Cloud-init will still
-ingest and write the user-data but will not execute it, when you disable
-the per-boot script handling.
-
-Note: Unless you have an explicit use-case, it is recommended that you not
- disable the per-boot script execution, especially if you are using
- any of the life-cycle management features of SmartOS.
-
-The cloud-config needs to be delivered over the cloud-init:user-data channel
-in order for cloud-init to ingest it.
-
-base64
-------
-
-The following are exempt from base64 encoding, owing to the fact that they
-are provided by SmartOS:
-
- * root_authorized_keys
- * enable_motd_sys_info
- * iptables_disable
- * user-data
- * user-script
-
-This list can be changed through
-:ref:`datasource base configuration<datasource_base_config>` variable
-'no_base64_decode'.
-
-This means that user-script and user-data as well as other values can be
-base64 encoded. Since Cloud-init can only guess as to whether or not something
-is truly base64 encoded, the following meta-data keys are hints as to whether
-or not to base64 decode something:
-
- * base64_all: Except for excluded keys, attempt to base64 decode
- the values. If the value fails to decode properly, it will be
- returned in its text
- * base64_keys: A comma delimited list of which keys are base64 encoded.
- * b64-<key>:
- for any key, if there exists an entry in the metadata for 'b64-<key>'
- Then 'b64-<key>' is expected to be a plaintext boolean indicating whether
- or not its value is encoded.
- * no_base64_decode: This is a configuration setting
- (i.e. /etc/cloud/cloud.cfg.d) that sets which values should not be
- base64 decoded.
-
-disk_aliases and ephemeral disk
--------------------------------
-By default, SmartOS only supports a single ephemeral disk. That disk is
-completely empty (un-partitioned with no filesystem).
-
-The SmartOS datasource has built-in cloud-config which instructs the
-'disk_setup' module to partition and format the ephemeral disk.
-
-You can control the disk_setup then in 2 ways:
- 1. through the datasource config, you can change the 'alias' of
- ephermeral0 to reference another device. The default is:
-
- 'disk_aliases': {'ephemeral0': '/dev/vdb'},
-
- Which means anywhere disk_setup sees a device named 'ephemeral0'
- then /dev/vdb will be substituted.
- 2. you can provide disk_setup or fs_setup data in user-data to overwrite
- the datasource's built-in values.
-
-See doc/examples/cloud-config-disk-setup.txt for information on disk_setup.
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/upcloud.rst b/doc/rtd/topics/datasources/upcloud.rst
deleted file mode 100644
index 75f438ee..00000000
--- a/doc/rtd/topics/datasources/upcloud.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-.. _datasource_upcloud:
-
-UpCloud
-=============
-
-The `UpCloud`_ datasource consumes information from UpCloud's `metadata
-service`_. This metadata service serves information about the
-running server via HTTP over the address 169.254.169.254 available in every
-DHCP-configured interface. The metadata API endpoints are fully described in
-UpCloud API documentation at
-`https://developers.upcloud.com/1.3/8-servers/#metadata-service
-<https://developers.upcloud.com/1.3/8-servers/#metadata-service>`_.
-
-Providing user-data
--------------------
-
-When creating a server, user-data is provided by specifying it as `user_data`
-in the API or via the server creation tool in the control panel. User-data is
-immutable during server's lifetime and can be removed by deleting the server.
-
-.. _UpCloud: https://upcloud.com/
-.. _metadata service: https://upcloud.com/community/tutorials/upcloud-metadata-service/
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/vmware.rst b/doc/rtd/topics/datasources/vmware.rst
deleted file mode 100644
index b45ff3cc..00000000
--- a/doc/rtd/topics/datasources/vmware.rst
+++ /dev/null
@@ -1,434 +0,0 @@
-.. _datasource_vmware:
-
-VMware
-======
-
-This datasource is for use with systems running on a VMware platform such as
-vSphere and currently supports the following data transports:
-
-
-* `Guest OS Customization <https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-58E346FF-83AE-42B8-BE58-253641D257BC.html>`_
-* `GuestInfo <https://github.com/vmware/govmomi/blob/master/govc/USAGE.md>`_ keys
-
-Configuration
--------------
-
-The configuration method is dependent upon the transport:
-
-Guest OS Customization
-^^^^^^^^^^^^^^^^^^^^^^
-
-The following configuration can be set for this datasource in cloud-init
-configuration (in `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d/`).
-
-System configuration:
-
-``disable_vmware_customization``:
-true(disable) or false(enable) the vmware traditional Linux guest customization. Traditional Linux guest customization is customizing a Linux virtual machine with a `traditional Linux customization specification <https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-EB5F090E-723C-4470-B640-50B35D1EC016.html#GUID-9A5093A5-C54F-4502-941B-3F9C0F573A39__GUID-40C60643-A2EB-4B05-8927-B51AF7A6CC5E>`_. Also set this configuration to false is required to make sure this datasource is found in ds-identify when using guest os customization transport. (default: true)
-
-Datasource configuration:
-
-``allow_raw_data``:
-true(enable) or false(disable) the vmware customization using cloud-init
-metadata and userdata directly. Since vSphere 7.0 Update 3 version, user
-can create a Linux customizatino specification with barely cloud-init
-metadata and userdata and apply this kind specification to a virtual
-machine, this datasource will parse the metadata and userdata and
-configure virtual machine with them. See `Guest Customization Using
-cloud-init <https://developer.vmware.com/docs/17020/vsphere-web-services-sdk-programming-guide--8-0-/GUID-75E27FA9-2E40-4CBF-BF3D-22DCFC8F11F7.html>`_ (default: true)
-
-``vmware_cust_file_max_wait``:
-The maximum amount of clock time in seconds that should be spent waiting
-for vmware customization files. (default: 15)
-
-Configuration examples:
-
-1. Create a file /etc/cloud/cloud.cfg.d/99-vmware-guest-customization.cfg with
- below content will enable vmware customization, and set the maximum time of
- waiting for vmware customization file to 10 seconds:
-
-.. code-block:: yaml
-
- disable_vmware_customization: false
- datasource:
- VMware:
- vmware_cust_file_max_wait: 10
-
-2. Create a file /etc/cloud/cloud.cfg.d/99-vmware-guest-customization.cfg with
- below content will enable vmware customization, but only try to apply a
- traditional Linux guest customization configuration, and set the maximum time of
- waiting for vmware customization file to 10 seconds:
-
-.. code-block:: yaml
-
- disable_vmware_customization: false
- datasource:
- VMware:
- allow_raw_data: false
- vmware_cust_file_max_wait: 10
-
-VMware Tools configuration:
-
-`VMware Tools <https://docs.vmware.com/en/VMware-Tools/index.html>`_ is required for this datasource configuration
-settings as well as vCloud and vSphere admin configuration. User could change
-the VMware Tools configuration options with command:
-
-.. code-block:: shell
-
- vmware-toolbox-cmd config set <section> <key> <value>
-
-The following VMware Tools configuration option affects this datasource's
-behavior when applying customization configuration with custom script:
-
-``[deploypkg] enable-custom-scripts``:
-
-If this option is absent in VMware Tools configuration, the custom script is
-disabled by default for security reasons. Some VMware products could change
-this default behavior (for example: enabled by default) via customization
-specification settings.
-
-VMware admin can refer to `customization configuration <https://github.com/canonical/cloud-init/blob/main/cloudinit/sources/helpers/vmware/imc/config.py>`_ and set the customization specification settings.
-
-For more information, see `VMware vSphere Product Documentation <https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-EB5F090E-723C-4470-B640-50B35D1EC016.html#GUID-9A5093A5-C54F-4502-941B-3F9C0F573A39__GUID-40C60643-A2EB-4B05-8927-B51AF7A6CC5E>`_ and specific VMware Tools configuration options.
-
-GuestInfo Keys
-^^^^^^^^^^^^^^
-
-One method of providing meta, user, and vendor data is by setting the following
-key/value pairs on a VM's ``extraConfig`` `property <https://vdc-repo.vmware.com/vmwb-repository/dcr-public/723e7f8b-4f21-448b-a830-5f22fd931b01/5a8257bd-7f41-4423-9a73-03307535bd42/doc/vim.vm.ConfigInfo.html>`_:
-
-.. list-table::
- :header-rows: 1
-
- * - Property
- - Description
- * - ``guestinfo.metadata``
- - A YAML or JSON document containing the cloud-init metadata.
- * - ``guestinfo.metadata.encoding``
- - The encoding type for ``guestinfo.metadata``.
- * - ``guestinfo.userdata``
- - A YAML document containing the cloud-init user data.
- * - ``guestinfo.userdata.encoding``
- - The encoding type for ``guestinfo.userdata``.
- * - ``guestinfo.vendordata``
- - A YAML document containing the cloud-init vendor data.
- * - ``guestinfo.vendordata.encoding``
- - The encoding type for ``guestinfo.vendordata``.
-
-
-All ``guestinfo.*.encoding`` values may be set to ``base64`` or
-``gzip+base64``.
-
-Features
---------
-
-This section reviews several features available in this datasource.
-
-Instance data and lazy networks
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-One of the hallmarks of cloud-init is `its use of instance-data and JINJA
-queries <../instancedata.html#using-instance-data>`_
--- the ability to write queries in user and vendor data that reference runtime
-information present in ``/run/cloud-init/instance-data.json``. This works well
-when the metadata provides all of the information up front, such as the network
-configuration. For systems that rely on DHCP, however, this information may not
-be available when the metadata is persisted to disk.
-
-This datasource ensures that even if the instance is using DHCP to configure
-networking, the same details about the configured network are available in
-``/run/cloud-init/instance-data.json`` as if static networking was used. This
-information collected at runtime is easy to demonstrate by executing the
-datasource on the command line. From the root of this repository, run the
-following command:
-
-.. code-block:: bash
-
- PYTHONPATH="$(pwd)" python3 cloudinit/sources/DataSourceVMware.py
-
-The above command will result in output similar to the below JSON:
-
-.. code-block:: json
-
- {
- "hostname": "akutz.localhost",
- "local-hostname": "akutz.localhost",
- "local-ipv4": "192.168.0.188",
- "local_hostname": "akutz.localhost",
- "network": {
- "config": {
- "dhcp": true
- },
- "interfaces": {
- "by-ipv4": {
- "172.0.0.2": {
- "netmask": "255.255.255.255",
- "peer": "172.0.0.2"
- },
- "192.168.0.188": {
- "broadcast": "192.168.0.255",
- "mac": "64:4b:f0:18:9a:21",
- "netmask": "255.255.255.0"
- }
- },
- "by-ipv6": {
- "fd8e:d25e:c5b6:1:1f5:b2fd:8973:22f2": {
- "flags": 208,
- "mac": "64:4b:f0:18:9a:21",
- "netmask": "ffff:ffff:ffff:ffff::/64"
- }
- },
- "by-mac": {
- "64:4b:f0:18:9a:21": {
- "ipv4": [
- {
- "addr": "192.168.0.188",
- "broadcast": "192.168.0.255",
- "netmask": "255.255.255.0"
- }
- ],
- "ipv6": [
- {
- "addr": "fd8e:d25e:c5b6:1:1f5:b2fd:8973:22f2",
- "flags": 208,
- "netmask": "ffff:ffff:ffff:ffff::/64"
- }
- ]
- },
- "ac:de:48:00:11:22": {
- "ipv6": []
- }
- }
- }
- },
- "wait-on-network": {
- "ipv4": true,
- "ipv6": "false"
- }
- }
-
-
-Redacting sensitive information (GuestInfo keys transport only)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Sometimes the cloud-init userdata might contain sensitive information, and it
-may be desirable to have the ``guestinfo.userdata`` key (or other guestinfo
-keys) redacted as soon as its data is read by the datasource. This is possible
-by adding the following to the metadata:
-
-.. code-block:: yaml
-
- redact: # formerly named cleanup-guestinfo, which will also work
- - userdata
- - vendordata
-
-When the above snippet is added to the metadata, the datasource will iterate
-over the elements in the ``redact`` array and clear each of the keys. For
-example, when the guestinfo transport is used, the above snippet will cause
-the following commands to be executed:
-
-.. code-block:: shell
-
- vmware-rpctool "info-set guestinfo.userdata ---"
- vmware-rpctool "info-set guestinfo.userdata.encoding "
- vmware-rpctool "info-set guestinfo.vendordata ---"
- vmware-rpctool "info-set guestinfo.vendordata.encoding "
-
-Please note that keys are set to the valid YAML string ``---`` as it is not
-possible remove an existing key from the guestinfo key-space. A key's analogous
-encoding property will be set to a single white-space character, causing the
-datasource to treat the actual key value as plain-text, thereby loading it as
-an empty YAML doc (hence the aforementioned ``---``\ ).
-
-Reading the local IP addresses
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-This datasource automatically discovers the local IPv4 and IPv6 addresses for
-a guest operating system based on the default routes. However, when inspecting
-a VM externally, it's not possible to know what the *default* IP address is for
-the guest OS. That's why this datasource sets the discovered, local IPv4 and
-IPv6 addresses back in the guestinfo namespace as the following keys:
-
-
-* ``guestinfo.local-ipv4``
-* ``guestinfo.local-ipv6``
-
-It is possible that a host may not have any default, local IP addresses. It's
-also possible the reported, local addresses are link-local addresses. But these
-two keys may be used to discover what this datasource determined were the local
-IPv4 and IPv6 addresses for a host.
-
-Waiting on the network
-^^^^^^^^^^^^^^^^^^^^^^
-
-Sometimes cloud-init may bring up the network, but it will not finish coming
-online before the datasource's ``setup`` function is called, resulting in an
-``/var/run/cloud-init/instance-data.json`` file that does not have the correct
-network information. It is possible to instruct the datasource to wait until an
-IPv4 or IPv6 address is available before writing the instance data with the
-following metadata properties:
-
-.. code-block:: yaml
-
- wait-on-network:
- ipv4: true
- ipv6: true
-
-If either of the above values are true, then the datasource will sleep for a
-second, check the network status, and repeat until one or both addresses from
-the specified families are available.
-
-Walkthrough of GuestInfo Transport
----------------------------------------
-
-The following series of steps is a demonstration on how to configure a VM with
-this datasource using GuestInfo keys transport:
-
-
-#. Create the metadata file for the VM. Save the following YAML to a file named
- ``metadata.yaml``\ :
-
- .. code-block:: yaml
-
- instance-id: cloud-vm
- local-hostname: cloud-vm
- network:
- version: 2
- ethernets:
- nics:
- match:
- name: ens*
- dhcp4: yes
-
-#. Create the userdata file ``userdata.yaml``\ :
-
- .. code-block:: yaml
-
- #cloud-config
-
- users:
- - default
- - name: akutz
- primary_group: akutz
- sudo: ALL=(ALL) NOPASSWD:ALL
- groups: sudo, wheel
- lock_passwd: true
- ssh_authorized_keys:
- - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDE0c5FczvcGSh/tG4iw+Fhfi/O5/EvUM/96js65tly4++YTXK1d9jcznPS5ruDlbIZ30oveCBd3kT8LLVFwzh6hepYTf0YmCTpF4eDunyqmpCXDvVscQYRXyasEm5olGmVe05RrCJSeSShAeptv4ueIn40kZKOghinGWLDSZG4+FFfgrmcMCpx5YSCtX2gvnEYZJr0czt4rxOZuuP7PkJKgC/mt2PcPjooeX00vAj81jjU2f3XKrjjz2u2+KIt9eba+vOQ6HiC8c2IzRkUAJ5i1atLy8RIbejo23+0P4N2jjk17QySFOVHwPBDTYb0/0M/4ideeU74EN/CgVsvO6JrLsPBR4dojkV5qNbMNxIVv5cUwIy2ThlLgqpNCeFIDLCWNZEFKlEuNeSQ2mPtIO7ETxEL2Cz5y/7AIuildzYMc6wi2bofRC8HmQ7rMXRWdwLKWsR0L7SKjHblIwarxOGqLnUI+k2E71YoP7SZSlxaKi17pqkr0OMCF+kKqvcvHAQuwGqyumTEWOlH6TCx1dSPrW+pVCZSHSJtSTfDW2uzL6y8k10MT06+pVunSrWo5LHAXcS91htHV1M1UrH/tZKSpjYtjMb5+RonfhaFRNzvj7cCE1f3Kp8UVqAdcGBTtReoE8eRUT63qIxjw03a7VwAyB2w+9cu1R9/vAo8SBeRqw== sakutz@gmail.com
-
-#. Please note this step requires that the VM be powered off. All of the
- commands below use the VMware CLI tool, `govc <https://github.com/vmware/govmomi/blob/master/govc>`_.
-
- Go ahead and assign the path to the VM to the environment variable ``VM``\ :
-
- .. code-block:: shell
-
- export VM="/inventory/path/to/the/vm"
-
-#. Power off the VM:
-
- .. raw:: html
-
- <hr />
-
- &#x26a0;&#xfe0f; <strong>First Boot Mode</strong>
-
- To ensure the next power-on operation results in a first-boot scenario for
- cloud-init, it may be necessary to run the following command just before
- powering off the VM:
-
- .. code-block:: bash
-
- cloud-init clean --logs --machine-id
-
- Otherwise cloud-init may not run in first-boot mode. For more information
- on how the boot mode is determined, please see the
- `First Boot Documentation <../boot.html#first-boot-determination>`_.
-
- .. raw:: html
-
- <hr />
-
- .. code-block:: shell
-
- govc vm.power -off "${VM}"
-
-#.
- Export the environment variables that contain the cloud-init metadata and
- userdata:
-
- .. code-block:: shell
-
- export METADATA=$(gzip -c9 <metadata.yaml | { base64 -w0 2>/dev/null || base64; }) \
- USERDATA=$(gzip -c9 <userdata.yaml | { base64 -w0 2>/dev/null || base64; })
-
-#.
- Assign the metadata and userdata to the VM:
-
- .. code-block:: shell
-
- govc vm.change -vm "${VM}" \
- -e guestinfo.metadata="${METADATA}" \
- -e guestinfo.metadata.encoding="gzip+base64" \
- -e guestinfo.userdata="${USERDATA}" \
- -e guestinfo.userdata.encoding="gzip+base64"
-
- Please note the above commands include specifying the encoding for the
- properties. This is important as it informs the datasource how to decode
- the data for cloud-init. Valid values for ``metadata.encoding`` and
- ``userdata.encoding`` include:
-
-
- * ``base64``
- * ``gzip+base64``
-
-#.
- Power on the VM:
-
- .. code-block:: shell
-
- govc vm.power -on "${VM}"
-
-If all went according to plan, the CentOS box is:
-
-* Locked down, allowing SSH access only for the user in the userdata
-* Configured for a dynamic IP address via DHCP
-* Has a hostname of ``cloud-vm``
-
-Examples
---------
-
-This section reviews common configurations:
-
-Setting the hostname
-^^^^^^^^^^^^^^^^^^^^
-
-The hostname is set by way of the metadata key ``local-hostname``.
-
-Setting the instance ID
-^^^^^^^^^^^^^^^^^^^^^^^
-
-The instance ID may be set by way of the metadata key ``instance-id``. However,
-if this value is absent then the instance ID is read from the file
-``/sys/class/dmi/id/product_uuid``.
-
-Providing public SSH keys
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The public SSH keys may be set by way of the metadata key ``public-keys-data``.
-Each newline-terminated string will be interpreted as a separate SSH public
-key, which will be placed in distro's default user's
-``~/.ssh/authorized_keys``. If the value is empty or absent, then nothing will
-be written to ``~/.ssh/authorized_keys``.
-
-Configuring the network
-^^^^^^^^^^^^^^^^^^^^^^^
-
-The network is configured by setting the metadata key ``network`` with a value
-consistent with Network Config Versions
-`1 <../network-config-format-v1.html>`_ or
-`2 <../network-config-format-v2.html>`_\ , depending on the Linux
-distro's version of cloud-init.
-
-The metadata key ``network.encoding`` may be used to indicate the format of
-the metadata key "network". Valid encodings are ``base64`` and ``gzip+base64``.
diff --git a/doc/rtd/topics/datasources/vultr.rst b/doc/rtd/topics/datasources/vultr.rst
deleted file mode 100644
index f8601700..00000000
--- a/doc/rtd/topics/datasources/vultr.rst
+++ /dev/null
@@ -1,35 +0,0 @@
-.. _datasource_vultr:
-
-Vultr
-=====
-
-The `Vultr`_ datasource retrieves basic configuration values from the locally
-accessible `metadata service`_. All data is served over HTTP from the address
-169.254.169.254. The endpoints are documented in
-`https://www.vultr.com/metadata/
-<https://www.vultr.com/metadata/>`_
-
-Configuration
--------------
-
-Vultr's datasource can be configured as follows:
-
- datasource:
- Vultr:
- url: 'http://169.254.169.254'
- retries: 3
- timeout: 2
- wait: 2
-
-- *url*: The URL used to acquire the metadata configuration from
-- *retries*: Determines the number of times to attempt to connect to the
- metadata service
-- *timeout*: Determines the timeout in seconds to wait for a response from the
- metadata service
-- *wait*: Determines the timeout in seconds to wait before retrying after
- accessible failure
-
-.. _Vultr: https://www.vultr.com/
-.. _metadata service: https://www.vultr.com/metadata/
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/datasources/zstack.rst b/doc/rtd/topics/datasources/zstack.rst
deleted file mode 100644
index 6630ad9f..00000000
--- a/doc/rtd/topics/datasources/zstack.rst
+++ /dev/null
@@ -1,37 +0,0 @@
-.. _datasource_zstack:
-
-ZStack
-======
-ZStack platform provides a AWS Ec2 metadata service, but with different
-datasource identity.
-More information about ZStack can be found at `ZStack <https://www.zstack.io>`__.
-
-Discovery
----------
-To determine whether a vm running on ZStack platform, cloud-init checks DMI
-information by 'dmidecode -s chassis-asset-tag', if the output ends with
-'.zstack.io', it's running on ZStack platform:
-
-
-Metadata
-^^^^^^^^
-Same as EC2, instance metadata can be queried at
-
-::
-
- GET http://169.254.169.254/2009-04-04/meta-data/
- instance-id
- local-hostname
-
-Userdata
-^^^^^^^^
-Same as EC2, instance userdata can be queried at
-
-::
-
- GET http://169.254.169.254/2009-04-04/user-data/
- meta_data.json
- user_data
- password
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/docs.rst b/doc/rtd/topics/docs.rst
deleted file mode 100644
index 99c2c140..00000000
--- a/doc/rtd/topics/docs.rst
+++ /dev/null
@@ -1,76 +0,0 @@
-.. _docs:
-
-Docs
-****
-
-These docs are hosted on Read the Docs. The following will explain how to
-contribute to and build these docs locally.
-
-The documentation is primarily written in reStructuredText.
-
-
-Building
-========
-
-There is a makefile target to build the documentation for you:
-
-.. code-block:: shell-session
-
- $ tox -e doc
-
-This will do two things:
-
-- Build the documentation using sphinx
-- Run doc8 against the documentation source code
-
-Once build the HTML files will be viewable in ``doc/rtd_html``. Use your
-web browser to open ``index.html`` to view and navigate the site.
-
-Style Guide
-===========
-
-Headings
---------
-The headings used across the documentation use the following hierarchy:
-
-- ``*****``: used once atop of a new page
-- ``=====``: each sections on the page
-- ``-----``: subsections
-- ``^^^^^``: sub-subsections
-- ``"""""``: paragraphs
-
-The top level header ``######`` is reserved for the first page.
-
-If under and overline are used, their length must be identical. The length of
-the underline must be at least as long as the title itself
-
-Line Length
------------
-Please keep the line lengths to a maximum of **79** characters. This ensures
-that the pages and tables do not get too wide that side scrolling is required.
-
-Header
-------
-Adding a link at the top of the page allows for the page to be referenced by
-other pages. For example for the FAQ page this would be:
-
-.. code-block:: rst
-
- .. _faq:
-
-Vertical Whitespace
--------------------
-One newline between each section helps ensure readability of the documentation
-source code.
-
-Common Words
-------------
-There are some common words that should follow specific usage:
-
-- ``cloud-init``: always lower case with a hyphen, unless starting a sentence
- in which case only the 'C' is capitalized (e.g. ``Cloud-init``).
-- ``metadata``: one word
-- ``user data``: two words, not to be combined
-- ``vendor data``: like user data, it is two words
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/events.rst b/doc/rtd/topics/events.rst
deleted file mode 100644
index 1a562fb4..00000000
--- a/doc/rtd/topics/events.rst
+++ /dev/null
@@ -1,95 +0,0 @@
-.. _events:
-
-******************
-Events and Updates
-******************
-
-Events
-======
-
-`Cloud-init`_ will fetch and apply cloud and user data configuration
-upon several event types. The two most common events for cloud-init
-are when an instance first boots and any subsequent boot thereafter (reboot).
-In addition to boot events, cloud-init users and vendors are interested
-in when devices are added. cloud-init currently supports the following
-event types:
-
-- **BOOT_NEW_INSTANCE**: New instance first boot
-- **BOOT**: Any system boot other than 'BOOT_NEW_INSTANCE'
-- **BOOT_LEGACY**: Similar to 'BOOT', but applies networking config twice each
- boot: once during Local stage, then again in Network stage. As this behavior
- was previously the default behavior, this option exists to prevent regressing
- such behavior.
-- **HOTPLUG**: Dynamic add of a system device
-
-Future work will likely include infrastructure and support for the following
-events:
-
-- **METADATA_CHANGE**: An instance's metadata has change
-- **USER_REQUEST**: Directed request to update
-
-Datasource Event Support
-========================
-
-All :ref:`datasources` by default support the ``BOOT_NEW_INSTANCE`` event.
-Each Datasource will declare a set of these events that it is capable of
-handling. Datasources may not support all event types. In some cases a system
-may be configured to allow a particular event but may be running on
-a platform whose datasource cannot support the event.
-
-Configuring Event Updates
-=========================
-
-Update configuration may be specified via user data,
-which can be used to enable or disable handling of specific events.
-This configuration will be honored as long as the events are supported by
-the datasource. However, configuration will always be applied at first
-boot, regardless of the user data specified.
-
-Updates
-~~~~~~~
-Update policy configuration defines which
-events are allowed to be handled. This is separate from whether a
-particular platform or datasource has the capability for such events.
-
-**scope**: *<name of the scope for event policy>*
-
-The ``scope`` value is a string which defines under which domain does the
-event occur. Currently the only one known scope is ``network``, though more
-scopes may be added in the future. Scopes are defined by convention but
-arbitrary values can be used.
-
-**when**: *<list of events to handle for a particular scope>*
-
-Each ``scope`` requires a ``when`` element to specify which events
-are to allowed to be handled.
-
-Hotplug
-=======
-When the hotplug event is supported by the data source and configured in
-user data, cloud-init will respond to the addition or removal of network
-interfaces to the system. In addition to fetching and updating the system
-metadata, cloud-init will also bring up/down the newly added interface.
-
-.. warning:: Due to its use of systemd sockets, hotplug functionality
- is currently incompatible with SELinux. This issue is being tracked
- `on Launchpad`_. Additionally, hotplug support is considered experimental for
- non-Debian based systems.
-
-Examples
-========
-
-apply network config every boot
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-On every boot, apply network configuration found in the datasource.
-
-.. code-block:: shell-session
-
- # apply network config on every boot
- updates:
- network:
- when: ['boot']
-
-.. _Cloud-init: https://launchpad.net/cloud-init
-.. _on Launchpad: https://bugs.launchpad.net/cloud-init/+bug/1936229
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/faq.rst b/doc/rtd/topics/faq.rst
deleted file mode 100644
index f48801b6..00000000
--- a/doc/rtd/topics/faq.rst
+++ /dev/null
@@ -1,450 +0,0 @@
-.. _faq:
-
-FAQ
-***
-
-How do I get help?
-==================
-
-Having trouble? We would like to help!
-
-- First go through this page with answers to common questions
-- Use the search bar at the upper left to search these docs
-- Ask a question in the ``#cloud-init`` IRC channel on Libera
-- Join and ask questions on the `cloud-init mailing list <https://launchpad.net/~cloud-init>`_
-- Find a bug? Check out the :ref:`reporting_bugs` topic for
- how to report one
-
-Where are the logs?
-===================
-
-Cloud-init uses two files to log to:
-
-- `/var/log/cloud-init-output.log`: captures the output from each stage of
- cloud-init when it runs
-- `/var/log/cloud-init.log`: very detailed log with debugging output,
- detailing each action taken
-- `/run/cloud-init`: contains logs about how cloud-init decided to enable or
- disable itself, as well as what platforms/datasources were detected. These
- logs are most useful when trying to determine what cloud-init ran or did not
- run.
-
-Be aware that each time a system boots, new logs are appended to the files in
-`/var/log`. Therefore, the files may have more than one boot worth of
-information present.
-
-When reviewing these logs look for any errors or Python tracebacks to check
-for any errors.
-
-Where are the configuration files?
-==================================
-
-Cloud-init config is provided in two places:
-
-- `/etc/cloud/cloud.cfg`
-- `/etc/cloud/cloud.cfg.d/*.cfg`
-
-These files can define the modules that run during instance initialization,
-the datasources to evaluate on boot, and other settings.
-
-See the :ref:`configuration sources explanation<configuration>` and
-:ref:`configuration reference<base_config_reference>` for more information.
-
-Where are the data files?
-=========================
-
-Inside the `/var/lib/cloud/` directory there are two important subdirectories:
-
-instance
---------
-
-The `/var/lib/cloud/instance` directory is a symbolic link that points
-to the most recently used instance-id directory. This folder contains the
-information cloud-init received from datasources, including vendor and user
-data. This can be helpful to review to ensure the correct data was passed.
-
-It also contains the `datasource` file that contains the full information
-about what datasource was identified and used to setup the system.
-
-Finally, the `boot-finished` file is the last thing that cloud-init does.
-
-data
-----
-
-The `/var/lib/cloud/data` directory contain information related to the
-previous boot:
-
-* `instance-id`: id of the instance as discovered by cloud-init. Changing
- this file has no effect.
-* `result.json`: json file will show both the datasource used to setup
- the instance, and if any errors occurred
-* `status.json`: json file shows the datasource used and a break down
- of all four modules if any errors occurred and the start and stop times.
-
-What datasource am I using?
-===========================
-
-To correctly setup an instance, cloud-init must correctly identify the
-cloud that it is on. Therefore knowing what datasource is used on an
-instance launch can help aid in debugging.
-
-To find what datasource is getting used run the `cloud-id` command:
-
-.. code-block:: shell-session
-
- $ cloud-id
-
-Which will tell you which datasource is being used, for example:
-
-.. code-block::
-
- nocloud
-
-If the cloud-id is not what is expected, then running the `ds-identify`
-script in debug mode and providing that in a bug can help aid in resolving
-any issues:
-
-.. code-block:: shell-session
-
- $ sudo DEBUG_LEVEL=2 DI_LOG=stderr /usr/lib/cloud-init/ds-identify --force
-
-The force parameter allows the command to be run again since the instance has
-already launched. The other options increase the verbosity of logging and
-put the logs to STDERR.
-
-How can I re-run datasource detection and cloud-init?
-=====================================================
-
-If a user is developing a new datasource or working on debugging an issue it
-may be useful to re-run datasource detection and the initial setup of
-cloud-init.
-
-To do this, force ds-identify to re-run, clean up any logs, and re-run
-cloud-init:
-
-.. code-block:: shell-session
-
- $ sudo DI_LOG=stderr /usr/lib/cloud-init/ds-identify --force
- $ sudo cloud-init clean --logs
- $ sudo cloud-init init --local
- $ sudo cloud-init init
-
-.. warning::
-
- These commands will re-run cloud-init as if this were first boot of a
- system: this will, at the very least, cycle SSH host keys and may do
- substantially more. Do not run these commands on production systems.
-
-How can I debug my user data?
-=============================
-
-Two of the most common issues with user data, that also happens to be
-cloud-config is:
-
-1. Incorrectly formatted YAML
-2. First line does not contain `#cloud-config`
-
-To verify your YAML, we do have a short script called `validate-yaml.py`_
-that can validate your user data offline.
-
-.. _validate-yaml.py: https://github.com/canonical/cloud-init/blob/main/tools/validate-yaml.py
-
-Another option is to run the following on an instance to debug userdata
-provided to the system:
-
-.. code-block:: shell-session
-
- $ cloud-init schema --system --annotate
-
-Why did cloud-init never complete?
-==================================
-
-To check if cloud-init is running still, run:
-
-.. code-block:: shell-session
-
- $ cloud-init status
-
-To wait for cloud-init to complete, run:
-
-.. code-block:: shell-session
-
- $ cloud-init status --wait
-
-There are a number of reasons that cloud-init might never complete. This list
-is not exhaustive, but attempts to enumerate potential causes:
-
-External reasons:
------------------
-- failed dependent services in the boot
-- bugs in the kernel or drivers
-- bugs in external userspace tools that are called by cloud-init
-
-Internal reasons:
------------------
-- a command in ``bootcmd`` or ``runcmd`` that never completes (ex: running
- `cloud-init status --wait` will wait forever on itself and never complete)
-- nonstandard configurations that disable timeouts or set extremely high
- values ("never" is used in a loose sense here)
-
-Failing to Complete on Systemd:
--------------------------------
-
-Cloud-init consists of multiple services on systemd. If a service
-that cloud-init depends on stalls, cloud-init will not continue.
-If reporting a bug related to cloud-init failing to complete on
-systemd, please make sure to include the following logs.
-
-.. code-block:: shell-session
-
- $ systemd-analyze critical-chain cloud-init.target
- $ journalctl --boot=-1
- $ systemctl --failed
-
-
-Autoinstall, Preruncmd, Postruncmd
-==================================
-Since cloud-init ignores top level userdata cloud-config keys, other projects
-such as `Juju <https://ubuntu.com/blog/topics/juju>`_ and subiquity_
-autoinstaller use a YAML-formatted config that combines cloud-init's userdata
-cloud-config YAML format with their custom YAML keys. Since cloud-init ignores
-unused top level keys, these combined YAML configurations may be valid
-cloud-config files, however keys such as ``autoinstall``, ``preruncmd``, and
-``postruncmd`` are not used by cloud-init to configure anything.
-
-Please direct bugs and questions about other projects that use cloud-init to
-their respective support channels. For Subiquity autoinstaller that is via IRC
-#ubuntu-server on Libera or Discourse. For Juju support see their
-`discourse page <https://discourse.charmhub.io>`_.
-
-
-How can I make a module run on every boot?
-==========================================
-Modules have a default frequency that can be overridden. This is done
-by modifying the module list in ``/etc/cloud/cloud.cfg``.
-
-1. Change the module from a string (default) to a list.
-2. Set the first list item to the module name and the second item to the
- frequency.
-
-Example
--------
-The following example demonstrates how to log boot times to a file every boot.
-
-Update ``/etc/cloud/cloud.cfg``:
-
-.. code-block:: yaml
- :name: /etc/cloud/cloud.cfg
- :emphasize-lines: 3
-
- cloud_final_modules:
- # list shortened for brevity
- - [phone-home, always]
- - final-message
- - power-state-change
-
-
-
-Then your userdata could then be:
-
-.. code-block:: yaml
-
- #cloud-config
- phone_home:
- url: http://example.com/$INSTANCE_ID/
- post: all
-
-
-
-How can I test cloud-init locally before deploying to the cloud?
-================================================================
-
-Several different virtual machine and containerization tools can be used for
-testing locally. Multipass, LXD, and qemu are described in this section.
-
-
-Multipass
----------
-
-`Multipass`_ is a cross-platform tool to launch Ubuntu VMs across Linux,
-Windows, and macOS.
-
-When a user launches a Multipass VM, user data can be passed by adding the
-`--cloud-init` flag and the appropriate YAML file containing user data:
-
-.. code-block:: shell-session
-
- $ multipass launch bionic --name test-vm --cloud-init userdata.yaml
-
-Multipass will validate the YAML syntax of the cloud-config file before
-attempting to start the VM! A nice addition to help save time when
-experimenting with launching instances with various cloud-configs.
-
-Multipass only supports passing user-data and only as YAML cloud-config
-files. Passing a script, a MIME archive, or any of the other user-data
-formats cloud-init supports will result in an error from the YAML syntax
-validator.
-
-.. _Multipass: https://multipass.run/
-
-LXD
----
-
-`LXD`_ offers a streamlined user experience for using linux system
-containers. With LXD, a user can pass:
-
-* user data
-* vendor data
-* metadata
-* network configuration
-
-The following initializes a container with user data:
-
-.. code-block:: shell-session
-
- $ lxc init ubuntu-daily:bionic test-container
- $ lxc config set test-container user.user-data - < userdata.yaml
- $ lxc start test-container
-
-To avoid the extra commands this can also be done at launch:
-
-.. code-block:: shell-session
-
- $ lxc launch ubuntu-daily:bionic test-container --config=user.user-data="$(cat userdata.yaml)"
-
-Finally, a profile can be setup with the specific data if a user needs to
-launch this multiple times:
-
-.. code-block:: shell-session
-
- $ lxc profile create dev-user-data
- $ lxc profile set dev-user-data user.user-data - < cloud-init-config.yaml
- $ lxc launch ubuntu-daily:bionic test-container -p default -p dev-user-data
-
-The above examples all show how to pass user data. To pass other types of
-configuration data use the config option specified below:
-
-+----------------+---------------------------+
-| Data | Config Option |
-+================+===========================+
-| user data | cloud-init.user-data |
-+----------------+---------------------------+
-| vendor data | cloud-init.vendor-data |
-+----------------+---------------------------+
-| network config | cloud-init.network-config |
-+----------------+---------------------------+
-
-See the LXD `Instance Configuration`_ docs for more info about configuration
-values or the LXD `Custom Network Configuration`_ document for more about
-custom network config.
-
-.. _LXD: https://linuxcontainers.org/
-.. _Instance Configuration: https://linuxcontainers.org/lxd/docs/master/instances
-.. _Custom Network Configuration: https://linuxcontainers.org/lxd/docs/master/cloud-init
-
-QEMU
-----
-
-The `cloud-localds` command from the `cloud-utils`_ package generates a disk
-with user supplied data. The NoCloud datasouce allows users to provide their
-own user data, metadata, or network configuration directly to an instance
-without running a network service. This is helpful for launching local cloud
-images with QEMU for example.
-
-The following is an example of creating the local disk using the cloud-localds
-command:
-
-.. code-block:: shell-session
-
- $ cat >user-data <<EOF
- #cloud-config
- password: password
- chpasswd:
- expire: False
- ssh_pwauth: True
- ssh_authorized_keys:
- - ssh-rsa AAAA...UlIsqdaO+w==
- EOF
- $ cloud-localds seed.img user-data
-
-The resulting seed.img can then get passed along to a cloud image containing
-cloud-init. Below is an example of passing the seed.img with QEMU:
-
-.. code-block:: shell-session
-
- $ qemu-system-x86_64 -m 1024 -net nic -net user \
- -hda ubuntu-20.04-server-cloudimg-amd64.img \
- -hdb seed.img
-
-The now booted image will allow for login using the password provided above.
-
-For additional configuration, users can provide much more detailed
-configuration, including network configuration and metadata:
-
-.. code-block:: shell-session
-
- $ cloud-localds --network-config=network-config-v2.yaml \
- seed.img userdata.yaml metadata.yaml
-
-See the :ref:`network_config_v2` page for details on the format and config of
-network configuration. To learn more about the possible values for metadata,
-check out the :ref:`datasource_nocloud` page.
-
-.. _cloud-utils: https://github.com/canonical/cloud-utils/
-
-Where can I learn more?
-=======================
-
-Below are some videos, blog posts, and white papers about cloud-init from a
-variety of sources.
-
-Videos:
-
-- `cloud-init - The Good Parts`_
-- `Perfect Proxmox Template with Cloud Image and Cloud Init [proxmox, cloud-init, template]`_
-- `cloud-init - Building clouds one Linux box at a time (Video)`_
-- `Metadata and cloud-init`_
-- `Introduction to cloud-init`_
-
-Blog Posts:
-
-- `cloud-init - The cross-cloud Magic Sauce (PDF)`_
-- `cloud-init - Building clouds one Linux box at a time (PDF)`_
-- `The beauty of cloud-init`_
-- `Cloud-init Getting Started [fedora, libvirt, cloud-init]`_
-- `Build Azure Devops Agents With Linux cloud-init for Dotnet Development [terraform, azure, devops, docker, dotnet, cloud-init]`_
-- `Cloud-init Getting Started [fedora, libvirt, cloud-init]`_
-- `Setup Neovim cloud-init Completion [neovim, yaml, Language Server Protocol, jsonschema, cloud-init]`_
-
-Events:
-
-- `cloud-init Summit 2019`_
-- `cloud-init Summit 2018`_
-- `cloud-init Summit 2017`_
-
-
-Whitepapers:
-
-- `Utilising cloud-init on Microsoft Azure (Whitepaper)`_
-- `Cloud Instance Initialization with cloud-init (Whitepaper)`_
-
-.. _cloud-init - The Good Parts: https://www.youtube.com/watch?v=2_m6EUo6VOI
-.. _Utilising cloud-init on Microsoft Azure (Whitepaper): https://ubuntu.com/engage/azure-cloud-init-whitepaper
-.. _Cloud Instance Initialization with cloud-init (Whitepaper): https://ubuntu.com/blog/cloud-instance-initialisation-with-cloud-init
-
-.. _cloud-init - The cross-cloud Magic Sauce (PDF): https://events.linuxfoundation.org/wp-content/uploads/2017/12/cloud-init-The-cross-cloud-Magic-Sauce-Scott-Moser-Chad-Smith-Canonical.pdf
-.. _cloud-init - Building clouds one Linux box at a time (Video): https://www.youtube.com/watch?v=1joQfUZQcPg
-.. _cloud-init - Building clouds one Linux box at a time (PDF): https://web.archive.org/web/20181111020605/https://annex.debconf.org/debconf-share/debconf17/slides/164-cloud-init_Building_clouds_one_Linux_box_at_a_time.pdf
-.. _Metadata and cloud-init: https://www.youtube.com/watch?v=RHVhIWifVqU
-.. _The beauty of cloud-init: https://web.archive.org/web/20180830161317/http://brandon.fuller.name/archives/2011/05/02/06.40.57/
-.. _Introduction to cloud-init: http://www.youtube.com/watch?v=-zL3BdbKyGY
-.. _Build Azure Devops Agents With Linux cloud-init for Dotnet Development [terraform, azure, devops, docker, dotnet, cloud-init]: https://codingsoul.org/2022/04/25/build-azure-devops-agents-with-linux-cloud-init-for-dotnet-development/
-.. _Perfect Proxmox Template with Cloud Image and Cloud Init [proxmox, cloud-init, template]: https://www.youtube.com/watch?v=shiIi38cJe4
-.. _Cloud-init Getting Started [fedora, libvirt, cloud-init]: https://blog.while-true-do.io/cloud-init-getting-started/
-.. _Setup Neovim cloud-init Completion [neovim, yaml, Language Server Protocol, jsonschema, cloud-init]: https://phoenix-labs.xyz/blog/setup-neovim-cloud-init-completion/
-
-.. _cloud-init Summit 2019: https://powersj.io/post/cloud-init-summit19/
-.. _cloud-init Summit 2018: https://powersj.io/post/cloud-init-summit18/
-.. _cloud-init Summit 2017: https://powersj.io/post/cloud-init-summit17/
-.. _subiquity: https://ubuntu.com/server/docs/install/autoinstall
-.. _juju_project: https://discourse.charmhub.io/t/model-config-cloudinit-userdata/512
diff --git a/doc/rtd/topics/integration_tests.rst b/doc/rtd/topics/integration_tests.rst
deleted file mode 100644
index 2bee6a5c..00000000
--- a/doc/rtd/topics/integration_tests.rst
+++ /dev/null
@@ -1,208 +0,0 @@
-.. _integration_tests:
-
-*******************
-Integration Testing
-*******************
-
-Overview
-=========
-
-Integration tests are written using pytest and are located at
-``tests/integration_tests``. General design principles
-laid out in :ref:`testing` should be followed for integration tests.
-
-Setup is accomplished via a set of fixtures located in
-``tests/integration_tests/conftest.py``.
-
-Test Definition
-===============
-Tests are defined like any other pytest test. The ``user_data``
-mark can be used to supply the cloud-config user data. Platform specific
-marks can be used to limit tests to particular platforms. The
-client fixture can be used to interact with the launched
-test instance.
-
-See `Examples`_ section for examples.
-
-Test Execution
-==============
-Test execution happens via pytest. A tox definition exists to run integration
-tests. To run all integration tests, you would run:
-
-.. code-block:: bash
-
- $ tox -e integration-tests
-
-Pytest arguments may also be passed. For example:
-
-.. code-block:: bash
-
- $ tox -e integration-tests tests/integration_tests/modules/test_combined.py
-
-Configuration
-=============
-
-All possible configuration values are defined in
-`tests/integration_tests/integration_settings.py <https://github.com/canonical/cloud-init/blob/main/tests/integration_tests/integration_settings.py>`_.
-Defaults can be
-overridden by supplying values in ``tests/integration_tests/user_settings.py``
-or by providing an environment variable of the same name prepended with
-``CLOUD_INIT_``. For example, to set the ``PLATFORM`` setting:
-
-.. code-block:: bash
-
- CLOUD_INIT_PLATFORM='ec2' pytest tests/integration_tests/
-
-
-Cloud Interaction
-=================
-Cloud interaction happens via the
-`pycloudlib <https://pycloudlib.readthedocs.io/en/latest/index.html>`_ library.
-In order to run integration tests, pycloudlib must first be
-`configured <https://pycloudlib.readthedocs.io/en/latest/configuration.html#configuration>`_.
-
-For a minimal setup using LXD, write the following to
-``~/.config/pycloudlib.toml``:
-
-.. code-block:: toml
-
- [lxd]
-
-
-Image Selection
-===============
-
-Each integration testing run uses a single image as its basis. This
-image is configured using the ``OS_IMAGE`` variable; see
-`Configuration`_ for details of how configuration works.
-
-``OS_IMAGE`` can take two types of value: an Ubuntu series name (e.g.
-"focal"), or an image specification. If an Ubuntu series name is
-given, then the most recent image for that series on the target cloud
-will be used. For other use cases, an image specification is used.
-
-In its simplest form, an image specification can simply be a cloud's
-image ID (e.g. "ami-deadbeef", "ubuntu:focal"). In this case, the
-image so-identified will be used as the basis for this testing run.
-
-This has a drawback, however: as we do not know what OS or release is
-within the image, the integration testing framework will run *all*
-tests against the image in question. If it's a RHEL8 image, then we
-would expect Ubuntu-specific tests to fail (and vice versa).
-
-To address this, a full image specification can be given. This is of
-the form: ``<image_id>[::<os>[::<release>]]`` where ``image_id`` is a
-cloud's image ID, ``os`` is the OS name, and ``release`` is the OS
-release name. So, for example, Ubuntu 18.04 (Bionic Beaver) on LXD is
-``ubuntu:bionic::ubuntu::bionic`` or RHEL 8 on Amazon is
-``ami-justanexample::rhel::8``. When a full specification is given,
-only tests which are intended for use on that OS and release will be
-executed.
-
-Image Setup
-===========
-
-Image setup occurs once when a test session begins and is implemented
-via fixture. Image setup roughly follows these steps:
-
-* Launch an instance on the specified test platform
-* Install the version of cloud-init under test
-* Run ``cloud-init clean`` on the instance so subsequent boots
- resemble out of the box behavior
-* Take a snapshot of the instance to be used as a new image from
- which new instances can be launched
-
-Test Setup
-==============
-Test setup occurs between image setup and test execution. Test setup
-is implemented via one of the ``client`` fixtures. When a client fixture
-is used, a test instance from which to run tests is launched prior to
-test execution and torn down after.
-
-Continuous Integration
-======================
-A subset of the integration tests are run when a pull request
-is submitted on Github. The tests run on these continuous
-integration (CI) runs are given a pytest mark:
-
-.. code-block:: python
-
- @pytest.mark.ci
-
-Most new tests should *not* use this mark, so be aware that having a
-successful CI run does not necessarily mean that your test passed
-successfully.
-
-Fixtures
-========
-Integration tests rely heavily on fixtures to do initial test setup.
-One or more of these fixtures will be used in almost every integration test.
-
-Details such as the cloud platform or initial image to use are determined
-via what is specified in the `Configuration`_.
-
-client
-------
-The ``client`` fixture should be used for most test cases. It ensures:
-
-- All setup performed by `session_cloud`_ and `setup_image`_
-- `Pytest marks <https://github.com/canonical/cloud-init/blob/af7eb1deab12c7208853c5d18b55228e0ba29c4d/tests/integration_tests/conftest.py#L220-L224>`_
- used during instance creation are obtained and applied
-- The test instance is launched
-- Test failure status is determined after test execution
-- Logs are collected (if configured) after test execution
-- The test instance is torn down after test execution
-
-``module_client`` and ``class_client`` fixtures also exist for the
-purpose of running multiple tests against a single launched instance.
-They provide the exact same functionality as ``client``, but are
-scoped to the module or class respectively.
-
-session_cloud
--------------
-The ``session_cloud`` session-scoped fixture will provide an
-`IntegrationCloud <https://github.com/canonical/cloud-init/blob/af7eb1deab12c7208853c5d18b55228e0ba29c4d/tests/integration_tests/clouds.py#L102>`_
-instance for the currently configured cloud. The fixture also
-ensures that any custom cloud session cleanup is performed.
-
-setup_image
------------
-The ``setup_image`` session-scope fixture will
-create a new image to launch all further cloud instances
-during this test run. It ensures:
-
-- A cloud instance is launched on the configured platform
-- The version of cloud-init under test is installed on the instance
-- ``cloud-init clean --logs`` is run on the instance
-- A snapshot of the instance is taken to be used as the basis for
- future instance launches
-- The originally launched instance is torn down
-- The custom created image is torn down after all tests finish
-
-Examples
---------
-A simple test case using the ``client`` fixture:
-
-.. code-block:: python
-
- USER_DATA = """\
- #cloud-config
- bootcmd:
- - echo 'hello!' > /var/tmp/hello.txt
- """
-
-
- @pytest.mark.user_data(USER_DATA)
- def test_bootcmd(client):
- log = client.read_from_file("/var/log/cloud-init.log")
- assert "Shellified 1 commands." in log
- assert client.execute('cat /var/tmp/hello.txt').strip() == "hello!"
-
-Customizing the launch arguments before launching an instance manually:
-
-.. code-block:: python
-
- def test_launch(session_cloud: IntegrationCloud, setup_image):
- with session_cloud.launch(launch_kwargs={"wait": False}) as client:
- client.instance.wait()
- assert client.execute("echo hello world").strip() == "hello world"
diff --git a/doc/rtd/topics/kernel-cmdline.rst b/doc/rtd/topics/kernel-cmdline.rst
deleted file mode 100644
index 4aa02855..00000000
--- a/doc/rtd/topics/kernel-cmdline.rst
+++ /dev/null
@@ -1,71 +0,0 @@
-.. _kernel_cmdline:
-
-*******************
-Kernel Command Line
-*******************
-
-In order to allow an ephemeral, or otherwise pristine image to
-receive some configuration, cloud-init will read a url directed by
-the kernel command line and proceed as if its data had previously existed.
-
-This allows for configuring a meta-data service, or some other data.
-
-.. note::
-
- That usage of the kernel command line is somewhat of a last resort,
- as it requires knowing in advance the correct command line or modifying
- the boot loader to append data.
-
-For example, when ``cloud-init init --local`` runs, it will check to
-see if ``cloud-config-url`` appears in key/value fashion
-in the kernel command line as in:
-
-.. code-block:: text
-
- root=/dev/sda ro cloud-config-url=http://foo.bar.zee/abcde
-
-Cloud-init will then read the contents of the given url.
-If the content starts with ``#cloud-config``, it will store
-that data to the local filesystem in a static filename
-``/etc/cloud/cloud.cfg.d/91_kernel_cmdline_url.cfg``, and consider it as
-part of the config from that point forward.
-
-If that file exists already, it will not be overwritten, and the
-`cloud-config-url` parameter is completely ignored.
-
-Then, when the DataSource runs, it will find that config already available.
-
-So, in order to be able to configure the MAAS DataSource by controlling the
-kernel command line from outside the image, you can append:
-
- * ``cloud-config-url=http://your.url.here/abcdefg``
-
-Then, have the following content at that url:
-
-.. code-block:: yaml
-
- #cloud-config
- datasource:
- MAAS:
- metadata_url: http://mass-host.localdomain/source
- consumer_key: Xh234sdkljf
- token_key: kjfhgb3n
- token_secret: 24uysdfx1w4
-
-.. warning::
-
- `url` kernel command line key is deprecated.
- Please use `cloud-config-url` parameter instead"
-
-.. note::
-
- Because ``cloud-config-url=`` is so very generic, in order to avoid false
- positives,
- cloud-init requires the content to start with ``#cloud-config`` in order
- for it to be considered.
-
-.. note::
-
- The ``cloud-config-url=`` is un-authed http GET, and contains credentials.
- It could be set up to be randomly generated and also check source
- address in order to be more secure.
diff --git a/doc/rtd/topics/logging.rst b/doc/rtd/topics/logging.rst
deleted file mode 100644
index 4d0a14ca..00000000
--- a/doc/rtd/topics/logging.rst
+++ /dev/null
@@ -1,267 +0,0 @@
-.. _logging:
-
-*******
-Logging
-*******
-Cloud-init supports both local and remote logging configurable through
-multiple configurations:
-
-- Python's built-in logging configuration
-- Cloud-init's event reporting system
-- The cloud-init rsyslog module
-
-Python Logging
-==============
-Cloud-init uses the python logging module, and can accept config for this
-module using the standard python fileConfig format. Cloud-init looks for
-config for the logging module under the ``logcfg`` key.
-
-.. note::
- the logging configuration is not YAML, it is python ``fileConfig`` format,
- and is passed through directly to the python logging module. please use the
- correct syntax for a multi-line string in YAML.
-
-By default, cloud-init uses the logging configuration provided in
-``/etc/cloud/cloud.cfg.d/05_logging.cfg``. The default python logging
-configuration writes all cloud-init events with a priority of ``WARNING`` or
-higher to console, and writes all events with a level of ``DEBUG`` or higher
-to ``/var/log/cloud-init.log`` and via syslog.
-
-Python's fileConfig format consists of sections with headings in the format
-``[title]`` and key value pairs in each section. Configuration for python
-logging must contain the sections ``[loggers]``, ``[handlers]``, and
-``[formatters]``, which name the entities of their respective types that will
-be defined. The section name for each defined logger, handler and formatter
-will start with its type, followed by an underscore (``_``) and the name of
-the entity. For example, if a logger was specified with the name ``log01``,
-config for the logger would be in the section ``[logger_log01]``.
-
-Logger config entries contain basic logging set up. They may specify a list of
-handlers to send logging events to as well as the lowest priority level of
-events to handle. A logger named ``root`` must be specified and its
-configuration (under ``[logger_root]``) must contain a level and a list of
-handlers. A level entry can be any of the following: ``DEBUG``, ``INFO``,
-``WARNING``, ``ERROR``, ``CRITICAL``, or ``NOTSET``. For the ``root`` logger
-the ``NOTSET`` option will allow all logging events to be recorded.
-
-Each configured handler must specify a class under the python's ``logging``
-package namespace. A handler may specify a message formatter to use, a
-priority level, and arguments for the handler class. Common handlers are
-``StreamHandler``, which handles stream redirects (i.e. logging to stderr),
-and ``FileHandler`` which outputs to a log file. The logging module also
-supports logging over net sockets, over http, via smtp, and additional complex
-configurations. For full details about the handlers available for python
-logging, please see the documentation for `python logging handlers`_.
-
-Log messages are formatted using the ``logging.Formatter`` class, which is
-configured using ``formatter`` config entities. A default format of
-``%(message)s`` is given if no formatter configs are specified. Formatter
-config entities accept a format string which supports variable replacements.
-These may also accept a ``datefmt`` string which may be used to configure the
-timestamp used in the log messages. The format variables ``%(asctime)s``,
-``%(levelname)s`` and ``%(message)s`` are commonly used and represent the
-timestamp, the priority level of the event and the event message. For
-additional information on logging formatters see `python logging formatters`_.
-
-.. note::
- by default the format string used in the logging formatter are in python's
- old style ``%s`` form. the ``str.format()`` and ``string.Template`` styles
- can also be used by using ``{`` or ``$`` in place of ``%`` by setting the
- ``style`` parameter in formatter config.
-
-A simple, but functional python logging configuration for cloud-init is below.
-It will log all messages of priority ``DEBUG`` or higher both stderr and
-``/tmp/my.log`` using a ``StreamHandler`` and a ``FileHandler``, using
-the default format string ``%(message)s``::
-
- logcfg: |
- [loggers]
- keys=root,cloudinit
- [handlers]
- keys=ch,cf
- [formatters]
- keys=
- [logger_root]
- level=DEBUG
- handlers=
- [logger_cloudinit]
- level=DEBUG
- qualname=cloudinit
- handlers=ch,cf
- [handler_ch]
- class=StreamHandler
- level=DEBUG
- args=(sys.stderr,)
- [handler_cf]
- class=FileHandler
- level=DEBUG
- args=('/tmp/my.log',)
-
-For additional information about configuring python's logging module, please
-see the documentation for `python logging config`_.
-
-.. _logging_command_output:
-
-Command Output
-==============
-Cloud-init can redirect its stdout and stderr based on config given under the
-``output`` config key. The output of any commands run by cloud-init and any
-user or vendor scripts provided will also be included here. The ``output`` key
-accepts a dictionary for configuration. Output files may be specified
-individually for each stage (``init``, ``config``, and ``final``), or a single
-key ``all`` may be used to specify output for all stages.
-
-The output for each stage may be specified as a dictionary of ``output`` and
-``error`` keys, for stdout and stderr respectively, as a tuple with stdout
-first and stderr second, or as a single string to use for both. The strings
-passed to all of these keys are handled by the system shell, so any form of
-redirection that can be used in bash is valid, including piping cloud-init's
-output to ``tee``, or ``logger``. If only a filename is provided, cloud-init
-will append its output to the file as though ``>>`` was specified.
-
-By default, cloud-init loads its output configuration from
-``/etc/cloud/cloud.cfg.d/05_logging.cfg``. The default config directs both
-stdout and stderr from all cloud-init stages to
-``/var/log/cloud-init-output.log``. The default config is given as ::
-
- output: { all: "| tee -a /var/log/cloud-init-output.log" }
-
-For a more complex example, the following configuration would output the init
-stage to ``/var/log/cloud-init.out`` and ``/var/log/cloud-init.err``, for
-stdout and stderr respectively, replacing anything that was previously there.
-For the config stage, it would pipe both stdout and stderr through ``tee -a
-/var/log/cloud-config.log``. For the final stage it would append the output of
-stdout and stderr to ``/var/log/cloud-final.out`` and
-``/var/log/cloud-final.err`` respectively. ::
-
- output:
- init:
- output: "> /var/log/cloud-init.out"
- error: "> /var/log/cloud-init.err"
- config: "tee -a /var/log/cloud-config.log"
- final:
- - ">> /var/log/cloud-final.out"
- - "/var/log/cloud-final.err"
-
-Event Reporting
-===============
-Cloud-init contains an eventing system that allows events to emitted
-to a variety of destinations.
-
-3 configurations are available for reporting events:
-
-- **webhook**: POST to a web server
-- **log**: Write to the cloud-init log at configurable log level
-- **stdout**: Print to stdout
-
-The default configuration is to emit events to the cloud-init log file
-at ``DEBUG`` level.
-
-Event reporting can be configured using the ``reporting`` key in
-cloud-config userdata.
-
-Configuration
--------------
-
-**webhook**
-
-.. code-block:: yaml
-
- reporting:
- <user-defined name>:
- type: webhook
- endpoint: <url>
- timeout: <timeout in seconds>
- retries: <number of retries>
- consumer_key: <OAuth consumer key>
- token_key: <OAuth token key>
- token_secret: <OAuth token secret>
- consumer_secret: <OAuth consumer secret>
-
-``endpoint`` is the only additional required key when specifying
-``type: webhook``.
-
-**log**
-
-.. code-block:: yaml
-
- reporting:
- <user-defined name>:
- type: log
- level: <DEBUG|INFO|WARN|ERROR|FATAL>
-
-``level`` is optional and defaults to "DEBUG".
-
-**print**
-
-.. code-block:: yaml
-
- reporting:
- <user-defined name>:
- type: print
-
-
-Example
-^^^^^^^
-
-The follow example shows configuration for all three sources:
-
-.. code-block:: yaml
-
- #cloud-config
- reporting:
- webserver:
- type: webhook
- endpoint: "http://10.0.0.1:55555/asdf"
- timeout: 5
- retries: 3
- consumer_key: <consumer_key>
- token_key: <token_key>
- token_secret: <token_secret>
- consumer_secret: <consumer_secret>
- info_log:
- type: log
- level: WARN
- stdout:
- type: print
-
-Rsyslog Module
-==============
-Cloud-init's ``cc_rsyslog`` module allows for fully customizable rsyslog
-configuration under the ``rsyslog`` config key. The simplest way to
-use the rsyslog module is by specifying remote servers under the ``remotes``
-key in ``rsyslog`` config. The ``remotes`` key takes a dictionary where each
-key represents the name of an rsyslog server and each value is the
-configuration for that server. The format for server config is:
-
- - optional filter for log messages (defaults to ``*.*``)
- - optional leading ``@`` or ``@@``, indicating udp and tcp respectively
- (defaults to ``@``, for udp)
- - ipv4 or ipv6 hostname or address. ipv6 addresses must be in ``[::1]``
- format, (e.g. ``@[fd00::1]:514``)
- - optional port number (defaults to ``514``)
-
-For example, to send logging to an rsyslog server named ``log_serv`` with
-address ``10.0.4.1``, using port number ``514``, over udp, with all log
-messages enabled one could use either of the following.
-
-With all options specified::
-
- rsyslog:
- remotes:
- log_serv: "*.* @10.0.4.1:514"
-
-With defaults used::
-
- rsyslog:
- remotes:
- log_serv: "10.0.4.1"
-
-
-For more information on rsyslog configuration, see
-:ref:`topics/modules:rsyslog`.
-
-.. _python logging config: https://docs.python.org/3/library/logging.config.html#configuration-file-format
-.. _python logging handlers: https://docs.python.org/3/library/logging.handlers.html
-.. _python logging formatters: https://docs.python.org/3/library/logging.html#formatter-objects
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/merging.rst b/doc/rtd/topics/merging.rst
deleted file mode 100644
index a1422fe3..00000000
--- a/doc/rtd/topics/merging.rst
+++ /dev/null
@@ -1,288 +0,0 @@
-**************************
-Merging User-Data Sections
-**************************
-
-Overview
-========
-
-This was implemented because it has been a common feature request that there be
-a way to specify how cloud-config YAML "dictionaries" provided as user-data are
-merged together when there are multiple YAML files to merge together (say when
-performing an #include).
-
-Since previously the merging algorithm was very simple and would only overwrite
-and not append lists, or strings, and so on it was decided to create a new and
-improved way to merge dictionaries (and their contained objects) together in a
-way that is customizable, thus allowing for users who provide cloud-config
-user-data to determine exactly how their objects will be merged.
-
-For example.
-
-.. code-block:: yaml
-
- #cloud-config (1)
- runcmd:
- - bash1
- - bash2
-
- #cloud-config (2)
- runcmd:
- - bash3
- - bash4
-
-The previous way of merging the two objects above would result in a final
-cloud-config object that contains the following.
-
-.. code-block:: yaml
-
- #cloud-config (merged)
- runcmd:
- - bash3
- - bash4
-
-Typically this is not what users want; instead they would likely prefer:
-
-.. code-block:: yaml
-
- #cloud-config (merged)
- runcmd:
- - bash1
- - bash2
- - bash3
- - bash4
-
-This way makes it easier to combine the various cloud-config objects you have
-into a more useful list, thus reducing duplication necessary to accomplish the
-same result with the previous method.
-
-
-Built-in Mergers
-================
-
-Cloud-init provides merging for the following built-in types:
-
-- Dict
-- List
-- String
-
-The ``Dict`` merger has the following options which control what is done with
-values contained within the config.
-
-- ``allow_delete``: Existing values not present in the new value can be
- deleted, defaults to False
-- ``no_replace``: Do not replace an existing value if one is already present,
- enabled by default.
-- ``replace``: Overwrite existing values with new ones.
-
-The ``List`` merger has the following options which control what is done with
-the values contained within the config.
-
-- ``append``: Add new value to the end of the list, defaults to False.
-- ``prepend``: Add new values to the start of the list, defaults to False.
-- ``no_replace``: Do not replace an existing value if one is already present,
- enabled by default.
-- ``replace``: Overwrite existing values with new ones.
-
-The ``Str`` merger has the following options which control what is done with
-the values contained within the config.
-
-- ``append``: Add new value to the end of the string, defaults to False.
-
-Common options for all merge types which control how recursive merging is
-done on other types.
-
-- ``recurse_dict``: If True merge the new values of the dictionary, defaults to
- True.
-- ``recurse_list``: If True merge the new values of the list, defaults to
- False.
-- ``recurse_array``: Alias for ``recurse_list``.
-- ``recurse_str``: If True merge the new values of the string, defaults to
- False.
-
-
-Customizability
-===============
-
-Because the above merging algorithm may not always be desired (just as the
-previous merging algorithm was not always the preferred one), the concept of
-customized merging was introduced through 'merge classes'.
-
-A merge class is a class definition which provides functions that can be used
-to merge a given type with another given type.
-
-An example of one of these merging classes is the following:
-
-.. code-block:: python
-
- class Merger:
- def __init__(self, merger, opts):
- self._merger = merger
- self._overwrite = 'overwrite' in opts
-
- # This merging algorithm will attempt to merge with
- # another dictionary, on encountering any other type of object
- # it will not merge with said object, but will instead return
- # the original value
- #
- # On encountering a dictionary, it will create a new dictionary
- # composed of the original and the one to merge with, if 'overwrite'
- # is enabled then keys that exist in the original will be overwritten
- # by keys in the one to merge with (and associated values). Otherwise
- # if not in overwrite mode the 2 conflicting keys themselves will
- # be merged.
- def _on_dict(self, value, merge_with):
- if not isinstance(merge_with, (dict)):
- return value
- merged = dict(value)
- for (k, v) in merge_with.items():
- if k in merged:
- if not self._overwrite:
- merged[k] = self._merger.merge(merged[k], v)
- else:
- merged[k] = v
- else:
- merged[k] = v
- return merged
-
-As you can see there is a '_on_dict' method here that will be given a source
-value and a value to merge with. The result will be the merged object. This
-code itself is called by another merging class which 'directs' the merging to
-happen by analyzing the types of the objects to merge and attempting to find a
-know object that will merge that type. I will avoid pasting that here, but it
-can be found in the `mergers/__init__.py` file (see `LookupMerger` and
-`UnknownMerger`).
-
-So following the typical cloud-init way of allowing source code to be
-downloaded and used dynamically, it is possible for users to inject there own
-merging files to handle specific types of merging as they choose (the basic
-ones included will handle lists, dicts, and strings). Note how each merge can
-have options associated with it which affect how the merging is performed, for
-example a dictionary merger can be told to overwrite instead of attempt to
-merge, or a string merger can be told to append strings instead of discarding
-other strings to merge with.
-
-How to activate
-===============
-
-There are a few ways to activate the merging algorithms, and to customize them
-for your own usage.
-
-1. The first way involves the usage of MIME messages in cloud-init to specify
- multipart documents (this is one way in which multiple cloud-config is
- joined together into a single cloud-config). Two new headers are looked
- for, both of which can define the way merging is done (the first header to
- exist wins). These new headers (in lookup order) are 'Merge-Type' and
- 'X-Merge-Type'. The value should be a string which will satisfy the new
- merging format definition (see below for this format).
-
-2. The second way is actually specifying the merge-type in the body of the
- cloud-config dictionary. There are 2 ways to specify this, either as a
- string or as a dictionary (see format below). The keys that are looked up
- for this definition are the following (in order), 'merge_how',
- 'merge_type'.
-
-String format
--------------
-
-The string format that is expected is the following.
-
-::
-
- classname1(option1,option2)+classname2(option3,option4)....
-
-The class name there will be connected to class names used when looking for the
-class that can be used to merge and options provided will be given to the class
-on construction of that class.
-
-For example, the default string that is used when none is provided is the
-following:
-
-::
-
- list()+dict()+str()
-
-Dictionary format
------------------
-
-A dictionary can be used when it specifies the same information as the
-string format (i.e. the second option above), for example:
-
-.. code-block:: python
-
- {'merge_how': [{'name': 'list', 'settings': ['append']},
- {'name': 'dict', 'settings': ['no_replace', 'recurse_list']},
- {'name': 'str', 'settings': ['append']}]}
-
-This would be the equivalent format for default string format but in dictionary
-form instead of string form.
-
-Specifying multiple types and its effect
-========================================
-
-Now you may be asking yourself, if I specify a merge-type header or dictionary
-for every cloud-config that I provide, what exactly happens?
-
-The answer is that when merging, a stack of 'merging classes' is kept, the
-first one on that stack is the default merging classes, this set of mergers
-will be used when the first cloud-config is merged with the initial empty
-cloud-config dictionary. If the cloud-config that was just merged provided a
-set of merging classes (via the above formats) then those merging classes will
-be pushed onto the stack. Now if there is a second cloud-config to be merged
-then the merging classes from the cloud-config before the first will be used
-(not the default) and so on. This way a cloud-config can decide how it will
-merge with a cloud-config dictionary coming after it.
-
-Other uses
-==========
-
-In addition to being used for merging user-data sections, the default merging
-algorithm for merging 'conf.d' YAML files (which form an initial YAML config
-for cloud-init) was also changed to use this mechanism so its full
-benefits (and customization) can also be used there as well. Other places that
-used the previous merging are also, similarly, now extensible (metadata
-merging, for example).
-
-Note, however, that merge algorithms are not used *across* types of
-configuration. As was the case before merging was implemented,
-user-data will overwrite conf.d configuration without merging.
-
-Example cloud-config
-====================
-
-A common request is to include multiple ``runcmd`` directives in different
-files and merge all of the commands together. To achieve this, we must modify
-the default merging to allow for dictionaries to join list values.
-
-
-The first config
-
-.. code-block:: yaml
-
- #cloud-config
- merge_how:
- - name: list
- settings: [append]
- - name: dict
- settings: [no_replace, recurse_list]
-
- runcmd:
- - bash1
- - bash2
-
-The second config
-
-.. code-block:: yaml
-
- #cloud-config
- merge_how:
- - name: list
- settings: [append]
- - name: dict
- settings: [no_replace, recurse_list]
-
- runcmd:
- - bash3
- - bash4
-
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/network-config-format-v1.rst b/doc/rtd/topics/network-config-format-v1.rst
deleted file mode 100644
index a9dd31af..00000000
--- a/doc/rtd/topics/network-config-format-v1.rst
+++ /dev/null
@@ -1,625 +0,0 @@
-.. _network_config_v1:
-
-Networking Config Version 1
-===========================
-
-This network configuration format lets users customize their instance's
-networking interfaces by assigning subnet configuration, virtual device
-creation (bonds, bridges, vlans) routes and DNS configuration.
-
-Required elements of a Network Config Version 1 are ``config`` and
-``version``.
-
-Cloud-init will read this format from :ref:`base_config_reference`.
-
-For example the following could be present in
-``/etc/cloud/cloud.cfg.d/custom-networking.cfg``:
-
-.. code-block:: yaml
-
- network:
- version: 1
- config:
- - type: physical
- name: eth0
- subnets:
- - type: dhcp
-
-The :ref:`datasource_nocloud` datasource can also provide cloud-init
-networking configuration in this Format.
-
-Configuration Types
--------------------
-Within the network ``config`` portion, users include a list of configuration
-types. The current list of support ``type`` values are as follows:
-
-- Physical (``physical``)
-- Bond (``bond``)
-- Bridge (``bridge``)
-- VLAN (``vlan``)
-- Nameserver (``nameserver``)
-- Route (``route``)
-
-Physical, Bond, Bridge and VLAN types may also include IP configuration under
-the key ``subnets``.
-
-- Subnet/IP (``subnets``)
-
-
-Physical
-~~~~~~~~
-The ``physical`` type configuration represents a "physical" network device,
-typically Ethernet-based. At least one of these entries is required for
-external network connectivity. Type ``physical`` requires only one key:
-``name``. A ``physical`` device may contain some or all of the following
-keys:
-
-**name**: *<desired device name>*
-
-A devices name must be less than 15 characters. Names exceeding the maximum
-will be truncated. This is a limitation of the Linux kernel network-device
-structure.
-
-**mac_address**: *<MAC Address>*
-
-The MAC Address is a device unique identifier that most Ethernet-based network
-devices possess. Specifying a MAC Address is optional.
-Letters must be lowercase.
-
-.. note::
-
- MAC addresses must be strings. As MAC addresses which consist of only the
- digits 0-9 (i.e. no hex a-f) can be interpreted as a base 60 integer per
- the `YAML 1.1 spec`_ it is best practice to quote all MAC addresses to ensure
- they are parsed as strings regardless of value.
-
-.. _YAML 1.1 spec: https://yaml.org/type/int.html
-
-.. note::
-
- Cloud-init will handle the persistent mapping between a
- device's ``name`` and the ``mac_address``.
-
-**mtu**: *<MTU SizeBytes>*
-
-The MTU key represents a device's Maximum Transmission Unit, the largest size
-packet or frame, specified in octets (eight-bit bytes), that can be sent in a
-packet- or frame-based network. Specifying ``mtu`` is optional.
-
-.. note::
-
- The possible supported values of a device's MTU is not available at
- configuration time. It's possible to specify a value too large or to
- small for a device and may be ignored by the device.
-
-
-**Physical Example**::
-
- network:
- version: 1
- config:
- # Simple network adapter
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- # Second nic with Jumbo frames
- - type: physical
- name: jumbo0
- mac_address: aa:11:22:33:44:55
- mtu: 9000
- # 10G pair
- - type: physical
- name: gbe0
- mac_address: cd:11:22:33:44:00
- - type: physical
- name: gbe1
- mac_address: cd:11:22:33:44:02
-
-Bond
-~~~~
-A ``bond`` type will configure a Linux software Bond with one or more network
-devices. A ``bond`` type requires the following keys:
-
-**name**: *<desired device name>*
-
-A devices name must be less than 15 characters. Names exceeding the maximum
-will be truncated. This is a limitation of the Linux kernel network-device
-structure.
-
-**mac_address**: *<MAC Address>*
-
-When specifying MAC Address on a bond this value will be assigned to the bond
-device and may be different than the MAC address of any of the underlying
-bond interfaces. Specifying a MAC Address is optional. If ``mac_address`` is
-not present, then the bond will use one of the MAC Address values from one of
-the bond interfaces.
-
-.. note::
-
- MAC addresses must be strings. As MAC addresses which consist of only the
- digits 0-9 (i.e. no hex a-f) can be interpreted as a base 60 integer per
- the `YAML 1.1 spec`_ it is best practice to quote all MAC addresses to ensure
- they are parsed as strings regardless of value.
-
-.. _YAML 1.1 spec: https://yaml.org/type/int.html
-
-**bond_interfaces**: *<List of network device names>*
-
-The ``bond_interfaces`` key accepts a list of network device ``name`` values
-from the configuration. This list may be empty.
-
-**mtu**: *<MTU SizeBytes>*
-
-The MTU key represents a device's Maximum Transmission Unit, the largest size
-packet or frame, specified in octets (eight-bit bytes), that can be sent in a
-packet- or frame-based network. Specifying ``mtu`` is optional.
-
-.. note::
-
- The possible supported values of a device's MTU is not available at
- configuration time. It's possible to specify a value too large or to
- small for a device and may be ignored by the device.
-
-**params**: *<Dictionary of key: value bonding parameter pairs>*
-
-The ``params`` key in a bond holds a dictionary of bonding parameters.
-This dictionary may be empty. For more details on what the various bonding
-parameters mean please read the Linux Kernel Bonding.txt.
-
-Valid ``params`` keys are:
-
- - ``active_slave``: Set bond attribute
- - ``ad_actor_key``: Set bond attribute
- - ``ad_actor_sys_prio``: Set bond attribute
- - ``ad_actor_system``: Set bond attribute
- - ``ad_aggregator``: Set bond attribute
- - ``ad_num_ports``: Set bond attribute
- - ``ad_partner_key``: Set bond attribute
- - ``ad_partner_mac``: Set bond attribute
- - ``ad_select``: Set bond attribute
- - ``ad_user_port_key``: Set bond attribute
- - ``all_slaves_active``: Set bond attribute
- - ``arp_all_targets``: Set bond attribute
- - ``arp_interval``: Set bond attribute
- - ``arp_ip_target``: Set bond attribute
- - ``arp_validate``: Set bond attribute
- - ``downdelay``: Set bond attribute
- - ``fail_over_mac``: Set bond attribute
- - ``lacp_rate``: Set bond attribute
- - ``lp_interval``: Set bond attribute
- - ``miimon``: Set bond attribute
- - ``mii_status``: Set bond attribute
- - ``min_links``: Set bond attribute
- - ``mode``: Set bond attribute
- - ``num_grat_arp``: Set bond attribute
- - ``num_unsol_na``: Set bond attribute
- - ``packets_per_slave``: Set bond attribute
- - ``primary``: Set bond attribute
- - ``primary_reselect``: Set bond attribute
- - ``queue_id``: Set bond attribute
- - ``resend_igmp``: Set bond attribute
- - ``slaves``: Set bond attribute
- - ``tlb_dynamic_lb``: Set bond attribute
- - ``updelay``: Set bond attribute
- - ``use_carrier``: Set bond attribute
- - ``xmit_hash_policy``: Set bond attribute
-
-**Bond Example**::
-
- network:
- version: 1
- config:
- # Simple network adapter
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- # 10G pair
- - type: physical
- name: gbe0
- mac_address: cd:11:22:33:44:00
- - type: physical
- name: gbe1
- mac_address: cd:11:22:33:44:02
- - type: bond
- name: bond0
- bond_interfaces:
- - gbe0
- - gbe1
- params:
- bond-mode: active-backup
-
-Bridge
-~~~~~~
-Type ``bridge`` requires the following keys:
-
-- ``name``: Set the name of the bridge.
-- ``bridge_interfaces``: Specify the ports of a bridge via their ``name``.
- This list may be empty.
-- ``params``: A list of bridge params. For more details, please read the
- bridge-utils-interfaces manpage.
-
-Valid keys are:
-
- - ``bridge_ageing``: Set the bridge's ageing value.
- - ``bridge_bridgeprio``: Set the bridge device network priority.
- - ``bridge_fd``: Set the bridge's forward delay.
- - ``bridge_hello``: Set the bridge's hello value.
- - ``bridge_hw``: Set the bridge's MAC address.
- - ``bridge_maxage``: Set the bridge's maxage value.
- - ``bridge_maxwait``: Set how long network scripts should wait for the
- bridge to be up.
- - ``bridge_pathcost``: Set the cost of a specific port on the bridge.
- - ``bridge_portprio``: Set the priority of a specific port on the bridge.
- - ``bridge_ports``: List of devices that are part of the bridge.
- - ``bridge_stp``: Set spanning tree protocol on or off.
- - ``bridge_waitport``: Set amount of time in seconds to wait on specific
- ports to become available.
-
-
-**Bridge Example**::
-
- network:
- version: 1
- config:
- # Simple network adapter
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- # Second nic with Jumbo frames
- - type: physical
- name: jumbo0
- mac_address: aa:11:22:33:44:55
- mtu: 9000
- - type: bridge
- name: br0
- bridge_interfaces:
- - jumbo0
- params:
- bridge_ageing: 250
- bridge_bridgeprio: 22
- bridge_fd: 1
- bridge_hello: 1
- bridge_maxage: 10
- bridge_maxwait: 0
- bridge_pathcost:
- - jumbo0 75
- bridge_pathprio:
- - jumbo0 28
- bridge_stp: 'off'
- bridge_maxwait:
- - jumbo0 0
-
-
-VLAN
-~~~~
-Type ``vlan`` requires the following keys:
-
-- ``name``: Set the name of the VLAN
-- ``vlan_link``: Specify the underlying link via its ``name``.
-- ``vlan_id``: Specify the VLAN numeric id.
-
-The following optional keys are supported:
-
-**mtu**: *<MTU SizeBytes>*
-
-The MTU key represents a device's Maximum Transmission Unit, the largest size
-packet or frame, specified in octets (eight-bit bytes), that can be sent in a
-packet- or frame-based network. Specifying ``mtu`` is optional.
-
-.. note::
-
- The possible supported values of a device's MTU is not available at
- configuration time. It's possible to specify a value too large or to
- small for a device and may be ignored by the device.
-
-
-**VLAN Example**::
-
- network:
- version: 1
- config:
- # Physical interfaces.
- - type: physical
- name: eth0
- mac_address: c0:d6:9f:2c:e8:80
- # VLAN interface.
- - type: vlan
- name: eth0.101
- vlan_link: eth0
- vlan_id: 101
- mtu: 1500
-
-Nameserver
-~~~~~~~~~~
-
-Users can specify a ``nameserver`` type. Nameserver dictionaries include
-the following keys:
-
-- ``address``: List of IPv4 or IPv6 address of nameservers.
-- ``search``: List of hostnames to include in the resolv.conf search path.
-- ``interface``: Optional. Ties the nameserver definition to the specified
- interface. The value specified here must match the `name` of an interface
- defined in this config. If unspecified, this nameserver will be considered
- a global nameserver.
-
-**Nameserver Example**::
-
- network:
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- subnets:
- - type: static
- address: 192.168.23.14/27
- gateway: 192.168.23.1
- - type: nameserver
- interface: interface0 # Ties nameserver to interface0 only
- address:
- - 192.168.23.2
- - 8.8.8.8
- search:
- - exemplary
-
-
-
-Route
-~~~~~
-
-Users can include static routing information as well. A ``route`` dictionary
-has the following keys:
-
-- ``destination``: IPv4 network address with CIDR netmask notation.
-- ``gateway``: IPv4 gateway address with CIDR netmask notation.
-- ``metric``: Integer which sets the network metric value for this route.
-
-**Route Example**::
-
- network:
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- subnets:
- - type: static
- address: 192.168.23.14/24
- gateway: 192.168.23.1
- - type: route
- destination: 192.168.24.0/24
- gateway: 192.168.24.1
- metric: 3
-
-Subnet/IP
-~~~~~~~~~
-
-For any network device (one of the Config Types) users can define a list of
-``subnets`` which contain ip configuration dictionaries. Multiple subnet
-entries will create interface alias allowing a single interface to use
-different ip configurations.
-
-Valid keys for ``subnets`` include the following:
-
-- ``type``: Specify the subnet type.
-- ``control``: Specify manual, auto or hotplug. Indicates how the interface
- will be handled during boot.
-- ``address``: IPv4 or IPv6 address. It may include CIDR netmask notation.
-- ``netmask``: IPv4 subnet mask in dotted format or CIDR notation.
-- ``gateway``: IPv4 address of the default gateway for this subnet.
-- ``dns_nameservers``: Specify a list of IPv4 dns server IPs to end up in
- resolv.conf.
-- ``dns_search``: Specify a list of search paths to be included in
- resolv.conf.
-- ``routes``: Specify a list of routes for a given interface
-
-
-Subnet types are one of the following:
-
-- ``dhcp4``: Configure this interface with IPv4 dhcp.
-- ``dhcp``: Alias for ``dhcp4``
-- ``dhcp6``: Configure this interface with IPv6 dhcp.
-- ``static``: Configure this interface with a static IPv4.
-- ``static6``: Configure this interface with a static IPv6 .
-- ``ipv6_dhcpv6-stateful``: Configure this interface with ``dhcp6``
-- ``ipv6_dhcpv6-stateless``: Configure this interface with SLAAC and DHCP
-- ``ipv6_slaac``: Configure address with SLAAC
-
-When making use of ``dhcp`` or either of the ``ipv6_dhcpv6`` types,
-no additional configuration is needed in the subnet dictionary.
-
-Using ``ipv6_dhcpv6-stateless`` or ``ipv6_slaac`` allows the IPv6 address to be
-automatically configured with StateLess Address AutoConfiguration (`SLAAC`_).
-SLAAC requires support from the network, so verify that your cloud or network
-offering has support before trying it out. With ``ipv6_dhcpv6-stateless``,
-DHCPv6 is still used to fetch other subnet details such as gateway or DNS
-servers. If you only want to discover the address, use ``ipv6_slaac``.
-
-
-**Subnet DHCP Example**::
-
- network:
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- subnets:
- - type: dhcp
-
-
-**Subnet Static Example**::
-
- network:
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- subnets:
- - type: static
- address: 192.168.23.14/27
- gateway: 192.168.23.1
- dns_nameservers:
- - 192.168.23.2
- - 8.8.8.8
- dns_search:
- - exemplary.maas
-
-The following will result in an ``interface0`` using DHCP and ``interface0:1``
-using the static subnet configuration.
-
-**Multiple subnet Example**::
-
- network:
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- subnets:
- - type: dhcp
- - type: static
- address: 192.168.23.14/27
- gateway: 192.168.23.1
- dns_nameservers:
- - 192.168.23.2
- - 8.8.8.8
- dns_search:
- - exemplary
-
-**Subnet with routes Example**::
-
- network:
- version: 1
- config:
- - type: physical
- name: interface0
- mac_address: '00:11:22:33:44:55'
- subnets:
- - type: dhcp
- - type: static
- address: 10.184.225.122
- netmask: 255.255.255.252
- routes:
- - gateway: 10.184.225.121
- netmask: 255.240.0.0
- network: 10.176.0.0
- - gateway: 10.184.225.121
- netmask: 255.240.0.0
- network: 10.208.0.0
-
-
-Multi-layered configurations
-----------------------------
-
-Complex networking sometimes uses layers of configuration. The syntax allows
-users to build those layers one at a time. All of the virtual network devices
-supported allow specifying an underlying device by their ``name`` value.
-
-**Bonded VLAN Example**::
-
- network:
- version: 1
- config:
- # 10G pair
- - type: physical
- name: gbe0
- mac_address: cd:11:22:33:44:00
- - type: physical
- name: gbe1
- mac_address: cd:11:22:33:44:02
- # Bond.
- - type: bond
- name: bond0
- bond_interfaces:
- - gbe0
- - gbe1
- params:
- bond-mode: 802.3ad
- bond-lacp-rate: fast
- # A Bond VLAN.
- - type: vlan
- name: bond0.200
- vlan_link: bond0
- vlan_id: 200
- subnets:
- - type: dhcp4
-
-More Examples
--------------
-Some more examples to explore the various options available.
-
-**Multiple VLAN example**::
-
- network:
- version: 1
- config:
- - id: eth0
- mac_address: d4:be:d9:a8:49:13
- mtu: 1500
- name: eth0
- subnets:
- - address: 10.245.168.16/21
- dns_nameservers:
- - 10.245.168.2
- gateway: 10.245.168.1
- type: static
- type: physical
- - id: eth1
- mac_address: d4:be:d9:a8:49:15
- mtu: 1500
- name: eth1
- subnets:
- - address: 10.245.188.2/24
- dns_nameservers: []
- type: static
- type: physical
- - id: eth1.2667
- mtu: 1500
- name: eth1.2667
- subnets:
- - address: 10.245.184.2/24
- dns_nameservers: []
- type: static
- type: vlan
- vlan_id: 2667
- vlan_link: eth1
- - id: eth1.2668
- mtu: 1500
- name: eth1.2668
- subnets:
- - address: 10.245.185.1/24
- dns_nameservers: []
- type: static
- type: vlan
- vlan_id: 2668
- vlan_link: eth1
- - id: eth1.2669
- mtu: 1500
- name: eth1.2669
- subnets:
- - address: 10.245.186.1/24
- dns_nameservers: []
- type: static
- type: vlan
- vlan_id: 2669
- vlan_link: eth1
- - id: eth1.2670
- mtu: 1500
- name: eth1.2670
- subnets:
- - address: 10.245.187.2/24
- dns_nameservers: []
- type: static
- type: vlan
- vlan_id: 2670
- vlan_link: eth1
- - address: 10.245.168.2
- search:
- - dellstack
- type: nameserver
-
-.. _SLAAC: https://tools.ietf.org/html/rfc4862
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/network-config.rst b/doc/rtd/topics/network-config.rst
deleted file mode 100644
index 0327fa45..00000000
--- a/doc/rtd/topics/network-config.rst
+++ /dev/null
@@ -1,321 +0,0 @@
-.. _network_config:
-
-*********************
-Network Configuration
-*********************
-
-
-Default Behavior
-================
-
-`Cloud-init`_ 's searches for network configuration in order of increasing
-precedence; each item overriding the previous.
-
-**Datasource**
-
-For example, OpenStack may provide network config in the MetaData Service.
-
-**System Config**
-
-A ``network:`` entry in ``/etc/cloud/cloud.cfg.d/*`` configuration files.
-
-**Kernel Command Line**
-
-``ip=`` or ``network-config=<Base64 encoded YAML config string>``
-
-User-data cannot change an instance's network configuration. In the absence
-of network configuration in any of the above sources , `Cloud-init`_ will
-write out a network configuration that will issue a DHCP request on a "first"
-network interface.
-
-.. note::
-
- The network-config value is expected to be a Base64 encoded YAML string in
- :ref:`network_config_v1` or :ref:`network_config_v2` format. Optionally it
- can be compressed with ``gzip`` prior to Base64 encoding.
-
-
-Disabling Network Configuration
-===============================
-
-Users may disable `Cloud-init`_ 's network configuration capability and rely
-on other methods, such as embedded configuration or other customizations.
-
-`Cloud-init`_ supports the following methods for disabling cloud-init.
-
-
-**Kernel Command Line**
-
-`Cloud-init`_ will check additionally check for the parameter
-``network-config=disabled`` which will automatically disable any network
-configuration.
-
-Example disabling kernel command line entry: ::
-
- network-config=disabled
-
-
-**cloud config**
-
-In the combined cloud-init configuration dictionary, merged from
-``/etc/cloud/cloud.cfg`` and ``/etc/cloud/cloud.cfg.d/*``::
-
- network:
- config: disabled
-
-If `Cloud-init`_ 's networking config has not been disabled, and
-no other network information is found, then it will proceed
-to generate a fallback networking configuration.
-
-Disabling Network Activation
-----------------------------
-
-Some datasources may not be initialized until after network has been brought
-up. In this case, cloud-init will attempt to bring up the interfaces specified
-by the datasource metadata using a network activator discovered by
-`cloudinit.net.activators.select_activators`_.
-
-This behavior can be disabled in the cloud-init configuration dictionary,
-merged from ``/etc/cloud/cloud.cfg`` and ``/etc/cloud/cloud.cfg.d/*``::
-
- disable_network_activation: true
-
-Fallback Network Configuration
-==============================
-
-`Cloud-init`_ will attempt to determine which of any attached network devices
-is most likely to have a connection and then generate a network
-configuration to issue a DHCP request on that interface.
-
-`Cloud-init`_ runs during early boot and does not expect composed network
-devices (such as Bridges) to be available. `Cloud-init`_ does not consider
-the following interface devices as likely 'first' network interfaces for
-fallback configuration; they are filtered out from being selected.
-
-- **loopback**: ``name=lo``
-- **Virtual Ethernet**: ``name=veth*``
-- **Software Bridges**: ``type=bridge``
-- **Software VLANs**: ``type=vlan``
-
-
-`Cloud-init`_ will prefer network interfaces that indicate they are connected
-via the Linux ``carrier`` flag being set. If no interfaces are marked
-connected, then all unfiltered interfaces are potential connections.
-
-Of the potential interfaces, `Cloud-init`_ will attempt to pick the "right"
-interface given the information it has available.
-
-Finally after selecting the "right" interface, a configuration is
-generated and applied to the system.
-
-.. note::
-
- PhotonOS disables fallback networking configuration by default leaving
- network unrendered when no other network config is provided.
- If fallback config is still desired on PhotonOS, it can be enabled by
- providing `disable_fallback_netcfg: false` in
- `/etc/cloud/cloud.cfg:sys_config` settings.
-
-Network Configuration Sources
-=============================
-
-`Cloud-init`_ accepts a number of different network configuration formats in
-support of different cloud substrates. The Datasource for these clouds in
-`Cloud-init`_ will detect and consume Datasource-specific network
-configuration formats for use when writing an instance's network
-configuration.
-
-The following Datasources optionally provide network configuration:
-
-- :ref:`datasource_config_drive`
-
- - `OpenStack Metadata Service Network`_
- - :ref:`network_config_eni`
-
-- :ref:`datasource_digital_ocean`
-
- - `DigitalOcean JSON metadata`_
-
-- :ref:`datasource_nocloud`
-
- - :ref:`network_config_v1`
- - :ref:`network_config_v2`
- - :ref:`network_config_eni`
-
-- :ref:`datasource_opennebula`
-
- - :ref:`network_config_eni`
-
-- :ref:`datasource_openstack`
-
- - :ref:`network_config_eni`
- - `OpenStack Metadata Service Network`_
-
-- :ref:`datasource_smartos`
-
- - `SmartOS JSON Metadata`_
-
-- :ref:`datasource_upcloud`
-
- - `UpCloud JSON metadata`_
-
-- :ref:`datasource_vultr`
-
- - `Vultr JSON metadata`_
-
-For more information on network configuration formats
-
-.. toctree::
- :maxdepth: 1
-
- network-config-format-eni.rst
- network-config-format-v1.rst
- network-config-format-v2.rst
-
-
-Network Configuration Outputs
-=============================
-
-`Cloud-init`_ converts various forms of user supplied or automatically
-generated configuration into an internal network configuration state. From
-this state `Cloud-init`_ delegates rendering of the configuration to Distro
-supported formats. The following ``renderers`` are supported in cloud-init:
-
-- **NetworkManager**
-
-`NetworkManager <https://networkmanager.dev>`_ is the standard Linux network
-configuration tool suite. It supports a wide range of networking setups.
-Configuration is typically stored in ``/etc/NetworkManager``.
-
-It is the default for a number of Linux distributions, notably Fedora;
-CentOS/RHEL; and derivatives.
-
-- **ENI**
-
-/etc/network/interfaces or ``ENI`` is supported by the ``ifupdown`` package
-found in Alpine Linux, Debian and Ubuntu.
-
-- **Netplan**
-
-Introduced in Ubuntu 16.10 (Yakkety Yak), `netplan <https://netplan.io/>`_ has
-been the default network configuration tool in Ubuntu since 17.10 (Artful
-Aardvark). netplan consumes :ref:`network_config_v2` input and renders
-network configuration for supported backends such as ``systemd-networkd`` and
-``NetworkManager``.
-
-- **Sysconfig**
-
-Sysconfig format is used by RHEL, CentOS, Fedora and other derivatives.
-
-
-- **NetBSD, OpenBSD, FreeBSD**
-
-Network renders supporting BSD releases which typically write configuration to
-``/etc/rc.conf``. Unique to BSD renderers is that each renderer also calls
-something akin to `FreeBSD.start_services`_ which will invoke applicable
-network services to setup the network, making network activators unneeded
-for BSD flavors at the moment.
-
-
-Network Output Policy
-=====================
-
-The default policy for selecting a network ``renderer`` in order of preference
-is as follows:
-
-- ENI
-- Sysconfig
-- Netplan
-- NetworkManager
-- FreeBSD
-- NetBSD
-- OpenBSD
-- Networkd
-
-The default policy for selecting a network ``activator`` in order of preference
-is as follows:
-- ENI: using `ifup`, `ifdown` to manage device setup/teardown
-- Netplan: using `netplan apply` to manage device setup/teardown
-- NetworkManager: using `nmcli` to manage device setup/teardown
-- Networkd: using `ip` to manage device setup/teardown
-
-
-When applying the policy, `Cloud-init`_ checks if the current instance has the
-correct binaries and paths to support the renderer. The first renderer that
-can be used is selected. Users may override the network renderer policy by
-supplying an updated configuration in cloud-config. ::
-
- system_info:
- network:
- renderers: ['netplan', 'network-manager', 'eni', 'sysconfig', 'freebsd', 'netbsd', 'openbsd']
- activators: ['eni', 'netplan', 'network-manager', 'networkd']
-
-
-Network Configuration Tools
-===========================
-
-`Cloud-init`_ contains one tool used to test input/output conversion between
-formats. The ``tools/net-convert.py`` in the `Cloud-init`_ source repository
-is helpful for examining expected output for a given input format.
-
-CLI Interface :
-
-.. code-block:: shell-session
-
- % tools/net-convert.py --help
- usage: net-convert.py [-h] --network-data PATH --kind
- {eni,network_data.json,yaml} -d PATH [-m name,mac]
- --output-kind {eni,netplan,sysconfig}
-
- optional arguments:
- -h, --help show this help message and exit
- --network-data PATH, -p PATH
- --kind {eni,network_data.json,yaml}, -k {eni,network_data.json,yaml}
- -d PATH, --directory PATH
- directory to place output in
- -m name,mac, --mac name,mac
- interface name to mac mapping
- --output-kind {eni,netplan,sysconfig}, -ok {eni,netplan,sysconfig}
-
-
-Example output converting V2 to sysconfig:
-
-.. code-block:: shell-session
-
- $ tools/net-convert.py --network-data v2.yaml --kind yaml \
- --output-kind sysconfig -d target
- $ cat target/etc/sysconfig/network-scripts/ifcfg-eth*
-
-Example output:
-
-.. code-block::
-
- # Created by cloud-init on instance boot automatically, do not edit.
- #
- BOOTPROTO=static
- DEVICE=eth7
- IPADDR=192.168.1.5/255.255.255.0
- NM_CONTROLLED=no
- ONBOOT=yes
- TYPE=Ethernet
- USERCTL=no
- # Created by cloud-init on instance boot automatically, do not edit.
- #
- BOOTPROTO=dhcp
- DEVICE=eth9
- NM_CONTROLLED=no
- ONBOOT=yes
- TYPE=Ethernet
- USERCTL=no
-
-
-.. _Cloud-init: https://launchpad.net/cloud-init
-.. _DigitalOcean JSON metadata: https://developers.digitalocean.com/documentation/metadata/
-.. _OpenStack Metadata Service Network: https://specs.openstack.org/openstack/nova-specs/specs/liberty/implemented/metadata-service-network-info.html
-.. _SmartOS JSON Metadata: https://eng.joyent.com/mdata/datadict.html
-.. _UpCloud JSON metadata: https://developers.upcloud.com/1.3/8-servers/#metadata-service
-.. _Vultr JSON metadata: https://www.vultr.com/metadata/
-.. _cloudinit.net.activators.select_activators: https://github.com/canonical/cloud-init/blob/main/cloudinit/net/activators.py#L279
-.. _FreeBSD.start_services: https://github.com/canonical/cloud-init/blob/main/cloudinit/net/freebsd.py#L28
-
-.. vi: textwidth=79
diff --git a/doc/rtd/topics/tutorials/lxd.rst b/doc/rtd/topics/tutorials/lxd.rst
deleted file mode 100644
index 67c97340..00000000
--- a/doc/rtd/topics/tutorials/lxd.rst
+++ /dev/null
@@ -1,165 +0,0 @@
-.. _tutorial_lxd:
-
-Tutorials
-*********
-
-.. toctree::
- :titlesonly:
- :hidden:
-
- qemu.rst
-
-LXD
-===
-
-In this tutorial, we will create our first cloud-init user data script
-and deploy it into an LXD container. We'll be using LXD_ for this tutorial
-because it provides first class support for cloud-init user data as well as
-systemd support. Because it is container based, it allows for quick
-testing and iterating on our user data definition.
-
-Setup LXD
-=========
-
-Skip this section if you already have LXD_ set up.
-
-Install LXD
------------
-
-.. code-block:: shell-session
-
- $ sudo snap install lxd
-
-If you don't have snap, you can install LXD using one of the
-`other installation options`_.
-
-Initialize LXD
---------------
-
-.. code-block:: shell-session
-
- $ lxd init --minimal
-
-The minimal configuration should work fine for our purposes. It can always
-be changed at a later time if needed.
-
-Define our user data
-====================
-
-Now that LXD is set up, we can define our user data. Create the
-following file on your local filesystem at ``/tmp/my-user-data``:
-
-.. code-block:: yaml
-
- #cloud-config
- runcmd:
- - echo 'Hello, World!' > /var/tmp/hello-world.txt
-
-Here we are defining our cloud-init user data in the
-:ref:`cloud-config<topics/format:Cloud Config Data>` format, using the
-:ref:`runcmd module <mod-runcmd>` to define a command to run. When applied, it
-should write ``Hello, World!`` to ``/var/tmp/hello-world.txt``.
-
-Launch a container with our user data
-=====================================
-
-Now that we have LXD setup and our user data defined, we can launch an
-instance with our user data:
-
-.. code-block:: shell-session
-
- $ lxc launch ubuntu:focal my-test --config=user.user-data="$(cat /tmp/my-user-data)"
-
-Verify that cloud-init ran successfully
-=======================================
-
-After launching the container, we should be able to connect
-to our instance using
-
-.. code-block:: shell-session
-
- $ lxc shell my-test
-
-You should now be in a shell inside the LXD instance.
-Before validating the user data, let's wait for cloud-init to complete
-successfully:
-
-.. code-block:: shell-session
-
- $ cloud-init status --wait
-
-Which provides the following output:
-
-.. code-block::
-
- status: done
-
-We can now verify that cloud-init received the expected user data:
-
-.. code-block:: shell-session
-
- $ cloud-init query userdata
-
-Which should print the following to the terminal window:
-
-.. code-block::
-
- #cloud-config
- runcmd:
- - echo 'Hello, World!' > /var/tmp/hello-world.txt
-
-We can also assert the user data we provided is a valid cloud-config:
-
-.. code-block:: shell-session
-
- $ cloud-init schema --system --annotate
-
-Which should print the following:
-
-.. code-block::
-
- Valid cloud-config: system userdata
-
-Finally, verify that our user data was applied successfully:
-
-.. code-block:: shell-session
-
- $ cat /var/tmp/hello-world.txt
-
-Which should then print:
-
-.. code-block::
-
- Hello, World!
-
-We can see that cloud-init has consumed our user data successfully!
-
-Tear down
-=========
-
-Exit the container shell (i.e., using ``exit`` or ctrl-d). Once we have
-exited the container, we can stop the container using:
-
-.. code-block:: shell-session
-
- $ lxc stop my-test
-
-and we can remove the container using:
-
-.. code-block:: shell-session
-
- $ lxc rm my-test
-
-What's next?
-============
-
-In this tutorial, we used the :ref:`runcmd module <mod-runcmd>` to execute a
-shell command. The full list of modules available can be found in
-:ref:`modules documentation<modules>`.
-Each module contains examples of how to use it.
-
-You can also head over to the :ref:`examples<yaml_examples>` page for
-examples of more common use cases.
-
-.. _LXD: https://linuxcontainers.org/lxd/
-.. _other installation options: https://linuxcontainers.org/lxd/getting-started-cli/#other-installation-options
diff --git a/doc/rtd/topics/tutorials/qemu-debugging.rst b/doc/rtd/topics/tutorials/qemu-debugging.rst
deleted file mode 100644
index 845f9fcd..00000000
--- a/doc/rtd/topics/tutorials/qemu-debugging.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-.. _qemu_debug_info:
-
-Qemu tutorial debugging
-***********************
-
-You may wish to test out the commands in this tutorial as a
-:download:`script<qemu-script.sh>` to check for copy-paste mistakes.
-
-If you successfully launched the virtual machine, but couldn't log in,
-there are a few places to check to debug your setup.
-
-To debug, answer the following questions:
-
-Did cloud-init discover the IMDS webserver?
-===========================================
-
-The webserver should print a message in the terminal for each request it
-receives. If it didn't print out any messages when the virtual machine booted,
-then cloud-init was unable to obtain the config. Make sure that the webserver
-can be locally accessed using ``curl`` or ``wget``.
-
-.. code-block:: sh
-
- $ curl 0.0.0.0:8000/user-data
- $ curl 0.0.0.0:8000/meta-data
- $ curl 0.0.0.0:8000/vendor-data
-
-
-Did the IMDS webserver serve the expected files?
-================================================================
-
-If the webserver prints out 404 errors when launching Qemu, then first check
-that you started the server in the temp directory.
-
-Were the configurations inside the file correct?
-===================================================
-When launching Qemu, if the webserver shows that it succeeded in serving
-``user-data``, ``meta-data``, and ``vendor-data``, but you cannot log in, then
-you may have provided incorrect cloud-config files. If you can mount a copy of
-the virtual machine's filesystem locally to inspect the logs, it should be
-possible to get clues about what went wrong.
diff --git a/doc/rtd/topics/tutorials/qemu.rst b/doc/rtd/topics/tutorials/qemu.rst
deleted file mode 100644
index bf36b3b9..00000000
--- a/doc/rtd/topics/tutorials/qemu.rst
+++ /dev/null
@@ -1,295 +0,0 @@
-.. _tutorial_qemu:
-
-Qemu Tutorial
-*************
-
-.. toctree::
- :titlesonly:
- :hidden:
-
- qemu-debugging.rst
-
-
-
-In this tutorial, we will demonstrate launching an Ubuntu cloud image in a
-virtual machine that uses cloud-init to pre-configure the system during boot.
-
-The goal of this tutorial is to provide a minimal demonstration of cloud-init
-that you can use as a development environment to test cloud-init
-configurations locally prior to launching in the cloud.
-
-
-Why Qemu?
-=========
-
-Qemu_ is a cross-platform emulator capable of running performant virtual
-machines. Qemu is used at the core of a broad range of production operating
-system deployments and open source software projects (including libvirt, LXD,
-and vagrant) and is capable of running Windows, Linux, and Unix guest operating
-systems. While Qemu is flexibile and feature-rich, we are using it because of
-the broad support it has due to its broad adoption and ability to run on
-\*nix-derived operating systems.
-
-
-What is an IMDS?
-================
-
-Instance Metadata Service is a service provided by most cloud providers as a
-means of providing information to virtual machine instances. This service is
-used by cloud providers to expose information to a virtual machine. This
-service is used for many different things, and is the primary mechanism for
-some clouds to expose cloud-init configuration data to the instance.
-
-
-How does cloud-init use the IMDS?
-=================================
-
-The IMDS uses a private http webserver to provide metadata to each operating
-system instance. During early boot, cloud-init sets up network access and
-queries this webserver to gather configuration data. This allows cloud-init to
-configure your operating system while it boots.
-
-In this tutorial we emulate this workflow using Qemu and a simple python
-webserver. This workflow may be suitable for developing and testing cloud-init
-configurations prior to cloud deployments.
-
-
-How to use this tutorial
-========================
-
-In this tutorial each code block is to be copied and pasted directly
-into the terminal then executed. Omit the prompt ``$`` before each command.
-
-Each code block is preceded by a description of what the command does.
-
-
-Install Qemu
-============
-
-.. code-block:: sh
-
- $ sudo apt install qemu-system-x86
-
-If you are not using Ubuntu, you can visit Qemu's `install instructions`_ for
-additional information.
-
-
-Create a temporary directory
-============================
-
-This directory will store our cloud image and configuration files for
-:ref:`user-data<user_data_formats>`, :ref:`meta-data<instance_metadata>`, and
-:ref:`vendor-data<vendordata>`
-
-This tutorial expects that you run all commands from this temporary
-directory. Failure to do so will result in an unconfigured virtual
-machine.
-
-Create a temporary directory and make it your current working directory with
-``cd``.
-
-.. code-block:: sh
-
- $ mkdir temp
- $ cd temp
-
-
-Download a cloud image
-======================
-
-Cloud images typically come with cloud-init pre-installed and configured to run
-on first boot. Users should not need to worry about installing cloud-init
-unless they are manually creating their own images. In this case we select the
-latest Ubuntu LTS_.
-
-Download the server image using ``wget``.
-
-.. code-block:: sh
-
- $ wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
-
-
-Define our user data
-====================
-
-Create the following file ``user-data``. This user-data cloud-config
-sets the password of the default user and sets it to never expire. For
-more details see this module_.
-
-Execute the following command, which creates a file named ``user-data`` with
-configuration data.
-
-.. code-block:: sh
-
- $ cat << EOF > user-data
- #cloud-config
- password: password
- chpasswd:
- expire: False
-
- EOF
-
-
-What is user data?
-==================
-
-Before moving forward, let's inspect our user data file.
-
-.. code-block:: sh
-
- $ cat user-data
-
-You should see the following contents:
-
-.. code-block:: yaml
-
- #cloud-config
- password: password
- chpasswd:
- expire: False
-
-The first line starts with ``#cloud-config``, which tells cloud-init
-which type of user-data is in the config. Cloud-config is a YAML-based
-configuration type that tells cloud-init how to configure the virtual machine
-instance. Multiple different format types are supported by cloud-init. See the
-:ref:`documentation describing different formats<user_data_formats>`.
-
-The second line, ``password: password``, per :ref:`the docs<mod-users_groups>`,
-sets the default user's password to ``password``.
-
-The third and fourth lines direct cloud-init to not require password reset on
-first login.
-
-Define our meta data
-====================
-
-Execute the following command, which creates a file named ``meta-data`` with
-configuration data.
-
-.. code-block:: sh
-
- $ cat << EOF > meta-data
- instance-id: someid/somehostname
- local-hostname: jammy
-
- EOF
-
-
-Define our vendor data
-======================
-
-Now create the empty file ``vendor-data`` in your temporary directory. This
-will speed up the retry wait time.
-
-.. code-block:: sh
-
- $ touch vendor-data
-
-
-Start an ad hoc IMDS webserver
-==============================
-
-In a second terminal, change to your temporary directory and then start the
-python webserver (built-in to python).
-
-.. code-block:: sh
-
- $ cd temp
- $ python3 -m http.server --directory .
-
-
-Launch a virtual machine with our user data
-===========================================
-
-Switch back to your original terminal so we can launch the virtual machine.
-By default, Qemu will print the kernel logs and systemd logs to the terminal
-while the operating system boots. This may take a few moments to complete.
-
-If the output stopped scrolling but you don't see a prompt yet, press ``enter``
-to get to login prompt.
-
-.. code-block:: sh
-
- $ qemu-system-x86_64 \
- -net nic \
- -net user \
- -machine accel=kvm:tcg \
- -cpu host \
- -m 512 \
- -nographic \
- -hda jammy-server-cloudimg-amd64.img \
- -smbios type=1,serial=ds='nocloud-net;s=http://10.0.2.2:8000/'
-
-How is Qemu configured for cloud-init?
-======================================
-
-When launching Qemu, machine configuration is specified on the command
-line. Many things may be configured: memory size, graphical output, networking
-information, hard drives and more.
-
-Examine the last two lines of this command. This one,
-``-hda jammy-server-cloudimg-amd64.img``, tells qemu to use the cloud
-image as a virtual hard drive. This will cause the virtual machine to
-boot Ubuntu which already has cloud-init installed.
-
-The last line tells cloud-init where it can find user-data using the
-:ref:`NoCloud datasource<datasource_nocloud>`. During boot cloud-init checks
-the ``SMBIOS`` serial number for `ds=nocloud-net`. If found, cloud-init will
-use the specified URL to source its userdata config files. In this case we use
-the default gateway of the virtual machine (``10.0.2.2``) and default port
-number of the python webserver (``8000``), so that cloud-init in the virtual
-machine will query the server running on host.
-
-Verify that cloud-init ran successfully
-=======================================
-
-After launching the virtual machine we should be able to connect to our
-instance using the default distro username.
-
-In this case the default username is ``ubuntu`` and the password we configured
-is ``password``.
-
-If you can log in using the configured password, it worked!
-
-If you cloudn't log in, see
-:ref:`this page for debug information<qemu_debug_info>`.
-
-
-Check cloud-init status
-=======================
-
-.. code-block:: sh
-
- $ cloud-init status --wait
-
-If you see ``status: done`` in the output, it succeeded!
-
-If you see a failed status, you'll want to check ``/var/log/cloud-init.log``
-for warning/error messages.
-
-
-Tear down
-=========
-
-Exit the Qemu shell using ``ctrl-a x`` (that's ``ctrl`` and ``a``
-simultaneously, followed by ``x``).
-
-Stop the python webserver that was started in a different terminal
-(``ctrl-c``).
-
-
-What's next?
-============
-
-In this tutorial, we configured the default user's password.
-The full list of modules available can be found in
-:ref:`modules documentation<modules>`.
-The documentation for each module contains examples of how to use it.
-
-You can also head over to the :ref:`examples<yaml_examples>` page for
-examples of more common use cases.
-
-.. _Qemu: https://www.qemu.org
-.. _module: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#set-passwords
-.. _install instructions: https://www.qemu.org/download/#linux
-.. _LTS: https://wiki.ubuntu.com/Releases
diff --git a/doc/rtd/topics/vendordata.rst b/doc/rtd/topics/vendordata.rst
deleted file mode 100644
index 6ef6b74b..00000000
--- a/doc/rtd/topics/vendordata.rst
+++ /dev/null
@@ -1,73 +0,0 @@
-.. _vendordata:
-
-***********
-Vendor Data
-***********
-
-Overview
-========
-
-Vendordata is data provided by the entity that launches an instance
-(for example, the cloud provider). This data can be used to
-customize the image to fit into the particular environment it is
-being run in.
-
-Vendordata follows the same rules as user-data, with the following
-caveats:
-
- 1. Users have ultimate control over vendordata. They can disable its
- execution or disable handling of specific parts of multipart input.
- 2. By default it only runs on first boot
- 3. Vendordata can be disabled by the user. If the use of vendordata is
- required for the instance to run, then vendordata should not be used.
- 4. user supplied cloud-config is merged over cloud-config from vendordata.
-
-Users providing cloud-config data can use the '#cloud-config-jsonp' method to
-more finely control their modifications to the vendor supplied cloud-config.
-For example, if both vendor and user have provided 'runcmd' then the default
-merge handler will cause the user's runcmd to override the one provided by the
-vendor. To append to 'runcmd', the user could better provide multipart input
-with a cloud-config-jsonp part like:
-
-.. code:: yaml
-
- #cloud-config-jsonp
- [{ "op": "add", "path": "/runcmd", "value": ["my", "command", "here"]}]
-
-Further, we strongly advise vendors to not 'be evil'. By evil, we
-mean any action that could compromise a system. Since users trust
-you, please take care to make sure that any vendordata is safe,
-atomic, idempotent and does not put your users at risk.
-
-Input Formats
-=============
-
-cloud-init will download and cache to filesystem any vendor-data that it
-finds. Vendordata is handled exactly like user-data. That means that the
-vendor can supply multipart input and have those parts acted on in the same
-way as user-data.
-
-The only differences are:
-
- * vendor-data-defined scripts are stored in a different location than
- user-data-defined scripts (to avoid namespace collision)
- * user can disable part handlers by cloud-config settings.
- For example, to disable handling of 'part-handlers' in vendor-data,
- the user could provide user-data like this:
-
- .. code:: yaml
-
- #cloud-config
- vendordata: {excluded: 'text/part-handler'}
-
-Examples
-========
-There are examples in the examples subdirectory.
-
-Additionally, the 'tools' directory contains 'write-mime-multipart',
-which can be used to easily generate mime-multi-part files from a list
-of input files. That data can then be given to an instance.
-
-See 'write-mime-multipart --help' for usage.
-
-.. vi: textwidth=79
diff --git a/doc/rtd/tutorial/index.rst b/doc/rtd/tutorial/index.rst
new file mode 100644
index 00000000..392d2465
--- /dev/null
+++ b/doc/rtd/tutorial/index.rst
@@ -0,0 +1,37 @@
+.. _tutorial_index:
+
+Tutorials
+*********
+
+This section contains step-by-step tutorials to help you get started with
+``cloud-init``. We hope our tutorials make as few assumptions as possible and
+are accessible to anyone with an interest in ``cloud-init``. They should be a
+great place to start learning about ``cloud-init``, how it works, and what it's
+capable of.
+
+-----
+
+Core tutorial
+=============
+
+This tutorial, which we recommend if you are completely new to ``cloudinit``,
+uses the QEMU emulator to introduce you to all of the key concepts, tools,
+processes and operations that you will need to get started.
+
+.. toctree::
+ :maxdepth: 1
+
+ qemu.rst
+
+Quick-start tutorial
+====================
+
+This tutorial is recommended if you have some familiarity with ``cloud-init``
+or the concepts around it, and are looking to get started as quickly as
+possible. Here, you will use an LXD container to deploy a ``cloud-init``
+user data script.
+
+.. toctree::
+ :maxdepth: 1
+
+ lxd.rst
diff --git a/doc/rtd/tutorial/lxd.rst b/doc/rtd/tutorial/lxd.rst
new file mode 100644
index 00000000..33866a21
--- /dev/null
+++ b/doc/rtd/tutorial/lxd.rst
@@ -0,0 +1,175 @@
+.. _tutorial_lxd:
+
+Quick-start tutorial with LXD
+*****************************
+
+In this tutorial, we will create our first ``cloud-init`` user data script
+and deploy it into an `LXD`_ container.
+
+Why LXD?
+========
+
+We'll be using LXD for this tutorial because it provides first class support
+for ``cloud-init`` user data, as well as ``systemd`` support. Because it is
+container based, it allows us to quickly test and iterate upon our user data
+definition.
+
+How to use this tutorial
+========================
+
+In this tutorial, the commands in each code block can be copied and pasted
+directly into the terminal. Omit the prompt (``$``) before each command, or
+use the "copy code" button on the right-hand side of the block, which will copy
+the command for you without the prompt.
+
+Each code block is preceded by a description of what the command does, and
+followed by an example of the type of output you should expect to see.
+
+Install and initialise LXD
+==========================
+
+If you already have LXD set up, you can skip this section. Otherwise, let's
+install LXD:
+
+.. code-block:: shell-session
+
+ $ sudo snap install lxd
+
+If you don't have snap, you can install LXD using one of the
+`other installation options`_.
+
+Now we need to initialise LXD. The minimal configuration will be enough for
+the purposes of this tutorial. If you need to, you can always change the
+configuration at a later time.
+
+.. code-block:: shell-session
+
+ $ lxd init --minimal
+
+Define our user data
+====================
+
+Now that LXD is set up, we can define our user data. Create the
+following file on your local filesystem at :file:`/tmp/my-user-data`:
+
+.. code-block:: yaml
+
+ #cloud-config
+ runcmd:
+ - echo 'Hello, World!' > /var/tmp/hello-world.txt
+
+Here, we are defining our ``cloud-init`` user data in the
+:ref:`#cloud-config<user_data_formats>` format, using the
+:ref:`runcmd module <mod-runcmd>` to define a command to run. When applied, it
+will write ``Hello, World!`` to :file:`/var/tmp/hello-world.txt` (as we shall
+see later!).
+
+Launch a LXD container with our user data
+=========================================
+
+Now that we have LXD set up and our user data defined, we can launch an
+instance with our user data:
+
+.. code-block:: shell-session
+
+ $ lxc launch ubuntu:focal my-test --config=user.user-data="$(cat /tmp/my-user-data)"
+
+Verify that ``cloud-init`` ran successfully
+-------------------------------------------
+
+After launching the container, we should be able to connect to our instance
+using:
+
+.. code-block:: shell-session
+
+ $ lxc shell my-test
+
+You should now be in a shell inside the LXD instance.
+
+Before validating the user data, let's wait for ``cloud-init`` to complete
+successfully:
+
+.. code-block:: shell-session
+
+ $ cloud-init status --wait
+
+Which provides the following output:
+
+.. code-block::
+
+ status: done
+
+Verify our user data
+--------------------
+
+Now we know that ``cloud-init`` has been successfully run, we can verify that
+it received the expected user data we provided earlier:
+
+.. code-block:: shell-session
+
+ $ cloud-init query userdata
+
+Which should print the following to the terminal window:
+
+.. code-block::
+
+ #cloud-config
+ runcmd:
+ - echo 'Hello, World!' > /var/tmp/hello-world.txt
+
+We can also assert the user data we provided is a valid cloud-config:
+
+.. code-block:: shell-session
+
+ $ cloud-init schema --system --annotate
+
+Which should print the following:
+
+.. code-block::
+
+ Valid cloud-config: system userdata
+
+Finally, let us verify that our user data was applied successfully:
+
+.. code-block:: shell-session
+
+ $ cat /var/tmp/hello-world.txt
+
+Which should then print:
+
+.. code-block::
+
+ Hello, World!
+
+We can see that ``cloud-init`` has received and consumed our user data
+successfully!
+
+Tear down
+=========
+
+Exit the container shell (by typing :command:`exit` or pressing :kbd:`ctrl-d`).
+Once we have exited the container, we can stop the container using:
+
+.. code-block:: shell-session
+
+ $ lxc stop my-test
+
+We can then remove the container completely using:
+
+.. code-block:: shell-session
+
+ $ lxc rm my-test
+
+What's next?
+============
+
+In this tutorial, we used the :ref:`runcmd module <mod-runcmd>` to execute a
+shell command. The full list of modules available can be found in our
+:ref:`modules documentation<modules>`.
+Each module contains examples of how to use it.
+
+You can also head over to the :ref:`examples page<yaml_examples>` for
+examples of more common use cases.
+
+.. _LXD: https://linuxcontainers.org/lxd/
+.. _other installation options: https://linuxcontainers.org/lxd/getting-started-cli/#other-installation-options
diff --git a/doc/rtd/tutorial/qemu-debugging.rst b/doc/rtd/tutorial/qemu-debugging.rst
new file mode 100644
index 00000000..08d4c4c5
--- /dev/null
+++ b/doc/rtd/tutorial/qemu-debugging.rst
@@ -0,0 +1,41 @@
+.. _qemu_debug_info:
+
+QEMU tutorial debugging
+***********************
+
+You may wish to test out the commands in this tutorial as a
+:download:`script<qemu-script.sh>` to check for copy-paste mistakes.
+
+If you successfully launched the virtual machine, but couldn't log in,
+there are a few places to check to debug your setup.
+
+To debug, answer the following questions:
+
+Did ``cloud-init`` discover the IMDS webserver?
+===============================================
+
+The webserver should print a message in the terminal for each request it
+receives. If it didn't print out any messages when the virtual machine booted,
+then ``cloud-init`` was unable to obtain the config. Make sure that the
+webserver can be locally accessed using :command:`curl` or :command:`wget`.
+
+.. code-block:: sh
+
+ $ curl 0.0.0.0:8000/user-data
+ $ curl 0.0.0.0:8000/meta-data
+ $ curl 0.0.0.0:8000/vendor-data
+
+Did the IMDS webserver serve the expected files?
+================================================
+
+If the webserver prints out ``404 errors`` when launching QEMU, then check
+that you started the server in the temp directory.
+
+Were the configurations inside the file correct?
+================================================
+
+When launching QEMU, if the webserver shows that it succeeded in serving
+:file:`user-data`, :file:`meta-data` and :file:`vendor-data`, but you cannot
+log in, then you may have provided incorrect cloud-config files. If you can
+mount a copy of the virtual machine's filesystem locally to inspect the logs,
+it should be possible to get clues about what went wrong.
diff --git a/doc/rtd/topics/tutorials/qemu-script.sh b/doc/rtd/tutorial/qemu-script.sh
index 19a2cf85..19a2cf85 100755
--- a/doc/rtd/topics/tutorials/qemu-script.sh
+++ b/doc/rtd/tutorial/qemu-script.sh
diff --git a/doc/rtd/tutorial/qemu.rst b/doc/rtd/tutorial/qemu.rst
new file mode 100644
index 00000000..4370051a
--- /dev/null
+++ b/doc/rtd/tutorial/qemu.rst
@@ -0,0 +1,292 @@
+.. _tutorial_qemu:
+
+Core tutorial with QEMU
+***********************
+
+.. toctree::
+ :titlesonly:
+ :hidden:
+
+ qemu-debugging.rst
+
+In this tutorial, we will launch an Ubuntu cloud image in a virtual machine
+that uses ``cloud-init`` to pre-configure the system during boot.
+
+The goal of this tutorial is to provide a minimal demonstration of
+``cloud-init``, which you can then use as a development environment to test
+your ``cloud-init`` configurations locally before launching to the cloud.
+
+Why QEMU?
+=========
+
+`QEMU`_ is a cross-platform emulator capable of running performant virtual
+machines. QEMU is used at the core of a broad range of production operating
+system deployments and open source software projects (including libvirt, LXD,
+and vagrant) and is capable of running Windows, Linux, and Unix guest operating
+systems. While QEMU is flexibile and feature-rich, we are using it because of
+the broad support it has due to its broad adoption and ability to run on
+\*nix-derived operating systems.
+
+How to use this tutorial
+========================
+
+In this tutorial, the commands in each code block can be copied and pasted
+directly into the terminal. Omit the prompt (``$``) before each command, or
+use the "copy code" button on the right-hand side of the block, which will copy
+the command for you without the prompt.
+
+Each code block is preceded by a description of what the command does, and
+followed by an example of the type of output you should expect to see.
+
+Install QEMU
+============
+
+.. code-block:: sh
+
+ $ sudo apt install qemu-system-x86
+
+If you are not using Ubuntu, you can visit QEMU's `install instructions`_ for
+additional information.
+
+Create a temporary directory
+============================
+
+This directory will store our cloud image and configuration files for
+:ref:`user data<user_data_formats>`, :ref:`metadata<instance_metadata>`, and
+:ref:`vendor data<vendordata>`.
+
+You should run all commands from this temporary directory. If you run the
+commands from anywhere else, your virtual machine will not be configured.
+
+Let's create a temporary directory and make it our current working directory
+with :command:`cd`:
+
+.. code-block:: sh
+
+ $ mkdir temp
+ $ cd temp
+
+Download a cloud image
+======================
+
+Cloud images typically come with ``cloud-init`` pre-installed and configured to
+run on first boot. You will not need to worry about installing ``cloud-init``
+for now, since we are not manually creating our own image in this tutorial.
+
+In our case, we want to select the latest Ubuntu LTS_. Let's download the
+server image using :command:`wget`:
+
+.. code-block:: sh
+
+ $ wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
+
+Define our user data
+====================
+
+Now we need to create our :file:`user-data` file. This user data cloud-config
+sets the password of the default user, and sets that password to never expire.
+For more details you can refer to the
+:ref:`Set Passwords module page<mod-set_passwords>`.
+
+Run the following command, which creates a file named :file:`user-data`
+containing our configuration data.
+
+.. code-block:: sh
+
+ $ cat << EOF > user-data
+ #cloud-config
+ password: password
+ chpasswd:
+ expire: False
+
+ EOF
+
+What is user data?
+==================
+
+Before moving forward, let's inspect our :file:`user-data` file.
+
+.. code-block:: sh
+
+ $ cat user-data
+
+You should see the following contents:
+
+.. code-block:: yaml
+
+ #cloud-config
+ password: password
+ chpasswd:
+ expire: False
+
+The first line starts with ``#cloud-config``, which tells ``cloud-init``
+what type of user data is in the config. Cloud-config is a YAML-based
+configuration type that tells ``cloud-init`` how to configure the virtual
+machine instance. Multiple different format types are supported by
+``cloud-init``. For more information, see the
+:ref:`documentation describing different formats<user_data_formats>`.
+
+The second line, ``password: password``, as per
+:ref:`the Users and Groups module docs<mod-users_groups>`, sets the default
+user's password to ``password``.
+
+The third and fourth lines direct ``cloud-init`` to not require a password
+reset on first login.
+
+Define our metadata
+===================
+
+Now let's run the following command, which creates a file named
+:file:`meta-data` containing configuration data.
+
+.. code-block:: sh
+
+ $ cat << EOF > meta-data
+ instance-id: someid/somehostname
+ local-hostname: jammy
+
+ EOF
+
+Define our vendor data
+======================
+
+Now we will create the empty file :file:`vendor-data` in our temporary
+directory. This will speed up the retry wait time.
+
+.. code-block:: sh
+
+ $ touch vendor-data
+
+
+Start an ad hoc IMDS webserver
+==============================
+
+Open up a second terminal window, change to your temporary directory and then
+start the built-in Python webserver:
+
+.. code-block:: sh
+
+ $ cd temp
+ $ python3 -m http.server --directory .
+
+What is an IMDS?
+----------------
+
+Instance Metadata Service (IMDS) is a service provided by most cloud providers
+as a means of providing information to virtual machine instances. This service
+is used by cloud providers to expose information to a virtual machine. This
+service is used for many different things, and is the primary mechanism for
+some clouds to expose ``cloud-init`` configuration data to the instance.
+
+How does ``cloud-init`` use the IMDS?
+-------------------------------------
+
+The IMDS uses a private http webserver to provide metadata to each operating
+system instance. During early boot, ``cloud-init`` sets up network access and
+queries this webserver to gather configuration data. This allows ``cloud-init``
+to configure your operating system while it boots.
+
+In this tutorial we are emulating this workflow using QEMU and a simple Python
+webserver. This workflow is suitable for developing and testing
+``cloud-init`` configurations prior to cloud deployments.
+
+Launch a virtual machine with our user data
+===========================================
+
+Switch back to your original terminal, and run the following command so we can
+launch our virtual machine. By default, QEMU will print the kernel logs and
+``systemd`` logs to the terminal while the operating system boots. This may
+take a few moments to complete.
+
+.. code-block:: sh
+
+ $ qemu-system-x86_64 \
+ -net nic \
+ -net user \
+ -machine accel=kvm:tcg \
+ -cpu host \
+ -m 512 \
+ -nographic \
+ -hda jammy-server-cloudimg-amd64.img \
+ -smbios type=1,serial=ds='nocloud-net;s=http://10.0.2.2:8000/'
+
+.. note::
+ If the output stopped scrolling but you don't see a prompt yet, press
+ :kbd:`Enter` to get to the login prompt.
+
+How is QEMU configured for ``cloud-init``?
+------------------------------------------
+
+When launching QEMU, our machine configuration is specified on the command
+line. Many things may be configured: memory size, graphical output, networking
+information, hard drives and more.
+
+Let us examine the final two lines of our previous command. The first of them,
+:command:`-hda jammy-server-cloudimg-amd64.img`, tells QEMU to use the cloud
+image as a virtual hard drive. This will cause the virtual machine to
+boot Ubuntu, which already has ``cloud-init`` installed.
+
+The second line tells ``cloud-init`` where it can find user data, using the
+:ref:`NoCloud datasource<datasource_nocloud>`. During boot, ``cloud-init``
+checks the ``SMBIOS`` serial number for ``ds=nocloud-net``. If found,
+``cloud-init`` will use the specified URL to source its user data config files.
+
+In this case, we use the default gateway of the virtual machine (``10.0.2.2``)
+and default port number of the Python webserver (``8000``), so that
+``cloud-init`` will, inside the virtual machine, query the server running on
+host.
+
+Verify that ``cloud-init`` ran successfully
+===========================================
+
+After launching the virtual machine, we should be able to connect to our
+instance using the default distro username.
+
+In this case the default username is ``ubuntu`` and the password we configured
+is ``password``.
+
+If you can log in using the configured password, it worked!
+
+If you couldn't log in, see
+:ref:`this page for debug information<qemu_debug_info>`.
+
+Check ``cloud-init`` status
+===========================
+
+Run the following command, which will allow us to check if ``cloud-init`` has
+finished running:
+
+.. code-block:: sh
+
+ $ cloud-init status --wait
+
+If you see ``status: done`` in the output, it succeeded!
+
+If you see a failed status, you'll want to check
+:file:`/var/log/cloud-init.log` for warning/error messages.
+
+Tear down
+=========
+
+In our main terminal, let's exit the QEMU shell using :kbd:`ctrl-a x` (that's
+:kbd:`ctrl` and :kbd:`a` simultaneously, followed by :kbd:`x`).
+
+In the second terminal, where the Python webserver is running, we can stop the
+server using (:kbd:`ctrl-c`).
+
+What's next?
+============
+
+In this tutorial, we configured the default user's password and ran
+``cloud-init`` inside our QEMU virtual machine.
+
+The full list of modules available can be found in
+:ref:`our modules documentation<modules>`.
+The documentation for each module contains examples of how to use it.
+
+You can also head over to the :ref:`examples page<yaml_examples>` for
+examples of more common use cases.
+
+.. _QEMU: https://www.qemu.org
+.. _install instructions: https://www.qemu.org/download/#linux
+.. _LTS: https://wiki.ubuntu.com/Releases