Skip to content

Commit

Permalink
Release 1.7.1
Browse files Browse the repository at this point in the history
Merge branch develop@5b2e74d2353242d94e4f1906db4dc5d655493f57 into main
  • Loading branch information
lae committed Aug 14, 2022
2 parents f3bcd26 + 5b2e74d commit 6274a16
Show file tree
Hide file tree
Showing 14 changed files with 241 additions and 64 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ PVE version. They should be IPv4 or IPv6 addresses. For more information, refer
to the [Cluster Manager][pvecm-network] chapter in the PVE Documentation.

```
# pve_cluster_addr0: "{{ ansible_default_ipv4.address }}"
# pve_cluster_addr0: "{{ defaults to the default interface ipv4 or ipv6 if detected }}"
# pve_cluster_addr1: "another interface's IP address or hostname"
```

Expand Down
3 changes: 2 additions & 1 deletion defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ pve_ceph_crush_rules: []
pve_cluster_enabled: no
pve_cluster_clustername: "{{ pve_group }}"
pve_manage_hosts_enabled: yes
# pve_cluster_addr0: "{{ ansible_default_ipv4.address }}"
pve_cluster_addr0: "{{ ansible_default_ipv4.address if ansible_default_ipv4.address is defined else ansible_default_ipv6.address if ansible_default_ipv6.address is defined }}"
# pve_cluster_addr1: "{{ ansible_eth1.ipv4.address }}
pve_datacenter_cfg: {}
pve_cluster_ha_groups: []
# additional roles for your cluster (f.e. for monitoring)
pve_pools: []
pve_roles: []
pve_groups: []
pve_users: []
Expand Down
6 changes: 3 additions & 3 deletions handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
name: pveproxy
state: restarted

- name: reload sshd configuration
service:
name: sshd
- name: reload ssh server configuration
ansible.builtin.systemd:
name: ssh.service
state: reloaded

- name: restart watchdog-mux
Expand Down
58 changes: 30 additions & 28 deletions library/collect_kernel_info.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/python
import glob
import re
import subprocess

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text


