Browse Source

Add tripleo-lvmfilter role to restrict visible block devices for LVM2

The lvmfilter role creates an LVM filter looking at which physical
devices are in use by active logical volumes.

Change-Id: I9781007559e074f2b102f6f90c1aed6def1b02be
Related-Bug: 1855704
changes/90/697990/49
Giulio Fidente 3 years ago
parent
commit
696814e296
  1. 6
      doc/source/roles/role-tripleo_lvmfilter.rst
  2. 102
      tripleo_ansible/ansible_plugins/modules/lvm2_physical_devices_facts.py
  3. 23
      tripleo_ansible/roles/tripleo_lvmfilter/defaults/main.yml
  4. 20
      tripleo_ansible/roles/tripleo_lvmfilter/handlers/main.yml
  5. 37
      tripleo_ansible/roles/tripleo_lvmfilter/meta/main.yml
  6. 21
      tripleo_ansible/roles/tripleo_lvmfilter/molecule/default/converge.yml
  7. 49
      tripleo_ansible/roles/tripleo_lvmfilter/molecule/default/molecule.yml
  8. 24
      tripleo_ansible/roles/tripleo_lvmfilter/molecule/default/prepare.yml
  9. 67
      tripleo_ansible/roles/tripleo_lvmfilter/tasks/main.yml
  10. 34
      tripleo_ansible/tests/modules/test_lvm2_physical_devices_facts.py
  11. 10
      zuul.d/molecule.yaml

6
doc/source/roles/role-tripleo_lvmfilter.rst

@ -0,0 +1,6 @@
========================
Role - tripleo_lvmfilter
========================
.. ansibleautoplugin::
:role: tripleo_ansible/roles/tripleo_lvmfilter

102
tripleo_ansible/ansible_plugins/modules/lvm2_physical_devices_facts.py

@ -0,0 +1,102 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
__metaclass__ = type
DOCUMENTATION = """
module: lvm2_physical_devices_facts
short_description: Gather list of block devices in use by LVM2
version_added: '1.0.0'
description: Gather list of block devices in use by LVM2 as PVs
author:
- "Giulio Fidente (@gfidente)"
"""
EXAMPLES = """
- name: Get list of LVM2 PVs
lvm2_physical_devices_facts:
"""
RETURN = """
ansible_facts:
description: List of PVs in use
returned: always
type: dict
contains:
lvm2_active_pvs:
description: List of LVM2 volumes hosting active LVs
type: list
returned: always but it might be empty
sample: ['/dev/sdb2']
"""
from ansible.module_utils.basic import AnsibleModule
def get_vgs_with_active_lvs(module):
command = ['lvs', '--noheadings', '--options', 'vg_name', '--select', 'lv_active=active']
rc, out, err = module.run_command(command)
if rc != 0:
module.fail_json(msg="Failed to run LVM2 lvs command", err=err)
if not out:
return []
vgs = list(set(out.split()))
return vgs
def get_pvs_in_use_by_active_vg(module, active_vg):
command = ['vgs', '--noheadings', '--options', 'pv_name', active_vg]
rc, out, err = module.run_command(command)
if rc != 0:
module.fail_json(msg="Failed to run LVM2 vgs command for %s" % (active_vg), err=err)
if not out:
return []
pvs = list(set(out.split()))
return pvs
def run_module():
module_args = {}
result = dict(
changed=False,
ansible_facts=dict(),
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True,
)
if module.check_mode:
module.exit_json(**result)
active_vgs = get_vgs_with_active_lvs(module)
active_pvs = []
for vg in active_vgs:
active_pvs.extend(get_pvs_in_use_by_active_vg(module, vg))
pvs = {'lvm2_active_pvs': list(set(active_pvs))}
result['ansible_facts'] = pvs
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()

23
tripleo_ansible/roles/tripleo_lvmfilter/defaults/main.yml

