Add Nova flavor registration

This commit is contained in:
Will Miller 2018-09-06 16:53:20 +00:00
parent c8e4681c28
commit 8d02c28e5a
7 changed files with 115 additions and 3 deletions

View File

@ -7,3 +7,6 @@
- name: Enrol nodes in Ironic
import_playbook: enrol_nodes.yml
- name: Register flavors in Nova
import_playbook: register_flavors.yml

View File

@ -51,20 +51,24 @@ node_types: {}
specs: []
# nova_flavors is a list of Nova flavors to be created. Each flavor must
# specify the resource class it is associated with. This resource class must
# be referenced in `specs`.
#
# specify the resource class it is associated with, as well as the Tenks node
# type whose hardware specs should be used.
# For example:
#
# nova_flavors:
# # Required.
# - resource_class: my_rc
# # Required.
# node_type: type0
# # Defaults to `resource_class`.
# name: my_flavor
# # Optional, defaults to [].
# required_traits: []
# # Optional, defaults to [].
# forbidden_traits: []
# # Extra key-value pairs to add to the flavor's specs. Optional, defaults
# # to {}.
# custom_specs: {}
nova_flavors: []
# The Glance UUID of the image to use for the deployment kernel.

View File

@ -0,0 +1,11 @@
---
- hosts: localhost
tasks:
- name: Register Nova flavors
include_role:
name: nova-flavors
vars:
flavors_virtualenv_path: "{{ virtualenv_path }}"
flavors_python_upper_constraints_url: >-
{{ python_upper_constraints_url }}
flavors: "{{ nova_flavors }}"

View File

@ -0,0 +1,21 @@
Nova Flavors
============
This role creates flavors in Nova.
Requirements
------------
- *OS_\** environment variables for the OpenStack cloud in question present in
the shell environment. These can be sourced from an OpenStack RC file, for
example.
Role Variables
--------------
- `flavors`: A list of dicts of details for flavors that are to be created. The
format for this is detailed in `defaults/main.yml`.
- `flavors_virtualenv_path`: The path to the virtualenv in which to install the
OpenStack clients.
- `flavors_python_upper_constraints_url`: The URL of the upper constraints file
to pass to pip when installing Python packages.

View File

@ -0,0 +1,25 @@
---
# A list of Nova flavors to create.
# For example:
#
# flavors:
# # Required.
# - resource_class: my_rc
# # Required.
# node_type: type0
# # Defaults to `resource_class`.
# name: my_flavor
# # Optional, defaults to [].
# required_traits: []
# # Optional, defaults to [].
# forbidden_traits: []
# # Extra key-value pairs to add to the flavor's specs. Optional, defaults
# # to {}.
# custom_specs: {}
flavors: []
# The path to the virtualenv in which to install the OpenStack clients.
flavors_virtualenv_path:
# The URL of the upper constraints file to pass to pip when installing Python
# packages.
flavors_python_upper_constraints_url:

View File

@ -0,0 +1,4 @@
# This file contains the Python packages that are needed in the Tenks virtual
# env.
openstacksdk>=0.17.2 # Apache

View File

@ -0,0 +1,44 @@
---
- name: Ensure Python requirements are installed
pip:
requirements: "{{ '/'.join([role_path, 'files', 'requirements.txt']) }}"
extra_args: >-
-c {{ flavors_python_upper_constraints_url }}
virtualenv: "{{ flavors_virtualenv_path }}"
- name: Register Nova flavors
os_nova_flavor:
auth_type: password
name: "{{ item.name | default(item.resource_class) }}"
# FIXME(w-miller): don't necessarily assume the first disk?
disk: "{{ node_types[item.node_type].volumes.0.capacity | default('0')
| size_string_to_gb }}"
ram: "{{ node_types[item.node_type].memory_mb }}"
vcpus: "{{ node_types[item.node_type].vcpus }}"
# NOTE(w-miller): I'm not quite sure whether this is janky or beautiful.
#
# * Set hardware specs to zero here for scheduling purposes.
# * Add the resource class name.
# * Add required and forbidden traits.
# * Add any custom specs from the user.
extra_specs: >-
{{ {
"resources:DISK_GB": 0,
"resources:MEMORY_MB": 0,
"resources:VCPU": 0,
"resources:CUSTOM_" ~ (
item.resource_class | upper
| regex_replace('[^A-Za-z0-9]', '_')): 1
}
| combine(dict(item.required_traits | default([])
| map('regex_replace', '(.*)', 'trait:\1')
| zip_longest([], fillvalue='required')))
| combine(dict(item.forbidden_traits | default([])
| map('regex_replace', '(.*)', 'trait:\1')
| zip_longest([], fillvalue='forbidden')))
| combine(item.custom_specs | default({}))
}}
vars:
ansible_python_interpreter: >-
{{ '/'.join([flavors_virtualenv_path, 'bin', 'python']) }}
loop: "{{ flavors }}"