def main():
module = AnsibleModule(
argument_spec = dict(
Expand All @@ -16,52 +16,54 @@ def main():

params = module.params

# Much of the following is reimplemented from /usr/share/grub/grub-mkconfig_lib
kernels = []
# Collect a list of possible installed kernels
for filename in glob.glob("/boot/vmlinuz-*") + glob.glob("/vmlinuz-*") + \
glob.glob("/boot/kernel-*"):
if ".dpkg-" in filename:
continue
if filename.endswith(".rpmsave") or filename.endswith(".rpmnew"):
continue
kernels.append(filename)
# Collect a list of installed kernels
kernels = glob.glob("/lib/modules/*")

# Identify path to the latest kernel
latest_kernel = ""
re_prefix = re.compile("[^-]*-")
re_attributes = re.compile("[._-](pre|rc|test|git|old|trunk)")
for kernel in kernels:
right = re.sub(re_attributes, "~\1", re.sub(re_prefix, '', latest_kernel, count=1))
if not right:
if not latest_kernel:
latest_kernel = kernel
continue
left = re.sub(re_attributes, "~\1", re.sub(re_prefix, '', kernel, count=1))
# These splits remove the path and get the base directory name, which
# should be something like 5.4.78-1-pve, that we can compare
right = latest_kernel.split("/")[-1]
left = kernel.split("/")[-1]
cmp_str = "gt"
if left.endswith(".old") and not right.endswith(".old"):
left = left[:-4]
if right.endswith(".old") and not left.endswith(".old"):
right = right[:-4]
cmp_str = "ge"
if subprocess.call(["dpkg", "--compare-versions", left, cmp_str, right]) == 0:
latest_kernel = kernel

# This will likely output a path that considers the boot partition as /
# e.g. /vmlinuz-4.4.44-1-pve
booted_kernel = to_text(subprocess.check_output(["grep", "-o", "-P", "(?<=BOOT_IMAGE=).*?(?= )", "/proc/cmdline"]).strip())
booted_kernel = "/lib/modules/{}".format(to_text(
subprocess.run(["uname", "-r"], capture_output=True).stdout.strip))

booted_kernel_package = ""
old_kernel_packages = []

if params['lookup_packages']:
for kernel in kernels:
# Identify the currently booted kernel and unused old kernels by
# querying which packages own directories in /lib/modules
try:
sp = subprocess.run(["dpkg-query", "-S", kernel],
check=True, capture_output=True)
except subprocess.CalledProcessError as e:
# Ignore errors about directories not associated with a package
if e.stderr.startswith(b"dpkg-query: no path found matching"):
continue
raise e
if kernel.split("/")[-1] == booted_kernel.split("/")[-1]:
booted_kernel_package = to_text(subprocess.check_output(["dpkg-query", "-S", kernel])).split(":")[0]
booted_kernel_package = to_text(sp.stdout).split(":")[0]
elif kernel != latest_kernel:
old_kernel_packages.append(to_text(subprocess.check_output(["dpkg-query", "-S", kernel])).split(":")[0])
old_kernel_packages.append(to_text(sp.stdout).split(":")[0])

# returns True if we're not booted into the latest kernel
new_kernel_exists = booted_kernel.split("/")[-1] != latest_kernel.split("/")[-1]
module.exit_json(changed=False, new_kernel_exists=new_kernel_exists, old_packages=old_kernel_packages, booted_package=booted_kernel_package)
module.exit_json(
changed=False,
new_kernel_exists=new_kernel_exists,
old_packages=old_kernel_packages,
booted_package=booted_kernel_package
)


if __name__ == '__main__':
main()
175 changes: 175 additions & 0 deletions library/proxmox_pool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

ANSIBLE_METADATA = {
'metadata_version': '1.0',
'status': ['stableinterface'],
'supported_by': 'futuriste'
}

DOCUMENTATION = '''
---
module: proxmox_pool
short_description: Manages pools in Proxmox
options:
name:
required: true
aliases: [ "pool", "poolid" ]
description:
- Name of the PVE pool to manage.
state:
required: false
default: "present"
choices: [ "present", "absent" ]
description:
- Specifies whether the pool should exist or not.
comment:
required: false
description:
- Optionally sets the pool's comment in PVE.
author:
- Guiffo Joel (@futuriste)
'''

EXAMPLES = '''
- name: Create Administrators pool
proxmox_pool:
name: Administrators
- name: Create Dev Users pool's
proxmox_pool:
name: pool_dev
comment: Dev Users allowed to access on this pool.
'''

RETURN = '''
updated_fields:
description: Fields that were modified for an existing pool
type: list
pool:
description: Information about the pool fetched from PVE after this task completed.
type: json
'''

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.pvesh import ProxmoxShellError
import ansible.module_utils.pvesh as pvesh

class ProxmoxPool(object):
def __init__(self, module):
self.module = module
self.name = module.params['name']
self.state = module.params['state']
self.comment = module.params['comment']

def lookup(self):
try:
return pvesh.get("pools/{}".format(self.name))
except ProxmoxShellError as e:
self.module.fail_json(msg=e.message, status_code=e.status_code, **result)

def remove_pool(self):
try:
pvesh.delete("pools/{}".format(self.name))
return (True, None)
except ProxmoxShellError as e:
return (False, e.message)

def create_pool(self):
new_pool = {}
if self.comment is not None:
new_pool['comment'] = self.comment

try:
pvesh.create("pools", poolid=self.name, **new_pool)
return (True, None)
except ProxmoxShellError as e:
return (False, e.message)

def modify_pool(self):
lookup = self.lookup()
staged_pool = {}

if self.comment is not None:
staged_pool['comment'] = self.comment

updated_fields = []
error = None

for key in staged_pool:
staged_value = to_text(staged_pool[key]) if isinstance(staged_pool[key], str) else staged_pool[key]
if key not in lookup or staged_value != lookup[key]:
updated_fields.append(key)

if self.module.check_mode:
self.module.exit_json(changed=bool(updated_fields), expected_changes=updated_fields)

if not updated_fields:
# No changes necessary
return (updated_fields, error)

try:
pvesh.set("pools/{}".format(self.name), **staged_pool)
except ProxmoxShellError as e:
error = e.message

return (updated_fields, error)

def main():
# Refer to https://pve.proxmox.com/pve-docs/api-viewer/index.html
module = AnsibleModule(
argument_spec = dict(
name=dict(type='str', required=True, aliases=['pool', 'poolid']),
state=dict(default='present', choices=['present', 'absent'], type='str'),
comment=dict(default=None, type='str'),
),
supports_check_mode=True
)

pool = ProxmoxPool(module)

changed = False
error = None
result = {}
result['name'] = pool.name
result['state'] = pool.state

if pool.state == 'absent':
if pool.lookup() is not None:
if module.check_mode:
module.exit_json(changed=True)

(changed, error) = pool.remove_pool()

if error is not None:
module.fail_json(name=pool.name, msg=error)
elif pool.state == 'present':
if not pool.lookup():
if module.check_mode:
module.exit_json(changed=True)

(changed, error) = pool.create_pool()
else:
# modify pool (note: this function is check mode aware)
(updated_fields, error) = pool.modify_pool()

if updated_fields:
changed = True
result['updated_fields'] = updated_fields

if error is not None:
module.fail_json(name=pool.name, msg=error)

lookup = pool.lookup()
if lookup is not None:
result['pool'] = lookup

result['changed'] = changed

module.exit_json(**result)

if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion module_utils/pvesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def run_command(handler, resource, **params):
if handler == "get":
if any(re.match(pattern, stderr[0]) for pattern in [
"^no such user \('.{3,64}?'\)$",
"^(group|role) '[A-Za-z0-9\.\-_]+' does not exist$",
"^(group|role|pool) '[A-Za-z0-9\.\-_]+' does not exist$",
"^domain '[A-Za-z][A-Za-z0-9\.\-_]+' does not exist$"]):
return {u"status": 404, u"message": stderr[0]}

Expand Down
8 changes: 6 additions & 2 deletions tasks/ceph.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@
- block:
- name: Query for existing Ceph volumes
pve_ceph_volume:
check_mode: no
register: _ceph_volume_data

- name: Generate a list of active OSDs
ansible.builtin.set_fact:
_existing_ceph_osds: "{{ _ceph_volume_data.stdout | from_json | json_query('*[].devices[]') }}"
_existing_ceph_osds: "{{ _ceph_volume_data.stdout | from_json | json_query('*[].devices[]') | default([]) }}"

- name: Generate list of unprovisioned OSDs
ansible.builtin.set_fact:
Expand Down Expand Up @@ -126,6 +127,7 @@
- name: List Ceph Pools
command: ceph osd pool ls
changed_when: false
check_mode: no
register: _ceph_pools

- name: Create Ceph Pools
Expand Down Expand Up @@ -175,6 +177,7 @@
- name: List Ceph Filesystems
command: ceph fs ls -f json
changed_when: false
check_mode: no
when: "pve_ceph_fs | length > 0"
register: _ceph_fs

Expand All @@ -192,6 +195,7 @@
- name: Get Ceph Filesystem pool CRUSH rules
command: 'ceph -f json osd pool get {{ item.0.name }}_{{ item.1 }} crush_rule'
changed_when: false
check_mode: no
when: "pve_ceph_fs | length > 0"
register: _ceph_fs_rule
loop: '{{ pve_ceph_fs | product(["data", "metadata"]) | list }}'
Expand Down Expand Up @@ -241,7 +245,7 @@
{{ loop.last | ternary("", ",") -}}
{% endfor %}:/
fstype: 'ceph'
opts: 'name={{ item.name }},secretfile=/etc/ceph/{{ item.name }}.secret,_netdev'
opts: 'name={{ item.name }},secretfile=/etc/ceph/{{ item.name }}.secret,_netdev,fs={{ item.name }}'
state: 'mounted'
when: "item.mountpoint is defined"
loop: '{{ pve_ceph_fs }}'
2 changes: 1 addition & 1 deletion tasks/kernel_module_cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
state: absent
when: >
(pve_zfs_options is not defined) or
(pve_zfs_options is defined and not pve_zfs_options | bool) or
(pve_zfs_options is defined and not pve_zfs_options | length > 0) or
(not pve_zfs_enabled | bool)
- name: Disable loading of ZFS module on init
Expand Down
Loading

0 comments on commit 6274a16

Please sign in to comment.