@ -0,0 +1,23 @@
---
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# All variables intended for modification should be placed in this file.
# All variables within this role should have a prefix of "tripleo_tripleo_lvmfilter"
tripleo_tripleo_lvmfilter_enabled: false
tripleo_tripleo_lvmfilter_devices_allowlist: []
tripleo_tripleo_lvmfilter_devices_denylist: []

20
tripleo_ansible/roles/tripleo_lvmfilter/handlers/main.yml

@ -0,0 +1,20 @@
---
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Refresh LVM caches
become: true
command: vgscan

37
tripleo_ansible/roles/tripleo_lvmfilter/meta/main.yml

@ -0,0 +1,37 @@
---
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
galaxy_info:
author: OpenStack
description: TripleO OpenStack Role -- tripleo_lvmfilter
company: Red Hat
license: Apache-2.0
min_ansible_version: 2.7
#
# Provide a list of supported platforms, and for each platform a list of versions.
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
# To view available platforms and versions (or releases), visit:
# https://galaxy.ansible.com/api/v1/platforms/
#
platforms:
- name: CentOS
versions:
- 7
- 8
galaxy_tags:
- tripleo

21
tripleo_ansible/roles/tripleo_lvmfilter/molecule/default/converge.yml

@ -0,0 +1,21 @@
---
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Converge
hosts: all
roles:
- role: "tripleo_lvmfilter"

49
tripleo_ansible/roles/tripleo_lvmfilter/molecule/default/molecule.yml

@ -0,0 +1,49 @@
---
driver:
name: podman
log: true
platforms:
- name: ubi8
hostname: ubi8
image: ubi8/ubi-init
registry:
url: registry.access.redhat.com
dockerfile: Dockerfile
pkg_extras: python*setuptools
volumes:
- /etc/ci/mirror_info.sh:/etc/ci/mirror_info.sh:ro
- /etc/pki/rpm-gpg:/etc/pki/rpm-gpg
- /opt/yum.repos.d:/etc/yum.repos.d:rw
privileged: true
environment: &env
http_proxy: "{{ lookup('env', 'http_proxy') }}"
https_proxy: "{{ lookup('env', 'https_proxy') }}"
ulimits: &ulimit
- host
provisioner:
inventory:
hosts:
all:
hosts:
ubi8:
ansible_python_interpreter: /usr/bin/python3
name: ansible
log: true
env:
ANSIBLE_STDOUT_CALLBACK: yaml
scenario:
test_sequence:
- destroy
- create
- prepare
- converge
- check
- verify
- destroy
verifier:
name: testinfra

24
tripleo_ansible/roles/tripleo_lvmfilter/molecule/default/prepare.yml

@ -0,0 +1,24 @@
---
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Prepare
hosts: all
vars:
test_deps_extra_packages:
- lvm2
roles:
- role: test_deps

67
tripleo_ansible/roles/tripleo_lvmfilter/tasks/main.yml

@ -0,0 +1,67 @@
---
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: gather package facts
package_facts:
manager: auto
- name: gather allowed block devices list
when: "'lvm2' in ansible_facts.packages"
block:
- name: collect in-use lvm2 devices list
become: true
lvm2_physical_devices_facts:
- name: set allowed_devices
set_fact:
allowed_devices: "{{ (ansible_facts['lvm2_active_pvs'] | default([]) | list)
| intersect(ansible_devices.keys())
+ (tripleo_tripleo_lvmfilter_devices_allowlist | default([]))
| unique }}"
- name: create lvm.conf with global_filter
when:
- allowed_devices is defined
- (allowed_devices | length) > 0
block:
- name: build lvm2 allow list
set_fact:
lvm2_allow_list: "\"{{ allowed_devices | map('regex_replace', '(.+)', 'a|\\1|')
| join('\",\"') }}\""
- name: build lvm2 deny list
set_fact:
lvm2_deny_list: "\"{{ tripleo_tripleo_lvmfilter_devices_denylist | default([])
| map('regex_replace', '(.+)', 'r|\\1|') | join('\",\"') }}\""
- name: build lvm2 filter
set_fact:
filter: "{{ lvm2_allow_list + ',' + lvm2_deny_list }}"
- name: regenerate lvm config
become: true
command: >
lvmconfig -f /tmp/tripleo_lvmfilter.conf
--mergedconfig --withgeneralpreamble --withspaces --withsummary --withcomments --ignorelocal --showdeprecated
--config devices/global_filter='[{{ filter }}]'
- name: copy new lvm.conf in place
become: true
copy:
remote_src: true
src: /tmp/tripleo_lvmfilter.conf
dest: /etc/lvm/lvm.conf
owner: root
group: root
mode: '0644'
backup: true
when: tripleo_tripleo_lvmfilter_enabled
notify:
- Refresh LVM caches

