Merge pull request #97 from markgoddard/remote-virtualenvs
Add support for virtual environments for remote execution
This commit is contained in:
commit
3736b46b01
@ -22,6 +22,10 @@
|
||||
- name: Ensure baremetal compute nodes are powered off
|
||||
command: ipmitool -U {{ ipmi_username }} -P {{ ipmi_password }} -H {{ ipmi_address }} -I lanplus chassis power off
|
||||
delegate_to: "{{ controller_host }}"
|
||||
failed_when:
|
||||
- result | failed
|
||||
# Some BMCs complain if the node is already powered off.
|
||||
- "'Command not supported in present state' not in result.stderr"
|
||||
vars:
|
||||
# NOTE: Without this, the controller's ansible_host variable will not
|
||||
# be respected when using delegate_to.
|
||||
|
@ -250,6 +250,10 @@ kolla_overcloud_inventory_kolla_top_level_groups:
|
||||
###############################################################################
|
||||
# Kolla-ansible configuration.
|
||||
|
||||
# Virtualenv directory where Kolla-ansible's ansible modules will execute
|
||||
# remotely on the target nodes. If None, no virtualenv will be used.
|
||||
kolla_ansible_target_venv: "{{ virtualenv_path ~ '/kolla-ansible' }}"
|
||||
|
||||
# Password to use to encrypt the kolla-ansible passwords.yml file.
|
||||
kolla_ansible_vault_password: "{{ lookup('env', 'KAYOBE_VAULT_PASSWORD') | default }}"
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
hosts: seed:overcloud
|
||||
vars:
|
||||
ansible_user: "{{ bootstrap_user }}"
|
||||
# We can't assume that a virtualenv exists at this point, so use the system
|
||||
# python interpreter.
|
||||
ansible_python_interpreter: /usr/bin/python
|
||||
roles:
|
||||
- role: singleplatform-eng.users
|
||||
users:
|
||||
|
54
ansible/kayobe-target-venv.yml
Normal file
54
ansible/kayobe-target-venv.yml
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
# Create a virtualenv for ansible modules to use on the remote target systems
|
||||
# when running kayobe.
|
||||
|
||||
- name: Ensure a virtualenv exists for kayobe
|
||||
hosts: seed:seed-hypervisor:overcloud
|
||||
gather_facts: False
|
||||
tags:
|
||||
- kayobe-target-venv
|
||||
tasks:
|
||||
- name: Set a fact about the kayobe target virtualenv
|
||||
set_fact:
|
||||
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
|
||||
when:
|
||||
- ansible_python_interpreter is defined
|
||||
- not ansible_python_interpreter.startswith('/bin')
|
||||
- not ansible_python_interpreter.startswith('/usr/bin')
|
||||
|
||||
- block:
|
||||
# This will cause ansible to use the system python interpreter.
|
||||
- name: Deactivate the virtualenv
|
||||
include_role:
|
||||
name: deactivate-virtualenv
|
||||
|
||||
- name: Ensure the python-virtualenv package is installed
|
||||
package:
|
||||
name: python-virtualenv
|
||||
state: installed
|
||||
become: True
|
||||
|
||||
- name: Ensure kayobe virtualenv directory exists
|
||||
file:
|
||||
path: "{{ virtualenv }}"
|
||||
state: directory
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: 0700
|
||||
become: True
|
||||
|
||||
- name: Ensure kayobe virtualenv has the latest version of pip installed
|
||||
pip:
|
||||
name: pip
|
||||
state: latest
|
||||
virtualenv: "{{ virtualenv }}"
|
||||
# Site packages are required for using the yum and selinux python
|
||||
# modules, which are not available via PyPI.
|
||||
virtualenv_site_packages: True
|
||||
|
||||
- name: Activate the virtualenv
|
||||
include_role:
|
||||
name: activate-virtualenv
|
||||
vars:
|
||||
activate_virtualenv_path: "{{ virtualenv }}"
|
||||
when: virtualenv is defined
|
44
ansible/kolla-target-venv.yml
Normal file
44
ansible/kolla-target-venv.yml
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
# Create a virtualenv for ansible modules to use on the remote target systems
|
||||
# when running kolla-ansible.
|
||||
|
||||
- name: Ensure a virtualenv exists for kolla-ansible
|
||||
hosts: seed:seed-hypervisor:overcloud
|
||||
gather_facts: False
|
||||
tags:
|
||||
- kolla-ansible
|
||||
- kolla-target-venv
|
||||
tasks:
|
||||
- block:
|
||||
- name: Ensure the python-virtualenv package is installed
|
||||
package:
|
||||
name: python-virtualenv
|
||||
state: installed
|
||||
become: True
|
||||
|
||||
- name: Ensure kolla-ansible virtualenv has the latest version of pip installed
|
||||
pip:
|
||||
name: pip
|
||||
state: latest
|
||||
virtualenv: "{{ kolla_ansible_target_venv }}"
|
||||
# Site packages are required for using the yum and selinux python
|
||||
# modules, which are not available via PyPI.
|
||||
virtualenv_site_packages: True
|
||||
become: True
|
||||
|
||||
- name: Ensure kolla-ansible virtualenv has docker SDK for python installed
|
||||
pip:
|
||||
name: docker
|
||||
state: latest
|
||||
virtualenv: "{{ kolla_ansible_target_venv }}"
|
||||
become: True
|
||||
|
||||
- name: Ensure kolla-ansible virtualenv has correct ownership
|
||||
file:
|
||||
path: "{{ kolla_ansible_target_venv }}"
|
||||
recurse: True
|
||||
state: directory
|
||||
owner: kolla
|
||||
group: kolla
|
||||
become: True
|
||||
when: kolla_ansible_target_venv is not none
|
@ -5,14 +5,24 @@
|
||||
# Docker renamed their python SDK from docker-py to docker in the 2.0.0
|
||||
# release, and also broke backwards compatibility. Kolla-ansible requires
|
||||
# docker, so ensure it is installed.
|
||||
- name: Set a fact about the virtualenv on the remote system
|
||||
set_fact:
|
||||
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
|
||||
when:
|
||||
- ansible_python_interpreter is defined
|
||||
- not ansible_python_interpreter.startswith('/bin/')
|
||||
- not ansible_python_interpreter.startswith('/usr/bin/')
|
||||
|
||||
- name: Ensure legacy docker-py python package is uninstalled
|
||||
pip:
|
||||
name: docker-py
|
||||
state: absent
|
||||
become: True
|
||||
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
|
||||
become: "{{ virtualenv is not defined }}"
|
||||
|
||||
- name: Ensure docker SDK for python is installed
|
||||
pip:
|
||||
name: docker
|
||||
state: latest
|
||||
become: True
|
||||
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
|
||||
become: "{{ virtualenv is not defined }}"
|
||||
|
@ -6,6 +6,21 @@
|
||||
include 'devicemapper' and 'overlay'.
|
||||
when: docker_storage_driver not in ['devicemapper', 'overlay']
|
||||
|
||||
- name: Set a fact about the virtualenv on the remote system
|
||||
set_fact:
|
||||
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
|
||||
when:
|
||||
- ansible_python_interpreter is defined
|
||||
- not ansible_python_interpreter.startswith('/bin/')
|
||||
- not ansible_python_interpreter.startswith('/usr/bin/')
|
||||
|
||||
- name: Ensure docker SDK for python is installed
|
||||
pip:
|
||||
name: docker
|
||||
state: latest
|
||||
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
|
||||
become: "{{ virtualenv is not defined }}"
|
||||
|
||||
- name: Ensure user is in the docker group
|
||||
user:
|
||||
name: "{{ ansible_user_id }}"
|
||||
|
@ -29,11 +29,11 @@
|
||||
- "{{ ipa_images_ramdisk_name }}"
|
||||
register: ipa_images_checksum
|
||||
|
||||
# Note that setting this via a play or task variable seems to not
|
||||
# evaluate the Jinja variable reference, so we use set_fact.
|
||||
- name: Update the Ansible python interpreter fact to point to the virtualenv
|
||||
set_fact:
|
||||
ansible_python_interpreter: "{{ ipa_images_venv }}/bin/python"
|
||||
- name: Activate the virtualenv
|
||||
include_role:
|
||||
name: activate-virtualenv
|
||||
vars:
|
||||
activate_virtualenv_path: "{{ ipa_images_venv }}"
|
||||
|
||||
# To support updating the IPA image, we check the MD5 sum of the cached image
|
||||
# files, and compare with the images in Glance (if there are any).
|
||||
@ -92,8 +92,6 @@
|
||||
- name: "{{ ipa_images_ramdisk_name }}"
|
||||
format: ari
|
||||
|
||||
# This variable is unset before we set it, and it does not appear to be
|
||||
# possible to unset a variable in Ansible.
|
||||
- name: Set a fact to reset the Ansible python interpreter
|
||||
set_fact:
|
||||
ansible_python_interpreter: /usr/bin/python
|
||||
- name: Deactivate the virtualenv
|
||||
include_role:
|
||||
name: deactivate-virtualenv
|
||||
|
@ -8,9 +8,11 @@
|
||||
with_items:
|
||||
- name: python-ironic-inspector-client
|
||||
|
||||
- name: Set a fact to ensure Ansible uses the python interpreter in the virtualenv
|
||||
set_fact:
|
||||
ansible_python_interpreter: "{{ ironic_inspector_venv }}/bin/python"
|
||||
- name: Activate the virtualenv
|
||||
include_role:
|
||||
name: activate-virtualenv
|
||||
vars:
|
||||
activate_virtualenv_path: "{{ ironic_inspector_venv }}"
|
||||
|
||||
- name: Ensure introspection rules exist
|
||||
os_ironic_inspector_rule:
|
||||
@ -24,8 +26,6 @@
|
||||
inspector_url: "{{ ironic_inspector_url }}"
|
||||
with_items: "{{ ironic_inspector_rules }}"
|
||||
|
||||
# This variable is unset before we set it, and it does not appear to be
|
||||
# possible to unset a variable in Ansible.
|
||||
- name: Set a fact to reset the Ansible python interpreter
|
||||
set_fact:
|
||||
ansible_python_interpreter: /usr/bin/python
|
||||
- name: Deactivate the virtualenv
|
||||
include_role:
|
||||
name: deactivate-virtualenv
|
||||
|
@ -15,6 +15,10 @@ kolla_ansible_source_version:
|
||||
# Virtualenv directory where Kolla-ansible will be installed.
|
||||
kolla_ansible_venv: "{{ ansible_env['PWD'] }}/kolla-venv"
|
||||
|
||||
# Virtualenv directory where Kolla-ansible's ansible modules will execute
|
||||
# remotely on the target nodes. If None, no virtualenv will be used.
|
||||
kolla_ansible_target_venv:
|
||||
|
||||
# Password to use to encrypt the passwords.yml file.
|
||||
kolla_ansible_vault_password:
|
||||
|
||||
|
@ -30,6 +30,11 @@
|
||||
[overcloud:vars]
|
||||
ansible_user=kolla
|
||||
ansible_become=true
|
||||
{% if kolla_ansible_target_venv is not none %}
|
||||
# Execute ansible modules on the remote target hosts using a virtualenv.
|
||||
ansible_python_interpreter={{ kolla_ansible_target_venv }}/bin/python
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% for kolla_group, kolla_group_config in kolla_overcloud_inventory_top_level_group_map.items() %}
|
||||
{% if 'groups' in kolla_group_config %}
|
||||
|
@ -5,4 +5,6 @@
|
||||
# Install Kolla Ansible from PyPI.
|
||||
kolla-ansible=={{ kolla_openstack_release }}
|
||||
{% endif %}
|
||||
# Limit the version of ansible used by kolla-ansible to avoid new releases from
|
||||
# breaking tested code. Changes to this limit should be tested.
|
||||
ansible<2.4
|
||||
|
@ -7,6 +7,10 @@
|
||||
|
||||
[seed:vars]
|
||||
ansible_user=kolla
|
||||
{% if kolla_ansible_target_venv is not none %}
|
||||
# Execute ansible modules on the remote target hosts using a virtualenv.
|
||||
ansible_python_interpreter={{ kolla_ansible_target_venv }}/bin/python
|
||||
{% endif %}
|
||||
|
||||
[baremetal:children]
|
||||
seed
|
||||
|
@ -115,3 +115,19 @@ configuration files may be encrypted. Since encryption can make working with
|
||||
Kayobe difficult, it is recommended to follow `best practice
|
||||
<http://docs.ansible.com/ansible/playbooks_best_practices.html#best-practices-for-variables-and-vaults>`_,
|
||||
adding a layer of indirection and using encryption only where necessary.
|
||||
|
||||
Remote Execution Environment
|
||||
----------------------------
|
||||
|
||||
By default, ansible executes modules remotely using the system python
|
||||
interpreter, even if the ansible control process is executed from within a
|
||||
virtual environment (unless the ``local`` connection plugin is used).
|
||||
This is not ideal if there are python dependencies that must be installed
|
||||
without isolation from the system python packages. Ansible can be configured to
|
||||
use a virtualenv by setting the host variable ``ansible_python_interpreter``
|
||||
to a path to a python interpreter in an existing virtual environment.
|
||||
|
||||
If kayobe detects that ``ansible_python_interpreter`` is set and references a
|
||||
virtual environment, it will create the virtual environment if it does not
|
||||
exist. Typically this variable should be set via a group variable for hosts in
|
||||
the ``seed``, ``seed-hypervisor``, and/or ``overcloud`` groups.
|
||||
|
@ -27,6 +27,23 @@ kolla-ansible is installed and executed.
|
||||
the kolla-ansible virtualenv will be created.
|
||||
====================== ================================================== ============================
|
||||
|
||||
Remote Execution Environment
|
||||
============================
|
||||
|
||||
By default, ansible executes modules remotely using the system python
|
||||
interpreter, even if the ansible control process is executed from within a
|
||||
virtual environment (unless the ``local`` connection plugin is used).
|
||||
This is not ideal if there are python dependencies that must be installed
|
||||
without isolation from the system python packages. Ansible can be configured to
|
||||
use a virtualenv by setting the host variable ``ansible_python_interpreter``
|
||||
to a path to a python interpreter in an existing virtual environment.
|
||||
|
||||
If the variable ``kolla_ansible_target_venv`` is set, kolla-ansible will be
|
||||
configured to create and use a virtual environment on the remote hosts.
|
||||
This variable is by default set to ``{{ virtualenv_path }}/kolla-ansible``.
|
||||
The previous behaviour of installing python dependencies directly to the host
|
||||
can be used by setting ``kolla_ansible_target_venv`` to ``None``.
|
||||
|
||||
Control Plane Services
|
||||
======================
|
||||
|
||||
|
@ -31,6 +31,16 @@ Features
|
||||
* Adds commands for management of baremetal compute nodes - ``kayobe baremetal
|
||||
compute inspect``, ``kayobe baremetal compute manage``, and ``kayobe
|
||||
baremetal compute provide``.
|
||||
* Adds support for installation and use of a python virtual environment for
|
||||
remote execution of ansible modules, providing isolation from the system's
|
||||
python packages. This is enabled by setting a host variable,
|
||||
``ansible_python_interpreter``, to the path to a python interpreter in a
|
||||
virtualenv, noting that Jinja2 templating is not supported for this variable.
|
||||
* Adds support for configuration of a python virtual environment for remote
|
||||
execution of ansible modules in kolla-ansible, providing isolation from the
|
||||
system's python packages. This is enabled by setting the variable
|
||||
``kolla_ansible_target_venv`` to a path to the virtualenv. The default for
|
||||
this variable is ``{{ virtualenv_path }}/kolla-ansible``.
|
||||
|
||||
Upgrade Notes
|
||||
-------------
|
||||
@ -56,6 +66,25 @@ Upgrade Notes
|
||||
images for the seed were built on the seed, and container images for the
|
||||
overcloud were built on the controllers. The new design is intended to
|
||||
encourage a build, push, pull workflow.
|
||||
* It is now possible to configure kayobe to use a virtual environment for
|
||||
remote execution of ansible modules. If this is required, the following
|
||||
commands should be run in order to ensure that the virtual environments exist
|
||||
on the remote hosts::
|
||||
|
||||
(kayobe) $ kayobe seed hypervisor host upgrade
|
||||
(kayobe) $ kayobe seed host upgrade
|
||||
(kayobe) $ kayobe overcloud host upgrade
|
||||
|
||||
* The default behaviour is now to configure kolla-ansible to use a virtual
|
||||
environment for remote execution of ansible modules. In order to ensure the
|
||||
virtual environment exists on the remote hosts, run the following commands::
|
||||
|
||||
(kayobe) $ kayobe seed hypervisor host upgrade
|
||||
(kayobe) $ kayobe seed host upgrade
|
||||
(kayobe) $ kayobe overcloud host upgrade
|
||||
|
||||
The previous behaviour of installing python dependencies directly to the host
|
||||
can be used by setting ``kolla_ansible_target_venv`` to ``None``.
|
||||
|
||||
Kayobe 3.0.0
|
||||
============
|
||||
|
@ -80,10 +80,27 @@ To upgrade the Ansible control host::
|
||||
|
||||
(kayobe) $ kayobe control host upgrade
|
||||
|
||||
Upgrading the Seed Hypervisor
|
||||
=============================
|
||||
|
||||
Currently, upgrading the seed hypervisor services is not supported. It may
|
||||
however be necessary to upgrade some host services::
|
||||
|
||||
(kayobe) $ kayobe seed hypervisor host upgrade
|
||||
|
||||
Note that this will not perform full configuration of the host, and will
|
||||
instead perform a targeted upgrade of specific services where necessary.
|
||||
|
||||
Upgrading the Seed
|
||||
==================
|
||||
|
||||
Currently, upgrading the seed services is not supported.
|
||||
Currently, upgrading the seed services is not supported. It may however be
|
||||
necessary to upgrade some host services::
|
||||
|
||||
(kayobe) $ kayobe seed host upgrade
|
||||
|
||||
Note that this will not perform full configuration of the host, and will
|
||||
instead perform a targeted upgrade of specific services where necessary.
|
||||
|
||||
Upgrading the Overcloud
|
||||
=======================
|
||||
|
@ -131,6 +131,10 @@
|
||||
###############################################################################
|
||||
# Kolla-ansible configuration.
|
||||
|
||||
# Virtualenv directory where Kolla-ansible's ansible modules will execute
|
||||
# remotely on the target nodes. If None, no virtualenv will be used.
|
||||
#kolla_ansible_target_venv:
|
||||
|
||||
# Whether TLS is enabled for the external API endpoints.
|
||||
#kolla_enable_tls_external:
|
||||
|
||||
|
@ -263,6 +263,7 @@ class SeedHypervisorHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin,
|
||||
|
||||
* Allocate IP addresses for all configured networks.
|
||||
* Add the host to SSH known hosts.
|
||||
* Optionally, create a virtualenv for remote target hosts.
|
||||
* Configure user accounts, group associations, and authorised SSH keys.
|
||||
* Configure Yum repos.
|
||||
* Configure the host's network interfaces.
|
||||
@ -274,8 +275,24 @@ class SeedHypervisorHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin,
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Configuring seed hypervisor host OS")
|
||||
playbooks = _build_playbook_list(
|
||||
"ip-allocation", "ssh-known-host", "users", "yum", "dev-tools",
|
||||
"network", "sysctl", "ntp", "seed-hypervisor-libvirt-host")
|
||||
"ip-allocation", "ssh-known-host", "kayobe-target-venv", "users",
|
||||
"yum", "dev-tools", "network", "sysctl", "ntp",
|
||||
"seed-hypervisor-libvirt-host")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||
limit="seed-hypervisor")
|
||||
|
||||
|
||||
class SeedHypervisorHostUpgrade(KayobeAnsibleMixin, VaultMixin, Command):
|
||||
"""Upgrade the seed hypervisor host services.
|
||||
|
||||
Performs the changes necessary to make the host services suitable for the
|
||||
configured OpenStack release.
|
||||
"""
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Upgrading seed hypervisor host services")
|
||||
playbooks = _build_playbook_list(
|
||||
"kayobe-target-venv", "kolla-target-venv")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||
limit="seed-hypervisor")
|
||||
|
||||
@ -319,6 +336,7 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
* Allocate IP addresses for all configured networks.
|
||||
* Add the host to SSH known hosts.
|
||||
* Configure a user account for use by kayobe for SSH access.
|
||||
* Optionally, create a virtualenv for remote target hosts.
|
||||
* Optionally, wipe unmounted disk partitions (--wipe-disks).
|
||||
* Configure user accounts, group associations, and authorised SSH keys.
|
||||
* Configure Yum repos.
|
||||
@ -329,6 +347,7 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
* Disable bootstrap interface configuration.
|
||||
* Configure NTP.
|
||||
* Configure LVM volumes.
|
||||
* Optionally, create a virtualenv for kolla-ansible.
|
||||
* Configure a user account for kolla-ansible.
|
||||
* Configure Docker engine.
|
||||
"""
|
||||
@ -344,14 +363,25 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Configuring seed host OS")
|
||||
ansible_user = self.run_kayobe_config_dump(
|
||||
parsed_args, host="seed", var_name="kayobe_ansible_user")
|
||||
|
||||
# Query some kayobe ansible variables.
|
||||
hostvars = self.run_kayobe_config_dump(parsed_args, hosts="seed")
|
||||
if not hostvars:
|
||||
self.app.LOG.error("No hosts in the seed group")
|
||||
sys.exit(1)
|
||||
hostvars = hostvars.values()[0]
|
||||
ansible_user = hostvars.get("kayobe_ansible_user")
|
||||
if not ansible_user:
|
||||
self.app.LOG.error("Could not determine kayobe_ansible_user "
|
||||
"variable for seed host")
|
||||
sys.exit(1)
|
||||
python_interpreter = hostvars.get("ansible_python_interpreter")
|
||||
kolla_target_venv = hostvars.get("kolla_ansible_target_venv")
|
||||
|
||||
# Run kayobe playbooks.
|
||||
playbooks = _build_playbook_list(
|
||||
"ip-allocation", "ssh-known-host", "kayobe-ansible-user")
|
||||
"ip-allocation", "ssh-known-host", "kayobe-ansible-user",
|
||||
"kayobe-target-venv")
|
||||
if parsed_args.wipe_disks:
|
||||
playbooks += _build_playbook_list("wipe-disks")
|
||||
playbooks += _build_playbook_list(
|
||||
@ -360,12 +390,44 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed")
|
||||
playbooks = _build_playbook_list("kolla-ansible")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, tags="config")
|
||||
|
||||
# Run kolla-ansible bootstrap-servers.
|
||||
# This command should be run as the kayobe ansible user because at this
|
||||
# point the kolla user may not exist.
|
||||
extra_vars = {"ansible_user": ansible_user}
|
||||
if python_interpreter:
|
||||
# Use the kayobe virtualenv, as this is the executing user.
|
||||
extra_vars["ansible_python_interpreter"] = python_interpreter
|
||||
elif kolla_target_venv:
|
||||
# Override the kolla-ansible virtualenv, use the system python
|
||||
# instead.
|
||||
extra_vars["ansible_python_interpreter"] = "/usr/bin/python"
|
||||
if kolla_target_venv:
|
||||
# Specify a virtualenv in which to install python packages.
|
||||
extra_vars["virtualenv"] = kolla_target_venv
|
||||
self.run_kolla_ansible_seed(parsed_args, "bootstrap-servers",
|
||||
extra_vars={"ansible_user": ansible_user})
|
||||
extra_vars=extra_vars)
|
||||
|
||||
# Run final kayobe playbooks.
|
||||
playbooks = _build_playbook_list("kolla-host", "docker")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed")
|
||||
|
||||
|
||||
class SeedHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
Command):
|
||||
"""Upgrade the seed host services.
|
||||
|
||||
Performs the changes necessary to make the host services suitable for the
|
||||
configured OpenStack release.
|
||||
"""
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Upgrading seed host services")
|
||||
playbooks = _build_playbook_list(
|
||||
"kayobe-target-venv", "kolla-target-venv")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed")
|
||||
|
||||
|
||||
class SeedServiceDeploy(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
Command):
|
||||
"""Deploy the seed services.
|
||||
@ -559,6 +621,7 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
* Allocate IP addresses for all configured networks.
|
||||
* Add the host to SSH known hosts.
|
||||
* Configure a user account for use by kayobe for SSH access.
|
||||
* Optionally, create a virtualenv for remote target hosts.
|
||||
* Optionally, wipe unmounted disk partitions (--wipe-disks).
|
||||
* Configure user accounts, group associations, and authorised SSH keys.
|
||||
* Configure Yum repos.
|
||||
@ -568,6 +631,7 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
* Disable bootstrap interface configuration.
|
||||
* Configure NTP.
|
||||
* Configure LVM volumes.
|
||||
* Optionally, create a virtualenv for kolla-ansible.
|
||||
* Configure a user account for kolla-ansible.
|
||||
* Configure Docker engine.
|
||||
"""
|
||||
@ -583,15 +647,25 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Configuring overcloud host OS")
|
||||
ansible_user = self.run_kayobe_config_dump(
|
||||
parsed_args, hosts="overcloud", var_name="kayobe_ansible_user")
|
||||
|
||||
# Query some kayobe ansible variables.
|
||||
hostvars = self.run_kayobe_config_dump(parsed_args, hosts="overcloud")
|
||||
if not hostvars:
|
||||
self.app.LOG.error("No hosts in the overcloud group")
|
||||
sys.exit(1)
|
||||
hostvars = hostvars.values()[0]
|
||||
ansible_user = hostvars.get("kayobe_ansible_user")
|
||||
if not ansible_user:
|
||||
self.app.LOG.error("Could not determine kayobe_ansible_user "
|
||||
"variable for overcloud hosts")
|
||||
sys.exit(1)
|
||||
ansible_user = ansible_user.values()[0]
|
||||
python_interpreter = hostvars.get("ansible_python_interpreter")
|
||||
kolla_target_venv = hostvars.get("kolla_ansible_target_venv")
|
||||
|
||||
# Kayobe playbooks.
|
||||
playbooks = _build_playbook_list(
|
||||
"ip-allocation", "ssh-known-host", "kayobe-ansible-user")
|
||||
"ip-allocation", "ssh-known-host", "kayobe-ansible-user",
|
||||
"kayobe-target-venv")
|
||||
if parsed_args.wipe_disks:
|
||||
playbooks += _build_playbook_list("wipe-disks")
|
||||
playbooks += _build_playbook_list(
|
||||
@ -600,15 +674,31 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud")
|
||||
playbooks = _build_playbook_list("kolla-ansible")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, tags="config")
|
||||
|
||||
# Kolla-ansible bootstrap-servers.
|
||||
# The kolla-ansible bootstrap-servers command should be run as the
|
||||
# kayobe ansible user because at this point the kolla user may not
|
||||
# exist.
|
||||
extra_vars = {"ansible_user": ansible_user}
|
||||
if python_interpreter:
|
||||
# Use the kayobe virtualenv, as this is the executing user.
|
||||
extra_vars["ansible_python_interpreter"] = python_interpreter
|
||||
elif kolla_target_venv:
|
||||
# Override the kolla-ansible virtualenv, use the system python
|
||||
# instead.
|
||||
extra_vars["ansible_python_interpreter"] = "/usr/bin/python"
|
||||
if kolla_target_venv:
|
||||
# Specify a virtualenv in which to install python packages.
|
||||
extra_vars["virtualenv"] = kolla_target_venv
|
||||
self.run_kolla_ansible_overcloud(parsed_args, "bootstrap-servers",
|
||||
extra_vars=extra_vars)
|
||||
|
||||
# Further kayobe playbooks.
|
||||
playbooks = _build_playbook_list("kolla-host", "docker")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud")
|
||||
|
||||
|
||||
class OvercloudHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
Command):
|
||||
class OvercloudHostUpgrade(KayobeAnsibleMixin, VaultMixin, Command):
|
||||
"""Upgrade the overcloud host services.
|
||||
|
||||
Performs the changes necessary to make the host services suitable for the
|
||||
@ -618,8 +708,9 @@ class OvercloudHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Upgrading overcloud host services")
|
||||
playbooks = _build_playbook_list(
|
||||
"kayobe-target-venv", "kolla-target-venv",
|
||||
"overcloud-docker-sdk-upgrade", "overcloud-etc-hosts-fixup")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks)
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud")
|
||||
|
||||
|
||||
class OvercloudServiceConfigurationGenerate(KayobeAnsibleMixin,
|
||||
|
@ -98,6 +98,7 @@ class TestCase(unittest.TestCase):
|
||||
[
|
||||
"ansible/ip-allocation.yml",
|
||||
"ansible/ssh-known-host.yml",
|
||||
"ansible/kayobe-target-venv.yml",
|
||||
"ansible/users.yml",
|
||||
"ansible/yum.yml",
|
||||
"ansible/dev-tools.yml",
|
||||
@ -111,6 +112,28 @@ class TestCase(unittest.TestCase):
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_seed_hypervisor_host_upgrade(self, mock_run):
|
||||
command = commands.SeedHypervisorHostUpgrade(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/kayobe-target-venv.yml",
|
||||
"ansible/kolla-target-venv.yml",
|
||||
],
|
||||
limit="seed-hypervisor",
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
@ -121,13 +144,15 @@ class TestCase(unittest.TestCase):
|
||||
command = commands.SeedHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = "stack"
|
||||
mock_dump.return_value = {
|
||||
"seed": {"kayobe_ansible_user": "stack"}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(mock.ANY, host="seed", var_name="kayobe_ansible_user")
|
||||
mock.call(mock.ANY, hosts="seed")
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_dump.call_args_list)
|
||||
|
||||
@ -138,6 +163,7 @@ class TestCase(unittest.TestCase):
|
||||
"ansible/ip-allocation.yml",
|
||||
"ansible/ssh-known-host.yml",
|
||||
"ansible/kayobe-ansible-user.yml",
|
||||
"ansible/kayobe-target-venv.yml",
|
||||
"ansible/users.yml",
|
||||
"ansible/yum.yml",
|
||||
"ansible/dev-tools.yml",
|
||||
@ -177,6 +203,130 @@ class TestCase(unittest.TestCase):
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
@mock.patch.object(commands.KollaAnsibleMixin,
|
||||
"run_kolla_ansible_seed")
|
||||
def test_seed_host_configure_kayobe_venv(self, mock_kolla_run, mock_run,
|
||||
mock_dump):
|
||||
command = commands.SeedHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"seed": {
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"kayobe_ansible_user": "stack",
|
||||
}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
"bootstrap-servers",
|
||||
extra_vars={
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"ansible_user": "stack",
|
||||
},
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
@mock.patch.object(commands.KollaAnsibleMixin,
|
||||
"run_kolla_ansible_seed")
|
||||
def test_seed_host_configure_kolla_venv(self, mock_kolla_run, mock_run,
|
||||
mock_dump):
|
||||
command = commands.SeedHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"seed": {
|
||||
"kayobe_ansible_user": "stack",
|
||||
"kolla_ansible_target_venv": "/kolla/venv/bin/python",
|
||||
}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
"bootstrap-servers",
|
||||
extra_vars={
|
||||
"ansible_python_interpreter": "/usr/bin/python",
|
||||
"ansible_user": "stack",
|
||||
"virtualenv": "/kolla/venv/bin/python",
|
||||
},
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
@mock.patch.object(commands.KollaAnsibleMixin,
|
||||
"run_kolla_ansible_seed")
|
||||
def test_seed_host_configure_both_venvs(self, mock_kolla_run, mock_run,
|
||||
mock_dump):
|
||||
command = commands.SeedHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"seed": {
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"kayobe_ansible_user": "stack",
|
||||
"kolla_ansible_target_venv": "/kolla/venv/bin/python",
|
||||
}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
"bootstrap-servers",
|
||||
extra_vars={
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"ansible_user": "stack",
|
||||
"virtualenv": "/kolla/venv/bin/python",
|
||||
},
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_seed_host_upgrade(self, mock_run):
|
||||
command = commands.SeedHostUpgrade(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/kayobe-target-venv.yml",
|
||||
"ansible/kolla-target-venv.yml",
|
||||
],
|
||||
limit="seed",
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_seed_container_image_build(self, mock_run):
|
||||
@ -238,15 +388,15 @@ class TestCase(unittest.TestCase):
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"controller0": "stack"
|
||||
"controller0": {"kayobe_ansible_user": "stack"}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(mock.ANY, hosts="overcloud",
|
||||
var_name="kayobe_ansible_user")]
|
||||
mock.call(mock.ANY, hosts="overcloud")
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_dump.call_args_list)
|
||||
|
||||
expected_calls = [
|
||||
@ -256,6 +406,7 @@ class TestCase(unittest.TestCase):
|
||||
"ansible/ip-allocation.yml",
|
||||
"ansible/ssh-known-host.yml",
|
||||
"ansible/kayobe-ansible-user.yml",
|
||||
"ansible/kayobe-target-venv.yml",
|
||||
"ansible/users.yml",
|
||||
"ansible/yum.yml",
|
||||
"ansible/dev-tools.yml",
|
||||
@ -293,6 +444,132 @@ class TestCase(unittest.TestCase):
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
@mock.patch.object(commands.KollaAnsibleMixin,
|
||||
"run_kolla_ansible_overcloud")
|
||||
def test_overcloud_host_configure_kayobe_venv(self, mock_kolla_run,
|
||||
mock_run, mock_dump):
|
||||
command = commands.OvercloudHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"controller0": {
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"kayobe_ansible_user": "stack",
|
||||
}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
"bootstrap-servers",
|
||||
extra_vars={
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"ansible_user": "stack",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
@mock.patch.object(commands.KollaAnsibleMixin,
|
||||
"run_kolla_ansible_overcloud")
|
||||
def test_overcloud_host_configure_kolla_venv(self, mock_kolla_run,
|
||||
mock_run, mock_dump):
|
||||
command = commands.OvercloudHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"controller0": {
|
||||
"kayobe_ansible_user": "stack",
|
||||
"kolla_ansible_target_venv": "/kolla/venv/bin/python",
|
||||
}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
"bootstrap-servers",
|
||||
extra_vars={
|
||||
"ansible_python_interpreter": "/usr/bin/python",
|
||||
"ansible_user": "stack",
|
||||
"virtualenv": "/kolla/venv/bin/python",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_config_dump")
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
@mock.patch.object(commands.KollaAnsibleMixin,
|
||||
"run_kolla_ansible_overcloud")
|
||||
def test_overcloud_host_configure_both_venvs(self, mock_kolla_run,
|
||||
mock_run, mock_dump):
|
||||
command = commands.OvercloudHostConfigure(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
mock_dump.return_value = {
|
||||
"controller0": {
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"kayobe_ansible_user": "stack",
|
||||
"kolla_ansible_target_venv": "/kolla/venv/bin/python",
|
||||
}
|
||||
}
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
"bootstrap-servers",
|
||||
extra_vars={
|
||||
"ansible_python_interpreter": "/kayobe/venv/bin/python",
|
||||
"ansible_user": "stack",
|
||||
"virtualenv": "/kolla/venv/bin/python",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_overcloud_host_upgrade(self, mock_run):
|
||||
command = commands.OvercloudHostUpgrade(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/kayobe-target-venv.yml",
|
||||
"ansible/kolla-target-venv.yml",
|
||||
"ansible/overcloud-docker-sdk-upgrade.yml",
|
||||
"ansible/overcloud-etc-hosts-fixup.yml",
|
||||
],
|
||||
limit="overcloud",
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_overcloud_container_image_build(self, mock_run):
|
||||
|
Loading…
Reference in New Issue
Block a user