Introducing the overcloud-service-status role
This role will hit the overcloud API for nova and cinder, retrieve the services and will trig a failure if one of these services are either down or deprecated. The original intent was to validate that nova-consoleauth was deleted after an update to RHOSP16. Related: https://bugzilla.redhat.com/1921115 Change-Id: I057349fdac90a093c67aeb0b2f0a825c4c915e0b
This commit is contained in:
parent
98791eafff
commit
4fc80c6bd5
7
doc/source/roles/role-overcloud_service_status.rst
Normal file
7
doc/source/roles/role-overcloud_service_status.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
========================
|
||||||
|
overcloud_service_status
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. ansibleautoplugin::
|
||||||
|
:role: roles/overcloud_service_status
|
||||||
|
|
18
playbooks/overcloud-service-status.yaml
Normal file
18
playbooks/overcloud-service-status.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
- hosts: Undercloud
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
metadata:
|
||||||
|
name: Verify overcloud services state after running a deployment or an update
|
||||||
|
description: |
|
||||||
|
An Ansible role to verify the Overcloud services states after a deployment
|
||||||
|
or an update. It checks the API /os-services and looks for deprecated
|
||||||
|
services (nova-consoleauth) or any down services.
|
||||||
|
groups:
|
||||||
|
- post-deployment
|
||||||
|
- pre-upgrade
|
||||||
|
- post-upgrade
|
||||||
|
- post-overcloud-upgrade
|
||||||
|
- post-overcloud-converge
|
||||||
|
roles:
|
||||||
|
- overcloud_service_status
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Introducing the overcloud_service_status role. This role will hit the
|
||||||
|
overcloud API for nova and cinder, retrieve the services and will trig a
|
||||||
|
failure if one of these services are either down or deprecated.
|
||||||
|
The original intent was to validate that nova-consoleauth was deleted after
|
||||||
|
an update to RHOSP16.
|
47
roles/overcloud_service_status/README.md
Normal file
47
roles/overcloud_service_status/README.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Overcloud-service-status
|
||||||
|
=========================
|
||||||
|
|
||||||
|
An Ansible role to verify the Overcloud services states after a deployment or an update.
|
||||||
|
It checks the API /os-services and looks for deprecated services (nova-consoleauth) or
|
||||||
|
any down services.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
This role needs to be run on an Undercloud with a deployed Overcloud.
|
||||||
|
|
||||||
|
Role Variables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- overcloud_service_status_debug: Wether or not to log the token request
|
||||||
|
- overcloud_deprecated_services: A list of services that shouldn't be registered any more
|
||||||
|
- overcloud_service_api: overcloud API to validate against
|
||||||
|
|
||||||
|
These variables are normally set as host variables for the undercloud when generating
|
||||||
|
the inventory with tripleo-ansible-inventory:
|
||||||
|
- overcloud_keystone_url
|
||||||
|
- overcloud_admin_password
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
No dependencies.
|
||||||
|
|
||||||
|
Example Playbook
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
|
- hosts: undercloud
|
||||||
|
roles:
|
||||||
|
- { role: overcloud_service_status }
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Apache
|
||||||
|
|
||||||
|
Author Information
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Red Hat Nova Deployment Squad Team.
|
27
roles/overcloud_service_status/defaults/main.yml
Normal file
27
roles/overcloud_service_status/defaults/main.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
# 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 place placed in this file.
|
||||||
|
|
||||||
|
# All variables within this role should have a prefix of "overcloud_service_status"
|
||||||
|
overcloud_service_status_debug: false
|
||||||
|
overcloud_service_api:
|
||||||
|
- nova
|
||||||
|
- cinderv3
|
||||||
|
overcloud_deprecated_services:
|
||||||
|
nova:
|
||||||
|
- nova-consoleauth
|
37
roles/overcloud_service_status/molecule/default/Dockerfile
Normal file
37
roles/overcloud_service_status/molecule/default/Dockerfile
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Molecule managed
|
||||||
|
# Copyright 2021 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.
|
||||||
|
|
||||||
|
|
||||||
|
{% if item.registry is defined %}
|
||||||
|
FROM {{ item.registry.url }}/{{ item.image }}
|
||||||
|
{% else %}
|
||||||
|
FROM {{ item.image }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
|
||||||
|
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install sudo python*-devel python*-dnf bash {{ item.pkg_extras | default('') }} && dnf clean all; \
|
||||||
|
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl python-setuptools bash {{ item.pkg_extras | default('') }} && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
|
||||||
|
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml {{ item.pkg_extras | default('') }} && zypper clean -a; \
|
||||||
|
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates {{ item.pkg_extras | default('') }}; \
|
||||||
|
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates {{ item.pkg_extras | default('') }} && xbps-remove -O; fi
|
||||||
|
|
||||||
|
{% for pkg in item.easy_install | default([]) %}
|
||||||
|
# install pip for centos where there is no python-pip rpm in default repos
|
||||||
|
RUN easy_install {{ pkg }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
CMD ["sh", "-c", "while true; do sleep 10000; done"]
|
54
roles/overcloud_service_status/molecule/default/molecule.yml
Normal file
54
roles/overcloud_service_status/molecule/default/molecule.yml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
privileged: true
|
||||||
|
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
|
||||||
|
environment: &env
|
||||||
|
http_proxy: "{{ lookup('env', 'http_proxy') }}"
|
||||||
|
https_proxy: "{{ lookup('env', 'https_proxy') }}"
|
||||||
|
ulimits: &ulimit
|
||||||
|
- host
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
playbooks:
|
||||||
|
prepare: ../../resources/playbooks/prepare.yml
|
||||||
|
converge: ../../resources/playbooks/converge.yml
|
||||||
|
inventory:
|
||||||
|
hosts:
|
||||||
|
all:
|
||||||
|
hosts:
|
||||||
|
ubi8:
|
||||||
|
ansible_python_interpreter: /usr/bin/python3
|
||||||
|
overcloud_keystone_url: http://127.0.0.1:8080
|
||||||
|
overcloud_admin_password: hello
|
||||||
|
log: true
|
||||||
|
env:
|
||||||
|
ANSIBLE_STDOUT_CALLBACK: yaml
|
||||||
|
ANSIBLE_LIBRARY: "${ANSIBLE_LIBRARY:-/usr/share/ansible/plugins/modules}"
|
||||||
|
|
||||||
|
scenario:
|
||||||
|
test_sequence:
|
||||||
|
- destroy
|
||||||
|
- create
|
||||||
|
- prepare
|
||||||
|
- converge
|
||||||
|
- verify
|
||||||
|
- destroy
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: testinfra
|
@ -0,0 +1,37 @@
|
|||||||
|
# Molecule managed
|
||||||
|
# Copyright 2021 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.
|
||||||
|
|
||||||
|
|
||||||
|
{% if item.registry is defined %}
|
||||||
|
FROM {{ item.registry.url }}/{{ item.image }}
|
||||||
|
{% else %}
|
||||||
|
FROM {{ item.image }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
|
||||||
|
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install sudo python*-devel python*-dnf bash {{ item.pkg_extras | default('') }} && dnf clean all; \
|
||||||
|
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl python-setuptools bash {{ item.pkg_extras | default('') }} && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
|
||||||
|
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml {{ item.pkg_extras | default('') }} && zypper clean -a; \
|
||||||
|
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates {{ item.pkg_extras | default('') }}; \
|
||||||
|
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates {{ item.pkg_extras | default('') }} && xbps-remove -O; fi
|
||||||
|
|
||||||
|
{% for pkg in item.easy_install | default([]) %}
|
||||||
|
# install pip for centos where there is no python-pip rpm in default repos
|
||||||
|
RUN easy_install {{ pkg }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
CMD ["sh", "-c", "while true; do sleep 10000; done"]
|
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
privileged: true
|
||||||
|
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
|
||||||
|
environment: &env
|
||||||
|
http_proxy: "{{ lookup('env', 'http_proxy') }}"
|
||||||
|
https_proxy: "{{ lookup('env', 'https_proxy') }}"
|
||||||
|
ulimits: &ulimit
|
||||||
|
- host
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
playbooks:
|
||||||
|
prepare: ../../resources/playbooks/prepare.yml
|
||||||
|
converge: ../../resources/playbooks/converge.yml
|
||||||
|
inventory:
|
||||||
|
hosts:
|
||||||
|
all:
|
||||||
|
hosts:
|
||||||
|
ubi8:
|
||||||
|
ansible_python_interpreter: /usr/bin/python3
|
||||||
|
overcloud_keystone_url: http://127.0.0.1:8080
|
||||||
|
overcloud_admin_password: hello
|
||||||
|
log: true
|
||||||
|
env:
|
||||||
|
ANSIBLE_STDOUT_CALLBACK: yaml
|
||||||
|
ANSIBLE_LIBRARY: "${ANSIBLE_LIBRARY:-/usr/share/ansible/plugins/modules}"
|
||||||
|
|
||||||
|
scenario:
|
||||||
|
test_sequence:
|
||||||
|
- destroy
|
||||||
|
- create
|
||||||
|
- prepare
|
||||||
|
- converge
|
||||||
|
- verify
|
||||||
|
- destroy
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: testinfra
|
@ -0,0 +1,37 @@
|
|||||||
|
# Molecule managed
|
||||||
|
# Copyright 2021 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.
|
||||||
|
|
||||||
|
|
||||||
|
{% if item.registry is defined %}
|
||||||
|
FROM {{ item.registry.url }}/{{ item.image }}
|
||||||
|
{% else %}
|
||||||
|
FROM {{ item.image }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
|
||||||
|
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install sudo python*-devel python*-dnf bash {{ item.pkg_extras | default('') }} && dnf clean all; \
|
||||||
|
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl python-setuptools bash {{ item.pkg_extras | default('') }} && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
|
||||||
|
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml {{ item.pkg_extras | default('') }} && zypper clean -a; \
|
||||||
|
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates {{ item.pkg_extras | default('') }}; \
|
||||||
|
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates {{ item.pkg_extras | default('') }} && xbps-remove -O; fi
|
||||||
|
|
||||||
|
{% for pkg in item.easy_install | default([]) %}
|
||||||
|
# install pip for centos where there is no python-pip rpm in default repos
|
||||||
|
RUN easy_install {{ pkg }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
CMD ["sh", "-c", "while true; do sleep 10000; done"]
|
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
privileged: true
|
||||||
|
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
|
||||||
|
environment: &env
|
||||||
|
http_proxy: "{{ lookup('env', 'http_proxy') }}"
|
||||||
|
https_proxy: "{{ lookup('env', 'https_proxy') }}"
|
||||||
|
ulimits: &ulimit
|
||||||
|
- host
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
playbooks:
|
||||||
|
prepare: ../../resources/playbooks/prepare.yml
|
||||||
|
converge: ../../resources/playbooks/converge.yml
|
||||||
|
inventory:
|
||||||
|
hosts:
|
||||||
|
all:
|
||||||
|
hosts:
|
||||||
|
ubi8:
|
||||||
|
ansible_python_interpreter: /usr/bin/python3
|
||||||
|
overcloud_keystone_url: http://127.0.0.1:8080
|
||||||
|
overcloud_admin_password: hello
|
||||||
|
log: true
|
||||||
|
env:
|
||||||
|
ANSIBLE_STDOUT_CALLBACK: yaml
|
||||||
|
ANSIBLE_LIBRARY: "${ANSIBLE_LIBRARY:-/usr/share/ansible/plugins/modules}"
|
||||||
|
|
||||||
|
scenario:
|
||||||
|
test_sequence:
|
||||||
|
- destroy
|
||||||
|
- create
|
||||||
|
- prepare
|
||||||
|
- converge
|
||||||
|
- verify
|
||||||
|
- destroy
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: testinfra
|
1
roles/overcloud_service_status/resources/README.md
Normal file
1
roles/overcloud_service_status/resources/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Shared resources used for molecule unit testing
|
@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
# 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
|
||||||
|
tasks:
|
||||||
|
- block:
|
||||||
|
- name: "Include overcloud_service_status role"
|
||||||
|
include_role:
|
||||||
|
name: "overcloud_service_status"
|
||||||
|
rescue:
|
||||||
|
- fail:
|
||||||
|
msg: "Default test failed"
|
||||||
|
when: molecule_yml.scenario.name == "default"
|
||||||
|
- set_fact:
|
||||||
|
output_var: "{{ lookup('vars', molecule_yml.scenario.name + '_output')}}"
|
||||||
|
- fail:
|
||||||
|
msg: "No {{ molecule_yml.scenario.name }} found"
|
||||||
|
when: "'failed' not in output_var"
|
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
- name: Prepare
|
||||||
|
hosts: all
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Copy http_server.py
|
||||||
|
copy:
|
||||||
|
src: ../scripts/http_server.py
|
||||||
|
dest: /
|
||||||
|
|
||||||
|
- name: "Start http_server.py scenario {{ molecule_yml.scenario.name }}"
|
||||||
|
shell: cd /; nohup python3 /http_server.py --scenario {{ molecule_yml.scenario.name }} > http_server.log 2>&1 &
|
173
roles/overcloud_service_status/resources/scripts/http_server.py
Normal file
173
roles/overcloud_service_status/resources/scripts/http_server.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Simple http server to mock a keystone token and service list.
|
||||||
|
If arguments are passed, they will either set the services as down
|
||||||
|
or create additionnal services.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
./http_server.py --scenario default
|
||||||
|
- will return services based on the 'services' dict below.
|
||||||
|
|
||||||
|
./http_server.py --scenario deprecated_services
|
||||||
|
- will return services based on the 'services' dict below, as well
|
||||||
|
as a nova-consoleauth service.
|
||||||
|
|
||||||
|
./http_server.py --scenario down_services
|
||||||
|
- will return services based on the 'services' dict below, as well
|
||||||
|
as marking one of the services as down.
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
from datetime import datetime
|
||||||
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
|
import json
|
||||||
|
|
||||||
|
server_port = 8080
|
||||||
|
server_url = "http://127.0.0.1"
|
||||||
|
|
||||||
|
# List of services to mock
|
||||||
|
# Controllers are going to be created 3 times, computes and hostgroups once
|
||||||
|
services = {
|
||||||
|
"nova": {
|
||||||
|
"controller": ["nova-scheduler", "nova-conductor"],
|
||||||
|
"compute": ["nova-compute"],
|
||||||
|
},
|
||||||
|
"cinder": {
|
||||||
|
"controller": ["cinder-scheduler"],
|
||||||
|
"hostgroup": ["cinder-volume"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="mocking keystone and os-service calls")
|
||||||
|
parser.add_argument(
|
||||||
|
"--scenario",
|
||||||
|
action="store",
|
||||||
|
default="default",
|
||||||
|
help="Scenario to reproduce",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
class S(BaseHTTPRequestHandler):
|
||||||
|
def _set_response(self, code=200, **kwargs):
|
||||||
|
self.send_response(code)
|
||||||
|
self.send_header("Content-type", "application/json; charset=utf-8")
|
||||||
|
for key, val in kwargs.items():
|
||||||
|
self.send_header(key, val)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
def _write_body(self, text):
|
||||||
|
self.wfile.write(text.encode("utf-8"))
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
self._set_response()
|
||||||
|
path_split = self.path.split("/")
|
||||||
|
self._write_body(self._generate_services(path_split[1]))
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
content_length = int(self.headers["Content-Length"])
|
||||||
|
self._set_response(201, x_subject_token=123)
|
||||||
|
self._write_body(self._generate_token())
|
||||||
|
|
||||||
|
def _generate_services(self, service):
|
||||||
|
data = {"services": []}
|
||||||
|
svc = services[service]
|
||||||
|
for key, binaries in svc.items():
|
||||||
|
number_of_nodes = 3 if key == "controller" else 1
|
||||||
|
for i in range(number_of_nodes):
|
||||||
|
for binary in binaries:
|
||||||
|
data["services"].append(
|
||||||
|
self._generate_service(binary, f"{key}-{i}.redhat.local")
|
||||||
|
)
|
||||||
|
# NOTE(dvd): yeah this is ugly and won't work if we remove nova-consoleauth
|
||||||
|
# from overcloud_deprecated_services. We should probably just
|
||||||
|
# pass the overcloud_deprecated_services list as an argument to
|
||||||
|
# to make this future proof
|
||||||
|
if service == "nova" and args.scenario == "deprecated_services":
|
||||||
|
data["services"].extend(
|
||||||
|
[
|
||||||
|
self._generate_service(
|
||||||
|
"nova-consoleauth", "controller-0.redhat.local"
|
||||||
|
),
|
||||||
|
self._generate_service(
|
||||||
|
"nova-consoleauth", "controller-1.redhat.local", "disabled"
|
||||||
|
),
|
||||||
|
self._generate_service(
|
||||||
|
"nova-consoleauth",
|
||||||
|
"controller-2.redhat.local",
|
||||||
|
"enabled",
|
||||||
|
"down",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if args.scenario == "down_services":
|
||||||
|
data["services"][0]["state"] = "down"
|
||||||
|
|
||||||
|
return json.dumps(data)
|
||||||
|
|
||||||
|
def _generate_service(self, binary, host, status="enabled", state="up"):
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
return {
|
||||||
|
"binary": binary,
|
||||||
|
"host": host,
|
||||||
|
"status": status,
|
||||||
|
"state": state,
|
||||||
|
"updated_at": now,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _generate_token(self):
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
data = {
|
||||||
|
"token": {
|
||||||
|
"catalog": [
|
||||||
|
{
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"url": f"{server_url}:{server_port}/cinder",
|
||||||
|
"interface": "admin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": f"{server_url}:{server_port}/cinder",
|
||||||
|
"interface": "admin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": f"{server_url}:{server_port}/cinder",
|
||||||
|
"interface": "admin",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "cinderv3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"url": f"{server_url}:{server_port}/nova",
|
||||||
|
"interface": "admin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": f"{server_url}:{server_port}/nova",
|
||||||
|
"interface": "admin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": f"{server_url}:{server_port}/nova",
|
||||||
|
"interface": "admin",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "nova",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json.dumps(data)
|
||||||
|
|
||||||
|
|
||||||
|
def run(server_class=HTTPServer, handler_class=S, port=server_port):
|
||||||
|
server_address = ("", port)
|
||||||
|
httpd = server_class(server_address, handler_class)
|
||||||
|
try:
|
||||||
|
httpd.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run()
|
48
roles/overcloud_service_status/tasks/main.yml
Normal file
48
roles/overcloud_service_status/tasks/main.yml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
# Copyright 2021 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: Geting a system scoped Keystone token
|
||||||
|
no_log: "{{ not overcloud_service_status_debug | bool }}"
|
||||||
|
uri:
|
||||||
|
url: "{{ overcloud_keystone_url | urlsplit('scheme') }}://{{ overcloud_keystone_url | urlsplit('netloc') }}/v3/auth/tokens"
|
||||||
|
method: POST
|
||||||
|
body_format: json
|
||||||
|
body:
|
||||||
|
auth:
|
||||||
|
identity:
|
||||||
|
methods:
|
||||||
|
- password
|
||||||
|
password:
|
||||||
|
user:
|
||||||
|
password: "{{ overcloud_admin_password }}"
|
||||||
|
name: admin
|
||||||
|
domain:
|
||||||
|
id: default
|
||||||
|
scope:
|
||||||
|
project:
|
||||||
|
name: admin
|
||||||
|
domain:
|
||||||
|
name: Default
|
||||||
|
return_content: true
|
||||||
|
status_code: 201
|
||||||
|
register: auth_token
|
||||||
|
when: overcloud_keystone_url|default('')
|
||||||
|
|
||||||
|
- name: Checking openstack services
|
||||||
|
include_tasks: tasks/os_service.yml
|
||||||
|
loop: "{{ overcloud_service_api }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: os_service
|
82
roles/overcloud_service_status/tasks/os_service.yml
Normal file
82
roles/overcloud_service_status/tasks/os_service.yml
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
# Copyright 2021 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: Extracting the endpoint url
|
||||||
|
set_fact:
|
||||||
|
endpoint: "{{ catalog.endpoints|selectattr('interface', 'eq', 'admin')|first }}"
|
||||||
|
loop: "{{ auth_token.json.token.catalog }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: catalog
|
||||||
|
when: catalog.name == os_service
|
||||||
|
|
||||||
|
- fail:
|
||||||
|
msg: "No endpoint found for {{ os_service }} interface admin in catalog"
|
||||||
|
when: endpoint is not defined
|
||||||
|
|
||||||
|
- name: Get services
|
||||||
|
uri:
|
||||||
|
url: "{{ endpoint.url }}/os-services"
|
||||||
|
method: GET
|
||||||
|
headers:
|
||||||
|
Accept: application/json
|
||||||
|
X-Auth-Token: "{{ auth_token.x_subject_token }}"
|
||||||
|
return_content: true
|
||||||
|
status_code: 200
|
||||||
|
register: os_services
|
||||||
|
|
||||||
|
- name: Verifying deprecated services are absent
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- service[0].binary != service[1]
|
||||||
|
fail_msg: "{{ service[0].binary }} should be removed on {{ service[0].host }}"
|
||||||
|
loop: "{{ os_services.json.services | product(overcloud_deprecated_services[os_service]) | list }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: service
|
||||||
|
when: os_service in overcloud_deprecated_services
|
||||||
|
register: deprecated_services_output
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Verifying all services are up
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- (service.state == "up" and service.status == "enabled") or service.status == "disabled"
|
||||||
|
fail_msg: "{{ service.binary }} on {{ service.host }} is problematic (service state is {{ service.state }} while it's {{ service.status }})"
|
||||||
|
loop: "{{ os_services.json.services }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: service
|
||||||
|
register: down_services_output
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Asserted failure
|
||||||
|
fail:
|
||||||
|
msg: |
|
||||||
|
At least one of the assertion failed.
|
||||||
|
{% if 'failed' in deprecated_services_output %}
|
||||||
|
{% for service in deprecated_services_output.results %}
|
||||||
|
{% if service.failed %}
|
||||||
|
{{ service.msg }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'failed' in down_services_output %}
|
||||||
|
{% for service in down_services_output.results %}
|
||||||
|
{% if service.failed %}
|
||||||
|
{{ service.msg }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
when: "'failed' in deprecated_services_output or 'failed' in down_services_output"
|
32
roles/overcloud_service_status/vars/main.yml
Normal file
32
roles/overcloud_service_status/vars/main.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
# Copyright 2021 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.
|
||||||
|
|
||||||
|
|
||||||
|
# While options found within the vars/ path can be overridden using extra
|
||||||
|
# vars, items within this path are considered part of the role and not
|
||||||
|
# intended to be modified.
|
||||||
|
metadata:
|
||||||
|
name: Verify overcloud services state after running a deployment or an update
|
||||||
|
description: >
|
||||||
|
An Ansible role to verify the Overcloud services states after a deployment
|
||||||
|
or an update. It checks the API /os-services and looks for deprecated
|
||||||
|
services (nova-consoleauth) or any down services.
|
||||||
|
groups:
|
||||||
|
- post-deployment
|
||||||
|
- pre-upgrade
|
||||||
|
- post-upgrade
|
||||||
|
- post-overcloud-upgrade
|
||||||
|
- post-overcloud-converge
|
@ -14,6 +14,7 @@
|
|||||||
- tripleo-validations-centos-8-molecule-image_serve
|
- tripleo-validations-centos-8-molecule-image_serve
|
||||||
- tripleo-validations-centos-8-molecule-nova_status
|
- tripleo-validations-centos-8-molecule-nova_status
|
||||||
- tripleo-validations-centos-8-molecule-nova_svirt
|
- tripleo-validations-centos-8-molecule-nova_svirt
|
||||||
|
- tripleo-validations-centos-8-molecule-overcloud_service_status
|
||||||
- tripleo-validations-centos-8-molecule-package_version
|
- tripleo-validations-centos-8-molecule-package_version
|
||||||
- tripleo-validations-centos-8-molecule-rabbitmq_limits
|
- tripleo-validations-centos-8-molecule-rabbitmq_limits
|
||||||
- tripleo-validations-centos-8-molecule-repos
|
- tripleo-validations-centos-8-molecule-repos
|
||||||
@ -36,6 +37,7 @@
|
|||||||
- tripleo-validations-centos-8-molecule-frr_status
|
- tripleo-validations-centos-8-molecule-frr_status
|
||||||
- tripleo-validations-centos-8-molecule-nova_status
|
- tripleo-validations-centos-8-molecule-nova_status
|
||||||
- tripleo-validations-centos-8-molecule-nova_svirt
|
- tripleo-validations-centos-8-molecule-nova_svirt
|
||||||
|
- tripleo-validations-centos-8-molecule-overcloud_service_status
|
||||||
- tripleo-validations-centos-8-molecule-package_version
|
- tripleo-validations-centos-8-molecule-package_version
|
||||||
- tripleo-validations-centos-8-molecule-rabbitmq_limits
|
- tripleo-validations-centos-8-molecule-rabbitmq_limits
|
||||||
- tripleo-validations-centos-8-molecule-repos
|
- tripleo-validations-centos-8-molecule-repos
|
||||||
@ -339,3 +341,10 @@
|
|||||||
parent: tripleo-validations-centos-8-base
|
parent: tripleo-validations-centos-8-base
|
||||||
vars:
|
vars:
|
||||||
tripleo_validations_role_name: check_undercloud_conf
|
tripleo_validations_role_name: check_undercloud_conf
|
||||||
|
- job:
|
||||||
|
files:
|
||||||
|
- ^roles/overcloud_service_status/.*
|
||||||
|
name: tripleo-validations-centos-8-molecule-overcloud_service_status
|
||||||
|
parent: tripleo-validations-centos-8-base
|
||||||
|
vars:
|
||||||
|
tripleo_validations_role_name: overcloud_service_status
|
||||||
|
Loading…
x
Reference in New Issue
Block a user