community.general/plugins/modules/proxmox.py

1739 lines
61 KiB
Python
Raw Normal View History

2020-03-09 09:11:07 +00:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
2020-03-09 09:11:07 +00:00
from __future__ import absolute_import, division, print_function
2020-03-09 09:11:07 +00:00
__metaclass__ = type
DOCUMENTATION = r"""
2020-03-09 09:11:07 +00:00
module: proxmox
2022-11-09 12:57:41 +00:00
short_description: Management of instances in Proxmox VE cluster
2020-03-09 09:11:07 +00:00
description:
- Allows you to create/delete/stop instances in Proxmox VE cluster.
- The module automatically detects containerization type (lxc for PVE 4, openvz for older).
- Since community.general 4.0.0 on, there are no more default values.
attributes:
check_mode:
support: none
diff_mode:
support: none
action_group:
version_added: 9.0.0
2020-03-09 09:11:07 +00:00
options:
password:
description:
- The instance root password.
type: str
2020-03-09 09:11:07 +00:00
hostname:
description:
- The instance hostname.
- Required only for O(state=present).
- Must be unique if vmid is not passed.
type: str
2020-03-09 09:11:07 +00:00
ostemplate:
description:
- The template for VM creating.
- Required only for O(state=present).
type: str
2020-03-09 09:11:07 +00:00
disk:
description:
- This option was previously described as "hard disk size in GB for instance" however several formats describing a lxc
mount are permitted.
- Older versions of Proxmox will accept a numeric value for size using the O(storage) parameter to automatically choose
which storage to allocate from, however new versions enforce the C(<STORAGE>:<SIZE>) syntax.
- Additional options are available by using some combination of the following key-value pairs as a comma-delimited list
C([volume=]<volume>
[,acl=<1|0>] [,mountoptions=<opt[;opt...] [,quota=<1|0>] [,replicate=<1|0>] [,ro=<1|0>] [,shared=<1|0>]
[,size=<DiskSize>]).
2021-08-31 05:10:10 +00:00
- See U(https://pve.proxmox.com/wiki/Linux_Container) for a full description.
- This option is mutually exclusive with O(disk_volume).
type: str
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
disk_volume:
description:
- Specify a hash/dictionary of the C(rootfs) disk.
- See U(https://pve.proxmox.com/wiki/Linux_Container#pct_mount_points) for a full description.
- This option is mutually exclusive with O(storage) and O(disk).
type: dict
version_added: 9.2.0
suboptions:
storage:
description:
- O(disk_volume.storage) is the storage identifier of the storage to use for the C(rootfs).
- Mutually exclusive with O(disk_volume.host_path).
type: str
volume:
description:
- O(disk_volume.volume) is the name of an existing volume.
- If not defined, the module will check if one exists. If not, a new volume will be created.
- If defined, the volume must exist under that name.
- Required only if O(disk_volume.storage) is defined, and mutually exclusive with O(disk_volume.host_path).
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
type: str
size:
description:
- O(disk_volume.size) is the size of the storage to use.
- The size is given in GiB.
- Required only if O(disk_volume.storage) is defined, and mutually exclusive with O(disk_volume.host_path).
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
type: int
host_path:
description:
- O(disk_volume.host_path) defines a bind or device path on the PVE host to use for the C(rootfs).
- Mutually exclusive with O(disk_volume.storage), O(disk_volume.volume), and O(disk_volume.size).
type: path
options:
description:
- O(disk_volume.options) is a dict of extra options.
- The value of any given option must be a string, for example V("1").
type: dict
2020-03-09 09:11:07 +00:00
cores:
description:
- Specify number of cores per socket.
type: int
2020-03-09 09:11:07 +00:00
cpus:
description:
- Number of allocated cpus for instance.
type: int
2020-03-09 09:11:07 +00:00
memory:
description:
- Memory size in MB for instance.
type: int
2020-03-09 09:11:07 +00:00
swap:
description:
- Swap memory size in MB for instance.
type: int
2020-03-09 09:11:07 +00:00
netif:
description:
- Specifies network interfaces for the container. As a hash/dictionary defining interfaces.
type: dict
features:
description:
- Specifies a list of features to be enabled. For valid options, see U(https://pve.proxmox.com/wiki/Linux_Container#pct_options).
- Some features require the use of a privileged container.
type: list
elements: str
version_added: 2.0.0
startup:
description:
- Specifies the startup order of the container.
- Use C(order=#) where C(#) is a non-negative number to define the general startup order. Shutdown in done with reverse
ordering.
- Use C(up=#) where C(#) is in seconds, to specify a delay to wait before the next VM is started.
- Use C(down=#) where C(#) is in seconds, to specify a delay to wait before the next VM is stopped.
type: list
elements: str
version_added: 8.5.0
2020-03-09 09:11:07 +00:00
mounts:
description:
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
- Specifies additional mounts (separate disks) for the container. As a hash/dictionary defining mount points as strings.
- This Option is mutually exclusive with O(mount_volumes).
type: dict
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
mount_volumes:
description:
- Specify additional mounts (separate disks) for the container. As a hash/dictionary defining mount points.
- See U(https://pve.proxmox.com/wiki/Linux_Container#pct_mount_points) for a full description.
- This Option is mutually exclusive with O(mounts).
type: list
elements: dict
version_added: 9.2.0
suboptions:
id:
description:
- O(mount_volumes[].id) is the identifier of the mount point written as C(mp[n]).
type: str
required: true
storage:
description:
- O(mount_volumes[].storage) is the storage identifier of the storage to use.
- Mutually exclusive with O(mount_volumes[].host_path).
type: str
volume:
description:
- O(mount_volumes[].volume) is the name of an existing volume.
- If not defined, the module will check if one exists. If not, a new volume will be created.
- If defined, the volume must exist under that name.
- Required only if O(mount_volumes[].storage) is defined and mutually exclusive with O(mount_volumes[].host_path).
type: str
size:
description:
- O(mount_volumes[].size) is the size of the storage to use.
- The size is given in GiB.
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
- Required only if O(mount_volumes[].storage) is defined and mutually exclusive with O(mount_volumes[].host_path).
type: int
host_path:
description:
- O(mount_volumes[].host_path) defines a bind or device path on the PVE host to use for the C(rootfs).
- Mutually exclusive with O(mount_volumes[].storage), O(mount_volumes[].volume), and O(mount_volumes[].size).
type: path
mountpoint:
description:
- O(mount_volumes[].mountpoint) is the mount point of the volume.
type: path
required: true
options:
description:
- O(mount_volumes[].options) is a dict of extra options.
- The value of any given option must be a string, for example V("1").
type: dict
2020-03-09 09:11:07 +00:00
ip_address:
description:
- Specifies the address the container will be assigned.
type: str
2020-03-09 09:11:07 +00:00
onboot:
description:
- Specifies whether a VM will be started during system bootup.
2020-03-09 09:11:07 +00:00
type: bool
storage:
description:
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
- Target storage.
- This option is mutually exclusive with O(disk_volume) and O(mount_volumes).
type: str
2020-03-09 09:11:07 +00:00
default: 'local'
ostype:
description:
- Specifies the C(ostype) of the LXC container.
- If set to V(auto), no C(ostype) will be provided on instance creation.
choices: ['auto', 'debian', 'devuan', 'ubuntu', 'centos', 'fedora', 'opensuse', 'archlinux', 'alpine', 'gentoo', 'nixos',
'unmanaged']
type: str
default: 'auto'
version_added: 8.1.0
2020-03-09 09:11:07 +00:00
cpuunits:
description:
- CPU weight for a VM.
type: int
2020-03-09 09:11:07 +00:00
nameserver:
description:
- Sets DNS server IP address for a container.
type: str
2020-03-09 09:11:07 +00:00
searchdomain:
description:
- Sets DNS search domain for a container.
type: str
tags:
description:
- List of tags to apply to the container.
- Tags must start with V([a-z0-9_]) followed by zero or more of the following characters V([a-z0-9_-+.]).
- Tags are only available in Proxmox 7+.
type: list
elements: str
version_added: 6.2.0
2020-03-09 09:11:07 +00:00
timeout:
description:
- Timeout for operations.
type: int
2020-03-09 09:11:07 +00:00
default: 30
update:
description:
- If V(true), the container will be updated with new values.
- The current default value of V(false) is deprecated and should will change to V(true) in community.general 11.0.0.
Please set O(update) explicitly to V(false) or V(true) to avoid surprises and get rid of the deprecation warning.
type: bool
version_added: 8.1.0
2020-03-09 09:11:07 +00:00
force:
description:
- Forcing operations.
- Can be used only with states V(present), V(stopped), V(restarted).
- With O(state=present) force option allow to overwrite existing container.
- With states V(stopped), V(restarted) allow to force stop instance.
2020-03-09 09:11:07 +00:00
type: bool
default: false
purge:
description:
- Remove container from all related configurations.
- For example backup jobs, replication jobs, or HA.
- Related ACLs and Firewall entries will always be removed.
- Used with O(state=absent).
type: bool
default: false
version_added: 2.3.0
2020-03-09 09:11:07 +00:00
state:
description:
- Indicate desired state of the instance.
- V(template) was added in community.general 8.1.0.
type: str
choices: ['present', 'started', 'absent', 'stopped', 'restarted', 'template']
2020-03-09 09:11:07 +00:00
default: present
pubkey:
description:
- Public key to add to /root/.ssh/authorized_keys. This was added on Proxmox 4.2, it is ignored for earlier versions.
type: str
2020-03-09 09:11:07 +00:00
unprivileged:
description:
- Indicate if the container should be unprivileged.
- The default change to V(true) in community.general 7.0.0. It used to be V(false) before.
2020-03-09 09:11:07 +00:00
type: bool
default: true
description:
description:
- Specify the description for the container. Only used on the configuration web interface.
- This is saved as a comment inside the configuration file.
type: str
version_added: '0.2.0'
hookscript:
description:
- Script that will be executed during various steps in the containers lifetime.
type: str
version_added: '0.2.0'
timezone:
description:
- Timezone used by the container, accepts values like V(Europe/Paris).
- The special value V(host) configures the same timezone used by Proxmox host.
type: str
version_added: '7.1.0'
clone:
description:
- ID of the container to be cloned.
- O(description), O(hostname), and O(pool) will be copied from the cloned container if not specified.
- The type of clone created is defined by the O(clone_type) parameter.
- This operator is only supported for Proxmox clusters that use LXC containerization (PVE version >= 4).
type: int
version_added: 4.3.0
clone_type:
description:
- Type of the clone created.
- V(full) creates a full clone, and O(storage) must be specified.
- V(linked) creates a linked clone, and the cloned container must be a template container.
- V(opportunistic) creates a linked clone if the cloned container is a template container, and a full clone if not.
O(storage) may be specified, if not it will fall back to the default.
type: str
choices: ['full', 'linked', 'opportunistic']
default: opportunistic
version_added: 4.3.0
2020-03-09 09:11:07 +00:00
author: Sergei Antipov (@UnderGreen)
seealso:
- module: community.general.proxmox_vm_info
extends_documentation_fragment:
- community.general.proxmox.actiongroup_proxmox
- community.general.proxmox.documentation
- community.general.proxmox.selection
- community.general.attributes
"""
2020-03-09 09:11:07 +00:00
EXAMPLES = r"""
- name: Create new container with minimal options
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
- name: Create new container with minimal options specifying disk storage location and size
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
disk: 'local-lvm:20'
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
- name: Create new container with minimal options specifying disk storage location and size via disk_volume
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
disk_volume:
storage: local
size: 20
- name: Create new container with hookscript and description
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
hookscript: 'local:snippets/vm_hook.sh'
description: created with ansible
- name: Create new container automatically selecting the next available vmid.
community.general.proxmox:
2020-03-09 09:11:07 +00:00
node: 'uk-mc02'
api_user: 'root@pam'
api_password: '1q2w3e'
api_host: 'node1'
password: '123456'
hostname: 'example.org'
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
- name: Create new container with minimal options with force(it will rewrite existing container)
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
force: true
2020-03-09 09:11:07 +00:00
- name: Create new container with minimal options use environment PROXMOX_PASSWORD variable(you should export it before)
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
- name: Create new container with minimal options defining network interface with dhcp
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
netif:
net0: "name=eth0,ip=dhcp,ip6=dhcp,bridge=vmbr0"
2020-03-09 09:11:07 +00:00
- name: Create new container with minimal options defining network interface with static ip
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
netif:
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.2/24,bridge=vmbr0"
- name: Create new container with more options defining network interface with static ip4 and ip6 with vlan-tag and mtu
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
netif:
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.2/24,ip6=fe80::1227/64,gw6=fe80::1,bridge=vmbr0,firewall=1,tag=934,mtu=1500"
2020-03-09 09:11:07 +00:00
- name: Create new container with minimal options defining a mount with 8GB
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
mounts:
mp0: "local:8,mp=/mnt/test/"
2020-03-09 09:11:07 +00:00
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
- name: Create new container with minimal options defining a mount with 8GB using mount_volumes
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
mount_volumes:
- id: mp0
storage: local
size: 8
mountpoint: /mnt/test
- name: Create new container with minimal options defining a cpu core limit
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
2020-03-09 09:11:07 +00:00
cores: 2
- name: Create new container with minimal options and same timezone as proxmox host
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
timezone: host
- name: Create a new container with nesting enabled and allows the use of CIFS/NFS inside the container.
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
password: 123456
hostname: example.org
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
features:
- nesting=1
- mount=cifs,nfs
- name: >
Create a linked clone of the template container with id 100. The newly created container with be a
linked clone, because no storage parameter is defined
community.general.proxmox:
vmid: 201
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
clone: 100
hostname: clone.example.org
- name: Create a full clone of the container with id 100
community.general.proxmox:
vmid: 201
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
clone: 100
hostname: clone.example.org
storage: local
- name: Update container configuration
community.general.proxmox:
vmid: 100
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
netif:
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.3/24,bridge=vmbr0"
update: true
- name: Start container
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: started
- name: >
Start container with mount. You should enter a 90-second timeout because servers
with additional disks take longer to boot
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: started
timeout: 90
- name: Stop container
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: stopped
- name: Stop container with force
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
force: true
2020-03-09 09:11:07 +00:00
state: stopped
- name: Restart container(stopped or mounted container you can't restart)
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: restarted
- name: Convert container to template
community.general.proxmox:
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: template
- name: Convert container to template (stop container if running)
community.general.proxmox:
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: template
force: true
- name: Remove container
community.general.proxmox:
2020-03-09 09:11:07 +00:00
vmid: 100
api_user: root@pam
api_password: 1q2w3e
api_host: node1
state: absent
"""
2020-03-09 09:11:07 +00:00
import re
2020-03-09 09:11:07 +00:00
import time
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.general.plugins.module_utils.proxmox import (
ProxmoxAnsible,
ansible_to_proxmox_bool,
proxmox_auth_argument_spec,
)
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
2020-03-09 09:11:07 +00:00
def get_proxmox_args():
return dict(
vmid=dict(type="int", required=False),
node=dict(),
pool=dict(),
password=dict(no_log=True),
hostname=dict(),
ostemplate=dict(),
disk=dict(type="str"),
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
disk_volume=dict(
type="dict",
options=dict(
storage=dict(type="str"),
volume=dict(type="str"),
size=dict(type="int"),
host_path=dict(type="path"),
options=dict(type="dict"),
),
required_together=[("storage", "size")],
required_by={
"volume": ("storage", "size"),
},
mutually_exclusive=[
("host_path", "storage"),
("host_path", "volume"),
("host_path", "size"),
],
),
cores=dict(type="int"),
cpus=dict(type="int"),
memory=dict(type="int"),
swap=dict(type="int"),
netif=dict(type="dict"),
mounts=dict(type="dict"),
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
mount_volumes=dict(
type="list",
elements="dict",
options=dict(
id=(dict(type="str", required=True)),
storage=dict(type="str"),
volume=dict(type="str"),
size=dict(type="int"),
host_path=dict(type="path"),
mountpoint=dict(type="path", required=True),
options=dict(type="dict"),
),
required_together=[("storage", "size")],
required_by={
"volume": ("storage", "size"),
},
mutually_exclusive=[
("host_path", "storage"),
("host_path", "volume"),
("host_path", "size"),
],
),
ip_address=dict(),
ostype=dict(
default="auto",
choices=[
"auto",
"debian",
"devuan",
"ubuntu",
"centos",
"fedora",
"opensuse",
"archlinux",
"alpine",
"gentoo",
"nixos",
"unmanaged",
],
),
onboot=dict(type="bool"),
features=dict(type="list", elements="str"),
startup=dict(type="list", elements="str"),
storage=dict(default="local"),
cpuunits=dict(type="int"),
nameserver=dict(),
searchdomain=dict(),
timeout=dict(type="int", default=30),
update=dict(type="bool"),
force=dict(type="bool", default=False),
purge=dict(type="bool", default=False),
state=dict(
default="present",
choices=[
"present",
"absent",
"stopped",
"started",
"restarted",
"template",
],
),
pubkey=dict(type="str"),
unprivileged=dict(type="bool", default=True),
description=dict(type="str"),
hookscript=dict(type="str"),
timezone=dict(type="str"),
clone=dict(type="int"),
clone_type=dict(
default="opportunistic", choices=["full", "linked", "opportunistic"]
),
tags=dict(type="list", elements="str"),
)
def get_ansible_module():
module_args = proxmox_auth_argument_spec()
module_args.update(get_proxmox_args())
return AnsibleModule(
argument_spec=module_args,
required_if=[
("state", "present", ["node", "hostname"]),
# Require one of clone, ostemplate, or update.
# Together with mutually_exclusive this ensures that we either
# clone a container or create a new one from a template file.
("state", "present", ("clone", "ostemplate", "update"), True),
],
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
required_together=[("api_token_id", "api_token_secret")],
required_one_of=[
("api_password", "api_token_id"),
("vmid", "hostname"),
],
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
mutually_exclusive=[
# Creating a new container is done either by cloning an existing one, or based on a template.
("clone", "ostemplate", "update"),
("disk", "disk_volume"),
("storage", "disk_volume"),
Improve Proxmox volume handling (#8542) * proxmox: basic linting using black via trunk.io * proxmox: refactor mount handling (#8407) - make mount creation idempotent: Mounts created using the special syntax "<storage>:<size>" no longer create a new volume each time - add new keys for easier mount creation & management * proxmox: add changelog fragment * proxmox(fix): fix occasional syntax error * Update changelogs/fragments/8542-fix-proxmox-volume-handling.yml Link to pull request Co-authored-by: Felix Fontein <felix@fontein.de> * Update documentation - Fix options defined as values - Document mutual exclusivity - Fix option hierarchy - Add version_added tag * Revert "proxmox: basic linting" This reverts commit ca7214f60e7b517fa681089ee55ab0a1fed44fd4. * proxmox: Fix documentation * Fix list identifier in documentation * pass volume options as dict instead of list * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/proxmox.py Update documentation wording Co-authored-by: Felix Fontein <felix@fontein.de> * proxmox: ensure values of `disk_volume` and `mount_volumes.*` dicts are strings * proxmox(fix): correct indentation * Apply suggestions from code review: punctuation Add suggested punctuation to documentation Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/proxmox.py: vol_string building Accept suggested review change Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * proxmox: Use better string check and conversion --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-07-14 10:07:05 +00:00
("mounts", "mount_volumes"),
],
2020-03-09 09:11:07 +00:00
)
class ProxmoxLxcAnsible(ProxmoxAnsible):
MINIMUM_VERSIONS = {
"disk_volume": "5.0",
"mount_volumes": "5.0",
"tags": "6.1",
"timezone": "6.3",
}
2020-03-09 09:11:07 +00:00
def __init__(self, module):
super(ProxmoxLxcAnsible, self).__init__(module)
self.VZ_TYPE = "openvz" if self.version() < LooseVersion("4.0") else "lxc"
self.params = self.module.params
def run(self):
self.check_supported_features()
state = self.params.get("state")
vmid = self.params.get("vmid")
hostname = self.params.get("hostname")
if not vmid and not hostname:
self.module.fail_json(msg="Either VMID or hostname must be provided.")
if state == "present":
self.lxc_present(
vmid,
hostname,
node=self.params.get("node"),
update=self.params.get("update"),
force=self.params.get("force"),
)
elif state == "absent":
self.lxc_absent(
vmid,
hostname,
node=self.params.get("node"),
timeout=self.params.get("timeout"),
purge=self.params.get("purge"),
)
elif state == "started":
self.lxc_started(
vmid,
hostname,
node=self.params.get("node"),
timeout=self.params.get("timeout"),
)
elif state == "stopped":
self.lxc_stopped(
vmid,
hostname,
node=self.params.get("node"),
timeout=self.params.get("timeout"),
force=self.params.get("force"),
)
elif state == "restarted":
self.lxc_restarted(
vmid,
hostname,
node=self.params.get("node"),
timeout=self.params.get("timeout"),
force=self.params.get("force"),
)
elif state == "template":
self.lxc_to_template(
vmid,
hostname,
node=self.params.get("node"),
timeout=self.params.get("timeout"),
force=self.params.get("force"),
)
2020-03-09 09:11:07 +00:00
def lxc_present(self, vmid, hostname, node, update, force):
2020-03-09 09:11:07 +00:00
try:
lxc = self.get_lxc_resource(vmid, hostname)
vmid = vmid or lxc["id"].split("/")[-1]
node = node or lxc["node"]
except LookupError:
lxc = None
vmid = vmid or self.get_nextvmid()
if node is None:
raise ValueError(
"Argument 'node' is None, but should be found from VMID/hostname or provided."
)
2020-03-09 09:11:07 +00:00
# check if the container exists already
if lxc is not None:
if update is None:
# TODO: Remove deprecation warning in version 11.0.0
self.module.deprecate(
msg="The default value of false for 'update' has been deprecated and will be changed to true in version 11.0.0.",
version="11.0.0",
collection_name="community.general",
)
update = False
if update:
# Update it if we should
identifier = self.format_vm_identifier(vmid, hostname)
self.update_lxc_instance(
vmid,
node,
cores=self.params.get("cores"),
cpus=self.params.get("cpus"),
cpuunits=self.params.get("cpuunits"),
description=self.params.get("description"),
disk=self.params.get("disk"),
disk_volume=self.params.get("disk_volume"),
features=self.params.get("features"),
hookscript=self.params.get("hookscript"),
hostname=self.params.get("hostname"),
ip_address=self.params.get("ip_address"),
memory=self.params.get("memory"),
mounts=self.params.get("mounts"),
mount_volumes=self.params.get("mount_volumes"),
nameserver=self.params.get("nameserver"),
netif=self.params.get("netif"),
onboot=ansible_to_proxmox_bool(self.params.get("onboot")),
searchdomain=self.params.get("searchdomain"),
startup=self.params.get("startup"),
swap=self.params.get("swap"),
tags=self.params.get("tags"),
timezone=self.params.get("timezone"),
)
self.module.exit_json(
changed=True, vmid=vmid, msg="VM %s has been updated." % identifier
)
elif not force:
# We're done if it shouldn't be forcefully created
identifier = self.format_vm_identifier(vmid, lxc["name"])
self.module.exit_json(
changed=False, vmid=vmid, msg="VM %s already exists." % identifier
)
self.module.debug(
"VM %s already exists, but we don't update and instead forcefully recreate it."
% identifier
)
self.new_lxc_instance(
vmid,
hostname,
node=self.params.get("node"),
clone_from=self.params.get("clone"),
ostemplate=self.params.get("ostemplate"),
force=force,
)
2020-03-09 09:11:07 +00:00
def lxc_absent(self, vmid, hostname, node, timeout, purge):
2020-03-09 09:11:07 +00:00
try:
lxc = self.get_lxc_resource(vmid, hostname)
except LookupError:
identifier = self.format_vm_identifier(vmid, hostname)
self.module.exit_json(
changed=False, vmid=vmid, msg="VM %s is already absent." % (identifier)
)
vmid = vmid or lxc["id"].split("/")[-1]
node = node or lxc["node"]
lxc_status = self.get_lxc_status(vmid, node)
identifier = self.format_vm_identifier(vmid, hostname)
if lxc_status == "running":
self.module.exit_json(
changed=False,
vmid=vmid,
msg="VM %s is running. Stop it before deletion." % identifier,
)
if lxc_status == "mounted":
self.module.exit_json(
changed=False,
vmid=vmid,
msg="VM %s is mounted. Stop it with force option before deletion."
% identifier,
)
self.remove_lxc_instance(vmid, node, timeout, purge)
self.module.exit_json(
changed=True, vmid=vmid, msg="VM %s removed." % identifier
)
def lxc_started(self, vmid, hostname, node, timeout):
lxc = self.get_lxc_resource(vmid, hostname)
vmid = vmid or lxc["id"].split("/")[-1]
hostname = hostname or lxc["name"]
identifier = self.format_vm_identifier(vmid, hostname)
node = node or lxc["node"]
lxc_status = self.get_lxc_status(vmid, lxc["node"])
if lxc_status == "running":
self.module.exit_json(
changed=False, vmid=vmid, msg="VM %s is already running." % identifier
)
self.start_lxc_instance(vmid, node, timeout)
self.module.exit_json(
changed=True, vmid=vmid, msg="VM %s started." % identifier
)
def lxc_stopped(self, vmid, hostname, node, timeout, force):
lxc = self.get_lxc_resource(vmid, hostname)
vmid = vmid or lxc["id"].split("/")[-1]
hostname = hostname or lxc["name"]
identifier = self.format_vm_identifier(vmid, hostname)
node = node or lxc["node"]
lxc_status = self.get_lxc_status(vmid, node)
if lxc_status == "mounted":
if force:
self.umount_lxc_instance(vmid, hostname, timeout)
else:
self.module.exit_json(
changed=False,
vmid=vmid,
msg="VM %s is already stopped, but mounted. Use force option to umount it."
% identifier,
)
if lxc_status == "stopped":
self.module.exit_json(
changed=False, vmid=vmid, msg="VM %s is already stopped." % identifier
)
self.stop_lxc_instance(vmid, node, timeout, force)
self.module.exit_json(
changed=True, vmid=vmid, msg="VM %s stopped." % identifier
)
2020-03-09 09:11:07 +00:00
def lxc_restarted(self, vmid, hostname, node, timeout, force):
lxc = self.get_lxc_resource(vmid, hostname)
vmid = vmid or lxc["id"].split("/")[-1]
hostname = hostname or lxc["name"]
node = node or lxc["node"]
identifier = self.format_vm_identifier(vmid, hostname)
lxc_status = self.get_lxc_status(vmid, node)
if lxc_status in ["stopped", "mounted"]:
self.module.exit_json(
changed=False, vmid=vmid, msg="VM %s is not running." % identifier
)
self.stop_lxc_instance(vmid, node, timeout, force)
self.start_lxc_instance(vmid, node, timeout)
self.module.exit_json(
changed=True, vmid=vmid, msg="VM %s is restarted." % identifier
)
def lxc_to_template(self, vmid, hostname, node, timeout, force):
lxc = self.get_lxc_resource(vmid, hostname)
vmid = vmid or lxc["id"].split("/")[-1]
hostname = hostname or lxc["name"]
node = node or lxc["node"]
identifier = self.format_vm_identifier(vmid, hostname)
if self.is_template_container(node, vmid):
self.module.exit_json(
changed=False,
vmid=vmid,
msg="VM %s is already a template." % identifier,
)
lxc_status = self.get_lxc_status(vmid, node)
if lxc_status == "running" and force:
self.stop_instance(vmid, hostname, node, timeout, force)
proxmox_node = self.proxmox_api.nodes(node)
getattr(proxmox_node, self.VZ_TYPE)(vmid).template.post()
self.module.exit_json(
changed=True, vmid=vmid, msg="VM %s converted to template." % identifier
)
def update_lxc_instance(self, vmid, node, **kwargs):
if self.VZ_TYPE != "lxc":
self.module.fail_json(
msg="Updating LXC containers is only supported for LXC-enabled clusters in PVE 4.0 and above."
)
kwargs = {k: v for k, v in kwargs.items() if v is not None}
self.validate_tags(kwargs.get("tags", []))
if "features" in kwargs:
kwargs["features"] = ",".join(kwargs.pop("features"))
if "startup" in kwargs:
kwargs["startup"] = ",".join(kwargs.pop("startup"))
disk_updates = self.process_disk_keys(
vmid,
node,
kwargs.pop("disk", None),
kwargs.pop("disk_volume", None),
)
mounts_updates = self.process_mount_keys(
vmid,
node,
kwargs.pop("mounts", None),
kwargs.pop("mount_volumes", None),
)
kwargs.update(disk_updates)
kwargs.update(mounts_updates)
if "cpus" in kwargs:
kwargs["cpulimit"] = kwargs.pop("cpus")
if "netif" in kwargs:
kwargs.update(kwargs.pop("netif"))
if "pubkey" in kwargs:
pubkey = kwargs.pop("pubkey")
if self.version() >= LooseVersion("4.2"):
kwargs["ssh-public-keys"] = pubkey
else:
self.module.warn(
"'pubkey' is not supported for PVE 4.1 and below. Ignoring keyword."
)
# fetch current config
proxmox_node = self.proxmox_api.nodes(node)
current_config = getattr(proxmox_node, self.VZ_TYPE)(vmid).config.get()
# create diff between the current and requested config
diff = {}
for arg, value in kwargs.items():
# if the arg isn't in the current config, it needs to be added
if arg not in current_config:
diff[arg] = value
elif isinstance(value, str):
# compare all string values as lists as some of them may be lists separated by commas. order doesn't matter
current_values = current_config[arg].split(",")
requested_values = value.split(",")
for new_value in requested_values:
if new_value not in current_values:
diff[arg] = value
break
# if it's not a list (or string) just compare the values
# some types don't match with the API, so force a string comparison
elif str(value) != str(current_config[arg]):
diff[arg] = value
if not diff:
self.module.exit_json(
changed=False, vmid=vmid, msg="Container config is already up to date."
)
# update the config
getattr(proxmox_node, self.VZ_TYPE)(vmid).config.put(
vmid=vmid, node=node, **kwargs
)
def new_lxc_instance(self, vmid, hostname, node, clone_from, ostemplate, force):
identifier = self.format_vm_identifier(vmid, hostname)
if clone_from is not None:
self.clone_lxc_instance(
vmid,
node,
clone_from,
clone_type=self.params.get("clone_type"),
timeout=self.params.get("timeout"),
description=self.params.get("description"),
hostname=hostname,
pool=self.params.get("pool"),
storage=self.params.get("storage"),
)
self.module.exit_json(
changed=True,
vmid=vmid,
msg="Cloned VM %s from %d" % (identifier, clone_from),
)
if ostemplate is not None:
self.create_lxc_instance(
vmid,
node,
ostemplate,
timeout=self.params.get("timeout"),
cores=self.params.get("cores"),
cpus=self.params.get("cpus"),
cpuunits=self.params.get("cpuunits"),
description=self.params.get("description"),
disk=self.params.get("disk"),
disk_volume=self.params.get("disk_volume"),
features=self.params.get("features"),
force=ansible_to_proxmox_bool(force),
hookscript=self.params.get("hookscript"),
hostname=hostname,
ip_address=self.params.get("ip_address"),
memory=self.params.get("memory"),
mounts=self.params.get("mounts"),
mount_volumes=self.params.get("mount_volumes"),
nameserver=self.params.get("nameserver"),
netif=self.params.get("netif"),
onboot=ansible_to_proxmox_bool(self.params.get("onboot")),
ostype=self.params.get("ostype"),
password=self.params.get("password"),
pool=self.params.get("pool"),
pubkey=self.params.get("pubkey"),
searchdomain=self.params.get("searchdomain"),
startup=self.params.get("startup"),
storage=self.params.get("storage"),
swap=self.params.get("swap"),
tags=self.params.get("tags"),
timezone=self.params.get("timezone"),
unprivileged=ansible_to_proxmox_bool(self.params.get("unprivileged")),
)
self.module.exit_json(
changed=True,
vmid=vmid,
msg="Created VM %s from template %s" % (identifier, ostemplate),
)
self.module.fail_json(
vmid=vmid,
msg="VM %s does not exist but neither clone nor ostemplate were specified!"
% identifier,
)
def create_lxc_instance(self, vmid, node, ostemplate, timeout, **kwargs):
template_store = ostemplate.split(":")[0]
if not self.content_check(node, ostemplate, template_store):
self.module.fail_json(
vmid=vmid,
msg="ostemplate %s does not exist on node %s and storage %s."
% (ostemplate, node, template_store),
)
disk_updates = self.process_disk_keys(
vmid,
node,
kwargs.pop("disk"),
kwargs.pop("disk_volume"),
)
mounts_updates = self.process_mount_keys(
vmid,
node,
kwargs.pop("mounts"),
kwargs.pop("mount_volumes"),
)
kwargs.update(disk_updates)
kwargs.update(mounts_updates)
# Remove empty values from kwargs
kwargs = {k: v for k, v in kwargs.items() if v is not None}
if "features" in kwargs:
kwargs["features"] = ",".join(kwargs.pop("features"))
if "startup" in kwargs:
kwargs["startup"] = ",".join(kwargs.pop("startup"))
self.validate_tags(kwargs.get("tags", []))
if self.VZ_TYPE == "lxc":
if "cpus" in kwargs:
kwargs["cpuunits"] = kwargs.pop("cpus")
kwargs.update(kwargs.pop("netif", {}))
else:
if "mount_volumes" in kwargs:
kwargs.pop("mount_volumes")
self.module.warn(
"'mount_volumes' is not supported for non-LXC clusters. Ignoring keyword."
)
if "pubkey" in kwargs:
pubkey = kwargs.pop("pubkey")
if self.version() >= LooseVersion("4.2"):
kwargs["ssh-public-keys"] = pubkey
else:
self.module.warn(
"'pubkey' is not supported for PVE 4.1 and below. Ignoring keyword."
)
if kwargs.get("ostype") == "auto":
kwargs.pop("ostype")
proxmox_node = self.proxmox_api.nodes(node)
taskid = getattr(proxmox_node, self.VZ_TYPE).create(
vmid=vmid, ostemplate=ostemplate, **kwargs
)
self.handle_api_timeout(
vmid,
node,
taskid,
timeout,
"Reached timeout while waiting for creation of VM %s from template %s"
% (vmid, ostemplate),
)
def clone_lxc_instance(self, vmid, node, clone_from, clone_type, timeout, **kwargs):
if self.VZ_TYPE != "lxc":
self.module.fail_json(
msg="Cloning is only supported for LXC-enabled clusters in PVE 4.0 and above."
)
# Remove empty values from kwargs
kwargs = {k: v for k, v in kwargs.items() if v is not None}
target_is_template = self.is_template_container(node, clone_from)
# By default, create a full copy only when the cloned container is not a template.
create_full_copy = not target_is_template
# Only accept parameters that are compatible with the clone endpoint.
valid_clone_parameters = ["hostname", "pool", "description"]
if "storage" not in kwargs and target_is_template:
# Cloning a template, so create a full copy instead of a linked copy
create_full_copy = True
elif "storage" not in kwargs and not target_is_template:
self.module.fail_json(
changed=False,
msg="Clone target container is not a template, storage needs to be specified.",
)
if clone_type == "linked" and not target_is_template:
self.module.fail_json(
changed=False,
msg="Cloning type 'linked' is only supported for template containers.",
)
elif clone_type == "opportunistic" and not target_is_template:
# Cloned container is not a template, so we need our 'storage' parameter
valid_clone_parameters.append("storage")
elif clone_type == "full":
create_full_copy = True
valid_clone_parameters.append("storage")
clone_parameters = {}
clone_parameters["full"] = ansible_to_proxmox_bool(create_full_copy)
for param in valid_clone_parameters:
if param in kwargs:
clone_parameters[param] = kwargs[param]
proxmox_node = self.proxmox_api.nodes(node)
taskid = getattr(proxmox_node, self.VZ_TYPE)(clone_from).clone.post(
newid=vmid, **clone_parameters
)
self.handle_api_timeout(
vmid,
node,
taskid,
timeout,
timeout_msg="Reached timeout while waiting for VM to clone.",
)
def start_lxc_instance(self, vmid, node, timeout):
proxmox_node = self.proxmox_api.nodes(node)
taskid = getattr(proxmox_node, self.VZ_TYPE)(vmid).status.start.post()
self.handle_api_timeout(
vmid,
node,
taskid,
timeout,
timeout_msg="Reached timeout while waiting for VM to start.",
)
def stop_lxc_instance(self, vmid, node, timeout, force):
stop_params = {}
if force:
stop_params["forceStop"] = 1
proxmox_node = self.proxmox_api.nodes(node)
taskid = getattr(proxmox_node, self.VZ_TYPE)(vmid).status.shutdown.post(
**stop_params
)
self.handle_api_timeout(
vmid,
node,
taskid,
timeout,
timeout_msg="Reached timeout while waiting for VM to stop.",
)
def umount_lxc_instance(self, vmid, node, timeout):
proxmox_node = self.proxmox_api.nodes(node)
taskid = getattr(proxmox_node, self.VZ_TYPE)(vmid).status.unmount.post()
self.handle_api_timeout(
vmid,
node,
taskid,
timeout,
timeout_msg="Reached timeout while waiting for VM to be unmounted.",
)
def remove_lxc_instance(self, vmid, node, timeout, purge):
delete_params = {}
if purge:
delete_params["purge"] = 1
proxmox_node = self.proxmox_api.nodes(node)
taskid = getattr(proxmox_node, self.VZ_TYPE).delete(vmid, **delete_params)
self.handle_api_timeout(
vmid,
node,
taskid,
timeout,
timeout_msg="Reached timeout while waiting for VM to be removed.",
)
def process_disk_keys(self, vmid, node, disk, disk_volume):
"""
Process disk keys and return a formatted disk volume with the `rootfs` key.
Args:
vmid (int): VM identifier.
node (str): Node identifier.
disk (str, optional): Disk key in the format 'storage:volume'. Defaults to None.
disk_volume (Dict[str, Any], optional): Disk volume data. Defaults to None.
Returns:
Dict[str, str]: Formatted disk volume with the `rootfs` or `disk` key (depending on the `VZ_TYPE`), or an empty dict if no disk volume is specified.
"""
if disk is None and disk_volume is None:
return {}
disk_dict = {}
if disk is not None:
if disk.isdigit():
disk_dict["rootfs"] = disk
else:
disk_volume = self.parse_disk_string(disk)
if disk_volume is not None:
disk_dict = self.build_volume(vmid, node, key="rootfs", **disk_volume)
if self.VZ_TYPE != "lxc":
disk_dict["disk"] = disk_dict.pop("rootfs")
return disk_dict
def process_mount_keys(self, vmid, node, mounts, mount_volumes):
"""
Process mount keys and return a formatted mount volumes with the `mp[n]` keys.
Args:
vmid (str): VM identifier.
node (str): Node identifier.
mounts (str, optional): Mount key in the format 'pool:volume'. Defaults to None.
mount_volumes (Dict[str, Any], optional): Mount volume data. Defaults to None.
Returns:
Dict[str, str]: Formatted mount volumes with the `mp[n]` keys, or an empty dict if no mount volumes are specified.
"""
if mounts is not None:
mount_volumes = []
for mount_key, mount_string in mounts.items():
mount_config = self.parse_disk_string(mount_string)
mount_volumes.append(dict(id=mount_key, **mount_config))
elif mount_volumes is None or mount_volumes == []:
return {}
mounts_dict = {}
for mount_config in mount_volumes:
mount_key = mount_config.pop("id")
mount_dict = self.build_volume(vmid, node, key=mount_key, **mount_config)
mounts_dict.update(mount_dict)
return mounts_dict
def parse_disk_string(self, disk_string):
"""
Parse a disk string and return a dictionary with the disk details.
Args:
disk_string (str): Disk string.
Returns:
Dict[str, Any]: Disk details.
Note: Below are some example disk strings that this function MUST be able to parse:
"acl=0,thin1:base-100-disk-1,size=8G"
"thin1:10,backup=0"
"local:20"
"local-lvm:0.50"
"tmp-dir:300/subvol-300-disk-0.subvol,acl=1,size=0T"
"tmplog-dir:300/vm-300-disk-0.raw,mp=/var/log,mountoptions=noatime,size=32M"
"volume=local-lvm:base-100-disk-1,size=20G"
"/mnt/bindmounts/shared,mp=/shared"
"volume=/dev/USB01,mp=/mnt/usb01"
"""
args = disk_string.split(",")
# If the volume is not explicitly defined but implicit by only passing a key,
# add the "volume=" key prefix for ease of parsing.
args = ["volume=" + arg if "=" not in arg else arg for arg in args]
# Then create a dictionary from the arguments
disk_kwargs = dict(map(lambda item: item.split("="), args))
VOLUME_PATTERN = r"""(?x)
^
(?:
(?:
(?P<storage>[\w\-.]+):
(?:
(?P<size>\d+\.?\d*)|
(?P<volume>[^,\s]+)
)
)|
(?P<host_path>[^,\s]+)
)
$
"""
# DISCLAIMER:
# There are two things called a "volume":
# 1. The "volume" key which describes the storage volume, device or directory to mount into the container.
# 2. The storage volume of a storage-backed mount point in the PVE storage sub system.
# In this section, we parse the "volume" key and check which type of mount point we are dealing with.
pattern = re.compile(VOLUME_PATTERN)
volume_string = disk_kwargs.pop("volume")
match = pattern.match(volume_string)
if match is None:
raise ValueError(("Invalid volume string: %s", volume_string))
match_dict = match.groupdict()
match_dict = {k: v for k, v in match_dict.items() if v is not None}
if "storage" in match_dict and "volume" in match_dict:
disk_kwargs["storage"] = match_dict["storage"]
disk_kwargs["volume"] = match_dict["volume"]
elif "storage" in match_dict and "size" in match_dict:
disk_kwargs["storage"] = match_dict["storage"]
disk_kwargs["size"] = match_dict["size"]
elif "host_path" in match_dict:
disk_kwargs["host_path"] = match_dict["host_path"]
# Pattern matching only available in Python 3.10+
# TODO: Uncomment the following code once only Python 3.10+ is supported
# match match_dict:
# case {"storage": storage, "volume": volume}:
# disk_kwargs["storage"] = storage
# disk_kwargs["volume"] = volume
# case {"storage": storage, "size": size}:
# disk_kwargs["storage"] = storage
# disk_kwargs["size"] = size
# case {"host_path": host_path}:
# disk_kwargs["host_path"] = host_path
return disk_kwargs
def build_volume(self, vmid, node, key, storage=None, volume=None, host_path=None, size=None, mountpoint=None, options=None, **kwargs):
"""
Build a volume string for the specified VM.
Args:
vmid (str): The VM ID.
node (str): The node where the VM resides.
key (str): The key for the volume in the VM's config.
storage (str, optional): The storage pool where the volume resides. Defaults to None.
volume (str, optional): The name of the volume. Defaults to None.
host_path (str, optional): The host path to mount. Defaults to None.
size (str | int, optional): The size of the volume in GiB. Defaults to None.
mountpoint (str, optional): The mountpoint for the volume. Defaults to None.
options (Dict[str, Any], optional): Additional options for the volume. Defaults to None.
**kwargs: Additional keyword arguments.
Returns:
Dict[str, str]: The built volume string in the format {'volume_key': 'volume_string'}.
Note: Further documentation can be found in the proxmox-api documentation: https://pve.proxmox.com/wiki/Linux_Container#pct_mount_points
Note: To build a valid volume string, we need ONE of the following:
A volume name, storage name, and size
Only a storage name and size (to create a new volume or assign the volume automatically)
A host directory to mount into the container
"""
if isinstance(size, int):
size = str(size)
if size is not None and isfloat(size):
size += "G" # default to GiB
# Handle volume checks/creation
# TODO: Change the code below to pattern matching once only Python 3.10+ is supported
# 1. Check if defined volume exists
if volume is not None:
storage_content = self.get_storage_content(node, storage, vmid=vmid)
vol_ids = [vol["volid"] for vol in storage_content]
volid = "{storage}:{volume}".format(storage=storage, volume=volume)
if volid not in vol_ids:
self.module.fail_json(
changed=False,
msg="Storage {storage} does not contain volume {volume}".format(
storage=storage,
volume=volume,
),
)
vol_string = "{storage}:{volume},size={size}".format(
storage=storage, volume=volume, size=size
)
# 2. If volume not defined (but storage is), check if it exists
elif storage is not None:
proxmox_node = self.proxmox_api.nodes(
node
) # The node must exist, but not the LXC
try:
vol = proxmox_node.lxc(vmid).get("config").get(key)
volume = self.parse_disk_string(vol).get("volume")
vol_string = "{storage}:{volume},size={size}".format(
storage=storage, volume=volume, size=size
)
# If not, we have proxmox create one using the special syntax
except Exception:
if size is None:
raise ValueError(
"Size must be provided for storage-backed volume creation."
)
elif size.endswith("G"):
size = size.rstrip("G")
vol_string = "{storage}:{size}".format(storage=storage, size=size)
2020-03-09 09:11:07 +00:00
else:
raise ValueError(
"Size must be provided in GiB for storage-backed volume creation. Convert it to GiB or allocate a new storage manually."
)
# 3. If we have a host_path, we don't have storage, a volume, or a size
# Then we don't have to do anything, just build and return the vol_string
elif host_path is not None:
vol_string = ""
else:
raise ValueError(
"Could not build a valid volume string. One of volume, storage, or host_path must be provided."
)
2020-03-09 09:11:07 +00:00
if host_path is not None:
vol_string += "," + host_path
2020-03-09 09:11:07 +00:00
if mountpoint is not None:
vol_string += ",mp={}".format(mountpoint)
2020-03-09 09:11:07 +00:00
if options is not None:
vol_string += "," + ",".join(
["{0}={1}".format(k, v) for k, v in options.items()]
)
if kwargs:
vol_string += "," + ",".join(
["{0}={1}".format(k, v) for k, v in kwargs.items()]
)
return {key: vol_string}
def get_lxc_resource(self, vmid, hostname):
if not vmid and not hostname:
self.module.fail_json(msg="Either VMID or hostname must be provided.")
if vmid:
vm = self.get_lxc_resource_by_id(vmid)
elif hostname:
vm = self.get_lxc_resource_by_hostname(hostname)
vmid = vm["vmid"]
if vm["type"] != self.VZ_TYPE:
identifier = self.format_vm_identifier(vmid, hostname)
self.module.fail_json(
msg="The specified VM %s is not an %s." % (identifier, self.VZ_TYPE)
)
return vm
def get_lxc_resource_by_id(self, vmid):
vms = self.get_vm_resources()
2020-03-09 09:11:07 +00:00
vms = [vm for vm in vms if vm["vmid"] == vmid]
if len(vms) == 0:
raise LookupError("VM with VMID %d does not exist in cluster." % vmid)
return vms[0]
def get_lxc_resource_by_hostname(self, hostname):
vms = self.get_vm_resources()
vms = [vm for vm in vms if vm["name"] == hostname]
if len(vms) == 0:
raise LookupError(
"VM with hostname %s does not exist in cluster." % hostname
)
elif len(vms) > 1:
raise ValueError(
"Multiple VMs found with hostname %s. Please specify VMID." % hostname
)
return vms[0]
def get_vm_resources(self):
try:
return self.proxmox_api.cluster.resources.get(type="vm")
2020-03-09 09:11:07 +00:00
except Exception as e:
self.module.fail_json(
msg="Unable to retrieve list of %s VMs from cluster resources: %s"
% (self.VZ_TYPE, e)
)
2020-03-09 09:11:07 +00:00
def get_lxc_status(self, vmid, node_name):
2020-03-09 09:11:07 +00:00
try:
proxmox_node = self.proxmox_api.nodes(node_name)
except Exception as e:
self.module.fail_json(msg="Unable to retrieve node information: %s" % e)
return getattr(proxmox_node, self.VZ_TYPE)(vmid).status.current.get()
def format_vm_identifier(self, vmid, hostname):
if vmid and hostname:
return "%s (%s)" % (hostname, vmid)
elif hostname:
return hostname
else:
return to_native(vmid)
2020-03-09 09:11:07 +00:00
def handle_api_timeout(self, vmid, node, taskid, timeout, timeout_msg=""):
if timeout_msg != "":
timeout_msg = "%s " % timeout_msg
2020-03-09 09:11:07 +00:00
while timeout > 0:
if self.api_task_ok(node, taskid):
return
timeout -= 1
time.sleep(1)
2020-03-09 09:11:07 +00:00
self.module.fail_json(
vmid=vmid,
taskid=taskid,
msg="%sLast line in task before timeout: %s"
% (timeout_msg, self.proxmox_api.nodes(node).tasks(taskid).log.get()[:1]),
)
def is_template_container(self, node, target):
"""Check if the specified container is a template."""
proxmox_node = self.proxmox_api.nodes(node)
config = getattr(proxmox_node, self.VZ_TYPE)(target).config.get()
return config.get("template", False)
def content_check(self, node, ostemplate, template_store):
"""Check if the specified ostemplate is present in the specified storage."""
proxmox_node = self.proxmox_api.nodes(node)
storage_contents = proxmox_node.storage(template_store).content.get()
return any(content["volid"] == ostemplate for content in storage_contents)
def validate_tags(self, tags):
"""Check if the specified tags are valid."""
re_tag = re.compile(r"^[a-z0-9_][a-z0-9_\-\+\.]*$")
for tag in tags:
if not re_tag.match(tag):
self.module.fail_json(msg="%s is not a valid tag" % tag)
return False
return True
def check_supported_features(self):
for option, version in self.MINIMUM_VERSIONS.items():
if self.version() < LooseVersion(version) and option in self.module.params:
self.module.fail_json(
changed=False,
msg="Feature {option} is only supported in PVE {version}+, and you're using PVE {pve_version}".format(
option=option, version=version, pve_version=self.version()
),
)
2020-03-09 09:11:07 +00:00
def isfloat(value):
if value is None:
return False
try:
float(value)
return True
except ValueError:
return False
def main():
module = get_ansible_module()
proxmox = ProxmoxLxcAnsible(module)
try:
proxmox.run()
except Exception as e:
module.fail_json(msg="An error occurred: %s" % to_native(e))
2020-03-09 09:11:07 +00:00
if __name__ == "__main__":
2020-03-09 09:11:07 +00:00
main()