From 1999110bbc1d21d9792a761ef17c02503b9868e0 Mon Sep 17 00:00:00 2001 From: Mark Goddard <mark@stackhpc.com> Date: Wed, 7 Feb 2018 09:04:11 +0000 Subject: [PATCH] Fixes for ceph block device tagging (#1) * Install galaxy roles before running ansible tests * Use package module in kolla-ceph to support Debian-based systems This is required for running tests in TravisCI. * Fix kolla-ceph unit test * Add more tests for kolla-ceph Journal tests are currently failing on my laptop due to partition labels being truncated. * Add .gitignore for stackhpc.parted-1-1 galaxy role * Run all test cases Run all test cases, collecting failures, then report at the end. --- .gitignore | 1 + ansible/roles/kolla-ceph/tasks/config.yml | 6 +- ansible/roles/kolla-ceph/tests/main.yml | 6 +- .../tests/test-bootstrapped-journal.yml | 118 ++++++++++++++++++ .../kolla-ceph/tests/test-data-journal.yml | 117 +++++++++++++++++ .../roles/kolla-ceph/tests/test-journal.yml | 93 ++++++++++++++ ...{test-defaults.yml => test-no-journal.yml} | 28 ++--- tools/test-ansible.sh | 17 +++ tox.ini | 10 +- 9 files changed, 367 insertions(+), 29 deletions(-) create mode 100644 ansible/roles/kolla-ceph/tests/test-bootstrapped-journal.yml create mode 100644 ansible/roles/kolla-ceph/tests/test-data-journal.yml create mode 100644 ansible/roles/kolla-ceph/tests/test-journal.yml rename ansible/roles/kolla-ceph/tests/{test-defaults.yml => test-no-journal.yml} (66%) create mode 100755 tools/test-ansible.sh diff --git a/.gitignore b/.gitignore index a0fb698d0..961533f5e 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ ansible/roles/stackhpc.os-openstackclient/ ansible/roles/stackhpc.os-networks/ ansible/roles/stackhpc.os-projects/ ansible/roles/stackhpc.os-shade/ +ansible/roles/stackhpc.parted-1-1/ ansible/roles/resmo.ntp/ ansible/roles/yatesr.timezone/ diff --git a/ansible/roles/kolla-ceph/tasks/config.yml b/ansible/roles/kolla-ceph/tasks/config.yml index d23fe6b92..0a542b30e 100644 --- a/ansible/roles/kolla-ceph/tasks/config.yml +++ b/ansible/roles/kolla-ceph/tasks/config.yml @@ -2,7 +2,7 @@ # (ktibi) Need to remove parted_1_1 module when kayobe will support ansible 2.4 - name: Ensure required packages are installed - yum: + package: name: parted state: installed become: True @@ -63,7 +63,7 @@ label: "{{item.item}}" vars: part_label: "{% if item.item.journal is defined %}{{ part_label_with_journal }}{% else %}KOLLA_CEPH_OSD_BOOTSTRAP{% endif %}" - part_label_with_journal: "KOLLA_CEPH_OSD_BOOTSTRAP_{{ osd_id }}" + part_label_with_journal: "KOLLA_CEPH_OSD_BOOTSTRAP_{{ (osd_id | hash('md5'))[:9] }}" osd_id: "{{ item.item.osd | basename }}{{ ansible_hostname }}" - name: Create tag partition for Ceph external journal @@ -81,6 +81,6 @@ loop_control: label: "{{item.item}}" vars: - part_label: "KOLLA_CEPH_OSD_BOOTSTRAP_{{ osd_id }}_J" + part_label: "KOLLA_CEPH_OSD_BOOTSTRAP_{{ (osd_id | hash('md5'))[:9] }}_J" osd_id: "{{ item.item.osd | basename }}{{ ansible_hostname }}" diff --git a/ansible/roles/kolla-ceph/tests/main.yml b/ansible/roles/kolla-ceph/tests/main.yml index 3460876ee..97e8ab4f2 100644 --- a/ansible/roles/kolla-ceph/tests/main.yml +++ b/ansible/roles/kolla-ceph/tests/main.yml @@ -1,6 +1,8 @@ --- - -- include: test-defaults.yml +- include: test-no-journal.yml +- include: test-journal.yml +- include: test-bootstrapped-journal.yml +- include: test-data-journal.yml - hosts: localhost connection: local diff --git a/ansible/roles/kolla-ceph/tests/test-bootstrapped-journal.yml b/ansible/roles/kolla-ceph/tests/test-bootstrapped-journal.yml new file mode 100644 index 000000000..a15a28e21 --- /dev/null +++ b/ansible/roles/kolla-ceph/tests/test-bootstrapped-journal.yml @@ -0,0 +1,118 @@ +--- +# Test case with an OSD and external journal that have already been tagged by +# kayobe with the kolla-ansible bootstrap label, but have not yet been +# converted to use the in-use label. + +- hosts: localhost + connection: local + tasks: + - name: Allocate a temporary file for a fake OSD + tempfile: + register: osd_tempfile + + - name: Allocate a temporary file for a fake journal + tempfile: + register: journal_tempfile + + - name: Allocate a fake OSD file + command: fallocate -l 10M {{ osd_tempfile.path }} + + - name: Allocate a fake journal file + command: fallocate -l 10M {{ journal_tempfile.path }} + + - name: Create tag partition for the fake OSD + become: True + parted_1_1: + device: "{{ osd_tempfile.path }}" + number: 1 + label: gpt + name: "{{ part_label }}" + state: present + vars: + part_label: "KOLLA_CEPH_OSD_BOOTSTRAP_{{ (osd_id | hash('md5'))[:9] }}" + osd_id: "{{ osd_tempfile.path | basename }}{{ ansible_hostname }}" + + - name: Create tag partition for the fake journal + become: True + parted_1_1: + device: "{{ journal_tempfile.path }}" + number: 1 + label: gpt + name: "{{ part_label }}" + state: present + vars: + part_label: "KOLLA_CEPH_OSD_BOOTSTRAP_{{ (osd_id | hash('md5'))[:9] }}_J" + osd_id: "{{ journal_tempfile.path | basename }}{{ ansible_hostname }}" + + - block: + - name: Import parted role + include_role: + name: ../../stackhpc.parted-1-1 + + - name: Test the kolla-ceph role + include_role: + name: ../../kolla-ceph + vars: + ceph_disks: + - osd: "{{ osd_tempfile.path }}" + journal: "{{ journal_tempfile.path }}" + + - name: Get name of fake OSD partition + parted_1_1: + device: "{{ osd_tempfile.path }}" + register: "disk_osd_info" + become: True + + - name: Validate number of OSD partitions + assert: + that: disk_osd_info.partitions | length == 1 + msg: > + Number of OSD partitions is not correct. Expected 1, + actual {{ disk_osd_info.partitions | length }} + + - name: Validate OSD tag is present + assert: + that: "disk_osd_info.partitions.0.name == expected" + msg: > + Name of OSD partition is not correct. Expected {{ expected }}, + actual {{ disk_osd_info.partitions.0.name }}. + vars: + expected: "{{ 'KOLLA_CEPH_OSD_BOOTSTRAP_' ~ ((osd_tempfile.path | basename ~ ansible_hostname) | hash('md5'))[:9] }}" + + - name: Get name of fake journal partition + parted_1_1: + device: "{{ journal_tempfile.path }}" + register: "disk_journal_info" + become: True + + - name: Validate number of journal partitions + assert: + that: disk_journal_info.partitions | length == 1 + msg: > + Number of journal partitions is not correct. Expected 1, + actual {{ disk_journal_info.partitions | length }} + + - name: Validate journal tag is present + assert: + that: "disk_journal_info.partitions.0.name == expected" + msg: > + Name of journal partition is not correct. Expected {{ expected }}, + actual {{ disk_journal_info.partitions.0.name }}. + vars: + expected: "{{ 'KOLLA_CEPH_OSD_BOOTSTRAP_' ~ (( journal_tempfile.path | basename ~ ansible_hostname) | hash('md5'))[:9] ~ '_J' }}" + + always: + - name: Remove the fake OSD file + file: + name: "{{ osd_tempfile.path }}" + state: absent + + - name: Remove the fake journal file + file: + name: "{{ journal_tempfile.path }}" + state: absent + + rescue: + - name: Flag that a failure occurred + set_fact: + test_failures: "{{ test_failures | default(0) | int + 1 }}" diff --git a/ansible/roles/kolla-ceph/tests/test-data-journal.yml b/ansible/roles/kolla-ceph/tests/test-data-journal.yml new file mode 100644 index 000000000..4a8efecb1 --- /dev/null +++ b/ansible/roles/kolla-ceph/tests/test-data-journal.yml @@ -0,0 +1,117 @@ +--- +# Test case with an OSD and external journal that have been converted by +# kolla-ansible to use the in-use label. + +- hosts: localhost + connection: local + tasks: + - name: Allocate a temporary file for a fake OSD + tempfile: + register: osd_tempfile + + - name: Allocate a temporary file for a fake journal + tempfile: + register: journal_tempfile + + - name: Allocate a fake OSD file + command: fallocate -l 10M {{ osd_tempfile.path }} + + - name: Allocate a fake journal file + command: fallocate -l 10M {{ journal_tempfile.path }} + + - name: Create tag partition for the fake OSD + become: True + parted_1_1: + device: "{{ osd_tempfile.path }}" + number: 1 + label: gpt + name: "{{ part_label }}" + state: present + vars: + part_label: "KOLLA_CEPH_DATA_{{ (osd_id | hash('md5'))[:9]}}" + osd_id: "{{ (osd_tempfile.path | basename ~ ansible_hostname) }}" + + - name: Create tag partition for the fake journal + become: True + parted_1_1: + device: "{{ journal_tempfile.path }}" + number: 1 + label: gpt + name: "{{ part_label }}" + state: present + vars: + part_label: "KOLLA_CEPH_DATA_{{ (osd_id | hash('md5'))[:9] }}_J" + osd_id: "{{ (journal_tempfile.path | basename ~ ansible_hostname) }}" + + - block: + - name: Import parted role + include_role: + name: ../../stackhpc.parted-1-1 + + - name: Test the kolla-ceph role + include_role: + name: ../../kolla-ceph + vars: + ceph_disks: + - osd: "{{ osd_tempfile.path }}" + journal: "{{ journal_tempfile.path }}" + + - name: Get name of fake OSD partition + parted_1_1: + device: "{{ osd_tempfile.path }}" + register: "disk_osd_info" + become: True + + - name: Validate number of OSD partitions + assert: + that: disk_osd_info.partitions | length == 1 + msg: > + Number of OSD partitions is not correct. Expected 1, + actual {{ disk_osd_info.partitions | length }} + + - name: Validate OSD tag is present + assert: + that: "disk_osd_info.partitions.0.name == expected" + msg: > + Name of OSD partition is not correct. Expected {{ expected }}, + actual {{ disk_osd_info.partitions.0.name }}. + vars: + expected: "{{ 'KOLLA_CEPH_DATA_' ~ ((osd_tempfile.path | basename ~ ansible_hostname)| hash('md5'))[:9] }}" + + - name: Get name of fake journal partition + parted_1_1: + device: "{{ journal_tempfile.path }}" + register: "disk_journal_info" + become: True + + - name: Validate number of journal partitions + assert: + that: disk_journal_info.partitions | length == 1 + msg: > + Number of journal partitions is not correct. Expected 1, + actual {{ disk_journal_info.partitions | length }} + + - name: Validate journal tag is present + assert: + that: "disk_journal_info.partitions.0.name == expected" + msg: > + Name of journal partition is not correct. Expected {{ expected }}, + actual {{ disk_journal_info.partitions.0.name }}. + vars: + expected: "{{ 'KOLLA_CEPH_DATA_' ~ ((journal_tempfile.path | basename ~ ansible_hostname)| hash('md5'))[:9] ~ '_J' }}" + + always: + - name: Remove the fake OSD file + file: + name: "{{ osd_tempfile.path }}" + state: absent + + - name: Remove the fake journal file + file: + name: "{{ journal_tempfile.path }}" + state: absent + + rescue: + - name: Flag that a failure occurred + set_fact: + test_failures: "{{ test_failures | default(0) | int + 1 }}" diff --git a/ansible/roles/kolla-ceph/tests/test-journal.yml b/ansible/roles/kolla-ceph/tests/test-journal.yml new file mode 100644 index 000000000..d66b3cbf6 --- /dev/null +++ b/ansible/roles/kolla-ceph/tests/test-journal.yml @@ -0,0 +1,93 @@ +--- +# Test case with an OSD and external journal that have not yet been tagged by +# kayobe with the kolla-ansible bootstrap label. + +- hosts: localhost + connection: local + tasks: + - name: Allocate a temporary file for a fake OSD + tempfile: + register: osd_tempfile + + - name: Allocate a temporary file for a fake journal + tempfile: + register: journal_tempfile + + - name: Allocate a fake OSD file + command: fallocate -l 10M {{ osd_tempfile.path }} + + - name: Allocate a fake journal file + command: fallocate -l 10M {{ journal_tempfile.path }} + + - block: + - name: Import parted role + include_role: + name: ../../stackhpc.parted-1-1 + + - name: Test the kolla-ceph role + include_role: + name: ../../kolla-ceph + vars: + ceph_disks: + - osd: "{{ osd_tempfile.path }}" + journal: "{{ journal_tempfile.path }}" + + - name: Get name of fake OSD partition + parted_1_1: + device: "{{ osd_tempfile.path }}" + register: "disk_osd_info" + become: True + + - name: Validate number of OSD partitions + assert: + that: disk_osd_info.partitions | length == 1 + msg: > + Number of OSD partitions is not correct. Expected 1, + actual {{ disk_osd_info.partitions | length }} + + - name: Validate OSD tag is present + assert: + that: "disk_osd_info.partitions.0.name == expected" + msg: > + Name of OSD partition is not correct. Expected {{ expected }}, + actual {{ disk_osd_info.partitions.0.name }}. + vars: + expected: "{{ 'KOLLA_CEPH_OSD_BOOTSTRAP_' ~ ((osd_tempfile.path | basename ~ ansible_hostname)| hash('md5'))[:9] }}" + + - name: Get name of fake journal partition + parted_1_1: + device: "{{ journal_tempfile.path }}" + register: "disk_journal_info" + become: True + + - name: Validate number of journal partitions + assert: + that: disk_journal_info.partitions | length == 1 + msg: > + Number of journal partitions is not correct. Expected 1, + actual {{ disk_journal_info.partitions | length }} + + - name: Validate journal tag is present + assert: + that: "disk_journal_info.partitions.0.name == expected" + msg: > + Name of journal partition is not correct. Expected {{ expected }}, + actual {{ disk_journal_info.partitions.0.name }}. + vars: + expected: "{{ 'KOLLA_CEPH_OSD_BOOTSTRAP_' ~ ((journal_tempfile.path | basename ~ ansible_hostname)| hash('md5'))[:9] ~ '_J' }}" + + always: + - name: Remove the fake OSD file + file: + name: "{{ osd_tempfile.path }}" + state: absent + + - name: Remove the fake journal file + file: + name: "{{ journal_tempfile.path }}" + state: absent + + rescue: + - name: Flag that a failure occurred + set_fact: + test_failures: "{{ test_failures | default(0) | int + 1 }}" diff --git a/ansible/roles/kolla-ceph/tests/test-defaults.yml b/ansible/roles/kolla-ceph/tests/test-no-journal.yml similarity index 66% rename from ansible/roles/kolla-ceph/tests/test-defaults.yml rename to ansible/roles/kolla-ceph/tests/test-no-journal.yml index 9a0056516..8c0dec3f8 100644 --- a/ansible/roles/kolla-ceph/tests/test-defaults.yml +++ b/ansible/roles/kolla-ceph/tests/test-no-journal.yml @@ -1,4 +1,7 @@ --- +# Test case with an OSD and no external journal that has not yet been tagged by +# kayobe with the kolla-ansible bootstrap label. + - hosts: localhost connection: local tasks: @@ -7,32 +10,25 @@ register: tempfile - name: Allocate a fake OSD file - command: fallocate -l "{{ device_size }} {{ tempfile.path }}" - - - name: Find a free loopback device - command: losetup -f - register: loopback_result - - - name: Create a loopback device for the fake OSD file - command: losetup "{{ loopback_result.stdout }} {{ tempfile.path }}" - become: True + command: fallocate -l 10M {{ tempfile.path }} - block: - name: Import parted role include_role: - name: stackhpc.parted-1-1 + name: ../../stackhpc.parted-1-1 - name: Test the kolla-ceph role include_role: name: ../../kolla-ceph vars: ceph_disks: - - osd: "{{ loopback_result.stdout }}" + - osd: "{{ tempfile.path }}" - name: Get name of fake partition - parted_kayobe: - device: "{{ loopback_result.stdout }}" + parted_1_1: + device: "{{ tempfile.path }}" register: "disk_osd_info" + become: True - name: Validate number of partition assert: @@ -47,10 +43,6 @@ Name of partition is not correct. always: - - name: Detach the loopback device - command: losetup -d {{ loopback_result.stdout }} - become: True - - name: Remove the fake OSD file file: name: "{{ tempfile.path }}" @@ -60,5 +52,3 @@ - name: Flag that a failure occurred set_fact: test_failures: "{{ test_failures | default(0) | int + 1 }}" - - diff --git a/tools/test-ansible.sh b/tools/test-ansible.sh new file mode 100755 index 000000000..e54dc56fc --- /dev/null +++ b/tools/test-ansible.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Run ansible tests. Any arguments passed to this script will be passed onto +# ansible-playbook. + +set -e + +failed=0 +for playbook in ansible/roles/*/tests/main.yml; do + if ! ansible-playbook --connection=local $playbook $*; then + failed=$((failed + 1)) + fi +done +if [[ $failed -ne 0 ]]; then + echo "Failed $failed test cases" + exit 1 +fi diff --git a/tox.ini b/tox.ini index 6819d60d6..a882221f4 100644 --- a/tox.ini +++ b/tox.ini @@ -45,11 +45,11 @@ usedevelop = True sitepackages = True install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/pike} {opts} {packages} commands = - bash -c \ - "ansible-playbook \ - --connection=local \ - {toxinidir}/ansible/roles/*/tests/main.yml \ - {posargs}" + # Install ansible role dependencies from Galaxy. + ansible-galaxy install \ + -r {toxinidir}/requirements.yml \ + -p {toxinidir}/ansible/roles + {toxinidir}/tools/test-ansible.sh {posargs} [testenv:alint] commands = ansible-lint ansible/*.yaml