34
tripleo_ansible/tests/modules/test_lvm2_physical_devices_facts.py

@ -0,0 +1,34 @@
# Copyright 2019 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from collections import Counter
from unittest import mock
from tripleo_ansible.ansible_plugins.modules import lvm2_physical_devices_facts as lvm2
from tripleo_ansible.tests import base as tests_base
class TestLvm2PhysicalDevicesFacts(tests_base.TestCase):
def test_get_pvs(self):
mock_module = mock.Mock()
mock_module.run_command.return_value = (0, ' myvgname\n myvgname\n', '')
result = lvm2.get_vgs_with_active_lvs(mock_module)
self.assertEqual(['myvgname'], result)
mock_module.run_command.return_value = (0, ' /dev/sdb1\n /dev/sdb2\n', '')
result = lvm2.get_vgs_with_active_lvs(mock_module)
self.assertEqual(Counter(['/dev/sdb1', '/dev/sdb2']), Counter(result))

10
zuul.d/molecule.yaml

@ -30,6 +30,7 @@
- tripleo-ansible-centos-8-molecule-tripleo_image_serve
- tripleo-ansible-centos-8-molecule-tripleo_kernel
- tripleo-ansible-centos-8-molecule-tripleo_keystone_resources
- tripleo-ansible-centos-8-molecule-tripleo_lvmfilter
- tripleo-ansible-centos-8-molecule-tripleo_module_load
- tripleo-ansible-centos-8-molecule-tripleo_network_config
- tripleo-ansible-centos-8-molecule-tripleo_nodes_validation
@ -81,6 +82,7 @@
- tripleo-ansible-centos-8-molecule-tripleo_image_serve
- tripleo-ansible-centos-8-molecule-tripleo_kernel
- tripleo-ansible-centos-8-molecule-tripleo_keystone_resources
- tripleo-ansible-centos-8-molecule-tripleo_lvmfilter
- tripleo-ansible-centos-8-molecule-tripleo_module_load
- tripleo-ansible-centos-8-molecule-tripleo_network_config
- tripleo-ansible-centos-8-molecule-tripleo_nodes_validation
@ -132,6 +134,7 @@
- tripleo-ansible-centos-8-molecule-tripleo_image_serve
- tripleo-ansible-centos-8-molecule-tripleo_kernel
- tripleo-ansible-centos-8-molecule-tripleo_keystone_resources
- tripleo-ansible-centos-8-molecule-tripleo_lvmfilter
- tripleo-ansible-centos-8-molecule-tripleo_module_load
- tripleo-ansible-centos-8-molecule-tripleo_network_config
- tripleo-ansible-centos-8-molecule-tripleo_nodes_validation
@ -350,6 +353,13 @@
parent: tripleo-ansible-centos-8-base
vars:
tripleo_role_name: tripleo_keystone_resources
- job:
files:
- ^tripleo_ansible/roles/tripleo_lvmfilter/.*
name: tripleo-ansible-centos-8-molecule-tripleo_lvmfilter
parent: tripleo-ansible-centos-8-base
vars:
tripleo_role_name: tripleo_lvmfilter
- job:
files:
- ^tripleo_ansible/roles/tripleo_module_load/.*

Loading…
Cancel
Save