Add validation for checking node counts

This validation checks that available nodes is sufficient for what is
requested.

Change-Id: I1f3266275c39e093ddae18f93185eff3e4f74675
Implements: blueprint workflow-move-validations
Closes-Bug: #1632704
This commit is contained in:
Brad P. Crochet 2018-04-20 11:13:18 -04:00
parent af792d02e5
commit 9cf1f893d6
4 changed files with 140 additions and 2 deletions

View File

@ -16,12 +16,13 @@
# under the License.
from __future__ import print_function
from six import string_types
import collections
from keystoneauth1.identity import generic as ks_id
from keystoneauth1 import session
from six import string_types
from novaclient import client as nova_client
from swiftclient.client import Connection
@ -50,6 +51,17 @@ def get_swift_client(preauthurl, preauthtoken):
max_backoff=120)
def get_nova_client(auth_variables):
auth_url = auth_variables.get('auth_url')
username = auth_variables.get('username')
project_name = auth_variables.get('project_name')
token = auth_variables.get('os_auth_token')
session = get_auth_session(auth_url, username, project_name,
auth_token=token)
return nova_client.Client(2, session=session)
def filtered(obj):
"""Only return properties of obj whose value can be properly serialized."""
return {k: v for k, v in obj.__dict__.items()

View File

@ -0,0 +1,50 @@
---
- hosts: undercloud
vars:
metadata:
name: Verify hypervisor statistics
description: >
This validation checks that the nodes and hypervisor statistics
add up.
groups:
- pre-deployment
tasks:
- name: Retrieve the hypervisor statistics
set_fact:
statistics: "{{ lookup('nova_hypervisor_statistics', wantlist=True) }}"
- name: Get default role counts
set_fact:
roles_info: "{{ lookup('roles_info', wantlist=True) }}"
- name: Set requested count
set_fact:
requested_count: "{{ roles_info|sum(attribute='count') }}"
- name: Get associated nodes
set_fact:
associated_nodes: "{{ lookup('ironic_nodes', 'associated', wantlist=True) }}"
- name: Get available nodes
set_fact:
available_nodes: "{{ lookup('ironic_nodes', 'provision_state', ['available'], wantlist=True) }}"
- name: Set count of available nodes
set_fact:
available_count: "{{ ((associated_nodes|length) + (available_nodes|length))|int }}"
- name: Fail when requested is more than available
fail:
msg: >
Not enough baremetal nodes - available: {{ available_count }},
requested: {{ requested_count }}
failed_when: requested_count|int > available_count|int
- name: Fail when hypervisor count is less than available count
fail:
msg: >
Only {{ statistics.count }} nodes are exposed to Nova of
{{ available_count }} requests. Check that enough nodes are
in 'available' state with maintenance mode off.
failed_when: statistics.count < available_count|int

View File

@ -42,10 +42,22 @@ EXAMPLES = """
- name: Get all nodes for a set of instance UUIDs
debug:
msg: |
{{ lookup(''ironic_nodes', 'instance_uuid',
{{ lookup('ironic_nodes', 'instance_uuid',
['1691a1c7-9974-4bcc-a07a-5dec7fc04da0',
'07f2435d-820c-46ce-9097-cf8a7282293e'],
wantlist=True) }}"
- name: Get all nodes marked as 'associated'
debug:
msg: |
{{ lookup('ironic_nodes', 'associated',
wantlist=True) }}"
- name: Get nodes in provision state, and not associated or in maintenance
debug:
msg: |
{{ lookup('ironic_nodes', 'provision_state',
['available', 'inspect'], wantlist=True)}}
"""
RETURN = """
@ -82,6 +94,18 @@ class LookupModule(LookupBase):
nodes = [ironic.node.get_by_instance_uuid(uuid)
for uuid in terms[1]]
return [utils.filtered(node) for node in nodes]
elif terms[0] == 'associated':
nodes = ironic.node.list(associated=True, detail=True)
return [utils.filtered(node) for node in nodes]
elif terms[0] == 'provision_state':
nodes = []
for term in terms[1]:
nodes.extend(ironic.node.list(
provision_state=term,
associated=False,
maintenance=False,
detail=True))
return [utils.filtered(node) for node in nodes]
else:
return [utils.filtered(node)
for node in ironic.node.list(detail=True)]

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
# Copyright 2018 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 ansible.plugins.lookup import LookupBase
from tripleo_validations import utils
DOCUMENTATION = """
lookup: nova_hypervisor_statistics
description: Retrieve hypervisor statistic information from Nova
long_description:
- Load hypervisor statistics using the Nova API.
author: Brad P. Crochet <brad@redhat.com>
"""
EXAMPLES = """
- name: Get all hypervisor statistics from nova
debug:
msg: |
{{ lookup('nova_hypervisor_statistics') }}
"""
RETURN = """
_raw:
description: A Python list with results from the API call.
"""
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
"""Returns server information from nova."""
nova = utils.get_nova_client(variables)
statistics = nova.hypervisor_stats.statistics()
return utils.filtered(statistics)