Retire stackforge/tripleo-ansible

This commit is contained in:
Monty Taylor 2015-10-17 16:05:04 -04:00
parent bd0346b55b
commit 5730c2993a
120 changed files with 5 additions and 6358 deletions

View File

@ -1,7 +0,0 @@
[run]
branch = True
source = tripleo_ansible
omit = tripleo_ansible/tests/*,tripleo_ansible/openstack/*
[report]
ignore-errors = True

51
.gitignore vendored
View File

@ -1,51 +0,0 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
.testrepository
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp

View File

@ -1,4 +0,0 @@
[gerrit]
host=review.openstack.org
port=29418
project=stackforge/tripleo-ansible.git

View File

@ -1,3 +0,0 @@
# Format is:
# <preferred e-mail> <other e-mail 1>
# <preferred e-mail> <other e-mail 2>

View File

@ -1,7 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,16 +0,0 @@
If you would like to contribute to the development of OpenStack,
you must follow the steps in this page:
http://docs.openstack.org/infra/manual/developers.html
Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/tripleo-ansible

View File

@ -1,4 +0,0 @@
tripleo-ansible Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

175
LICENSE
View File

@ -1,175 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View File

@ -1,6 +0,0 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc

View File

@ -1,279 +1,7 @@
Using Ansible to update images
==============================
This project is no longer maintained.
This is a new approach to updating an in-place TripleO cloud with new
images. We have chosen Ansible as it allows fine grained control of
the work-flow without requiring one to write any idempotent bash or
python. There are components that are bash or python scripts, and we are
working hard not to replace the whole of TripleO with Ansible, but just
the pieces that make updates more complicated than they need to be.
In general this update process works in the following manner:
* Gather inventory and facts about the deployed cloud from Heat and Nova
* Quiesce the cloud by shutting down all OpenStack services on
appropriate nodes
* Nova-Rebuild nodes using requested image ids
* Disable os-collect-config polling of Heat
* Push Metadata from Heat to rebuilt nodes using Ansible and manually
trigger os-collect-config
* Start OpenStack services
Installing Ansible
------------------
Ideally the node Ansible is to be executed from was built with the following
disk image elements:
* ansible
* tripleo-ansible
Systems that the playbooks are brining up should ideally have the following
disk image elements:
* restore-ssh-host-keys
* disable-os-collect-config
If Ansible is not preloaded, it can be installed via `pip install
ansible` Ansible 1.8.1 or later is required.
If you have manually installed Ansible, see the section on "Setting
the OS Environment" for details on ensuring your dependencies are
met.
Executing Scripts and Playbooks
-------------------------------
All Ansible playbooks and scripts have been written to be run directly
from the tripleo-ansible folder.
An ``ansible.cfg`` file is provided. If you have a systemwide
(/etc/ansible/ansible.conf) or user-specific ( ~/.ansible.cfg) Ansible
config file, then Ansible will not utilize the provided configuration file.
Pre-flight check
----------------
A playbook exists that can be used to check the controllers prior to the
execution of the main playbook in order to quickly identify any issues in
advance.
All controller nodes must be in a healty state (ACTIVE) for the pre flight
checks to pass. We **CANNOT** proceed with an update if a controller node is
down.
ansible-playbook -vvvv -M library/cloud -i plugins/inventory/heat.py -u heat-admin playbooks/pre-flight_check.yml
Running the updates
-------------------
You will want to set your environment variables to the appropriate
values for the following: OS_AUTH_URL, OS_USERNAME, OS_PASSWORD, and
OS_TENANT_NAME
source /root/stackrc
Your new images will need to be uploaded to glance, such that an instance
can be booted from them, and the image ID will need to be provided to
the playbook as an argument.
You can obtain the ID with the `glance image-list` command, and then
set them to be passed into ansible as arguments.
glance image-list
Upon execution, you will see output along these lines:
+--------------------------------------+---------------------------+-------------+------------------+------------+--------+
| ID | Name | Disk Format | Container Format | Size | Status |
+--------------------------------------+---------------------------+-------------+------------------+------------+--------+
| 4ba4c941-2065-4925-8ddc-328d813051c3 | bm-deploy-kernel | aki | aki | 3194080 | active |
| b0379d39-b73e-459e-a22d-a79645b83995 | bm-deploy-ramdisk | ari | ari | 24962351 | active |
| b89342a9-94f7-4e19-a179-6b0d67a857a1 | overcloud-compute | qcow2 | bare | 706412544 | active |
| f25cc0d7-ff6f-4beb-9456-e24b06f5a2e4 | overcloud-compute-initrd | ari | ari | 10557800 | active |
| cbdccc2e-aaf0-4080-88bb-57656f31e747 | overcloud-compute-vmlinuz | aki | aki | 3194080 | active |
| a5b85458-f355-49e0-bdc9-29824f2429d5 | overcloud-control | qcow2 | bare | 1210996736 | active |
| 642f4197-5d4e-4e10-b466-188df9ac2915 | overcloud-control-initrd | ari | ari | 11652799 | active |
| 9c386c74-66d8-4937-9438-d00c9740670d | overcloud-control-vmlinuz | aki | aki | 3194080 | active |
| f52e97c6-e91a-4885-94be-97ea324f6c06 | overcloud-swift | qcow2 | bare | 440991744 | active |
| 1fd49eff-bdbc-4176-b4f5-3779848c5894 | overcloud-swift-initrd | ari | ari | 10557940 | active |
| 50aaab4b-8085-470c-9cc9-9fbfb9891071 | overcloud-swift-vmlinuz | aki | aki | 3194080 | active |
+--------------------------------------+---------------------------+-------------+------------------+------------+--------+
It may be possible to infer the image IDs using the script
"populate_image_vars". It will try to determine the latest image for
each image class and set it as a group variable in inventory. For
this to function correctly, the new images in glance must have the
same names that the previous images had, which match the node type
name, such as undercloud, swift, compute, control.
scripts/populate_image_vars
Upon execution, you will see output that indicates the ID values that
have been stored for the image variable. Example output below:
{
"nova-compute": {
"buildnum": null,
"id": "b89342a9-94f7-4e19-a179-6b0d67a857a1"
},
"swift-storage": {
"buildnum": null,
"id": "f52e97c6-e91a-4885-94be-97ea324f6c06"
},
"controller": {
"buildnum": null,
"id": "a5b85458-f355-49e0-bdc9-29824f2429d5"
},
}
... Creating plugins/inventory/group_vars/nova-compute
... Creating plugins/inventory/group_vars/swift-storage
... Creating plugins/inventory/group_vars/controller
After the populate_image_vars script runs, inspect the output,
example above, and if the data is what you expect, you can omit
the image ids from the ansible command line below. Note, the
undercloud is not shown in this list as this documentation is
geared for overcloud updates, however when you utilize the update
for the undercloud, the variable that needs to be set is
undercloud_rebuild_image_id.
Once you are ready to execute the update, below is an example command
for updating the overcloud, showing all of the disk image IDs being
defined on the command line.
ansible-playbook -vvvv -u heat-admin -i plugins/inventory/heat.py -e nova_compute_rebuild_image_id=1ae9fe6e-c0cc-4f62-8e2b-1d382b20fdcb -e controller_rebuild_image_id=2432dd37-a072-463d-ab86-0861bb5f36cc -e swift_storage_rebuild_image_id=2432dd37-a072-463d-ab86-0861bb5f36cc playbooks/update_cloud.yml
If you have set the image ids in group vars or via the
populate_image_vars script:
ansible-playbook -vvvv -u heat-admin -i plugins/inventory/heat.py playbooks/update_cloud.yml
Below, we break down the above command so you can see what each part does:
* -vvvv - Make Ansible very verbose.
* -u heat-admin - Utilize the heat-admin user to connect to the remote machine.
* -i plugins/inventory/heat.py - Sets the inventory plugin.
* -e nova_compute_rebuild_image_id=1ae9fe6e-c0cc-4f62-8e2b-1d382b20fdcb - Sets the compute node image ID.
* -e controller_rebuild_image_id=2432dd37-a072-463d-ab86-0861bb5f36cc - Sets the controller node image ID.
* -e swift_storage_rebuild_image_id=2432dd37-a072-463d-ab86-0861bb5f36cc - Sets the swift storage node image ID.
* playbooks/update_cloud.yml is the path and file name to the ansible playbook that will be utilized.
Upon a successful completion, ansible will print a summary report:
PLAY RECAP ********************************************************************
192.0.2.24 : ok=18 changed=9 unreachable=0 failed=0
192.0.2.25 : ok=19 changed=9 unreachable=0 failed=0
192.0.2.26 : ok=18 changed=8 unreachable=0 failed=0
Additionally:
As ansible utilizes SSH, you may encounter ssh key errors if the IP
address has been re-used. The fact that SSH keys aren't preserved is a
defect that is being addressed. In order to avoid problems while this
defect is being fixed, you will want to set an environment variable of
"ANSIBLE_HOST_KEY_CHECKING=False", example below.
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -vvvv -M library/cloud -i plugins/inventory/heat.py -e controller_rebuild_image_id=4bee1a0a-2670-48e4-a3a4-17da6be795cb -e nova_compute_rebuild_image_id=bd20e098-0753-4dc8-8dba-2f739c01ee65 -u heat-admin playbooks/update_cloud.yml
Python, the language that ansible is written in, buffers IO output by default.
This can be observed as long pauses between sudden bursts of log entries where
multiple steps are observed, particullarlly when executed by Jenkins. This
behavior can be disabled by passing setting the an environment variable of
"PYTHONUNBUFFERED=1", examble below.
PYTHONUNBUFFERED=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -vvvv -M library/cloud -i plugins/inventory/heat.py -e controller_rebuild_image_id=4bee1a0a-2670-48e4-a3a4-17da6be795cb -e nova_compute_rebuild_image_id=bd20e098-0753-4dc8-8dba-2f739c01ee65 -u heat-admin playbooks/update_cloud.yml
For more information about Ansible, please refer to the documentation at http://docs.ansible.com/
Failure Handling
----------------
Ansible has tunable options to abort the execution of a playbook upon
encountering a failure.
The max_fail_percentage parameter allows users to define what percentage of
nodes can fail before the playbook stops executing. This setting is pre-defined
in the playbook file playbooks/update_cloud.yml. The default value is zero,
which causes the playbook to abort execution if any node fails. You can read
about this option at:
http://docs.ansible.com/playbooks_delegation.html#maximum-failure-percentage
Additionally, it should be noted that the any_errors_fatal variable, when
set to a value of True, will result in ansible aborting upon encountering
any failures. This variable can be set by adding '-e any_errors_fatal=True'
to the command line.
Additional Options
------------------
The plugins/inventory/group_vars/all file has the following options in order
to tune behavior of the playbook execution. These options can be enabled by
defining the variable name that they represent on the ansible comamnd line, or
by uncommenting the appropriate line in the plugins/inventory/group-vars/all
file.
* force_rebuild - This option overrides the logic that prevents an instance
from being rebuilt if the pre-existing image id maches the id being deployed.
This may be useful for the purposes of testing.
Example command line addition: -e force_rebuild=True
* wait_for_hostkey - This option causes the playbook to wait for the
SSH host keys to be restored. This option should only be used if
the restore-ssh-host-keys element is built into the new image.
* single_controller - This option is for when a single controller node is
receiving an upgrade. It alters the logic so that mysql checks operate
as if the mysql database cluster is being maintained online by other
controller nodes during the upgrade. *IF* you are looking at this option
due to an error indicating "Node appears to be the last node in a cluster"
then consult Troubleshooting.rst.
* ssh_timeout - This value, defaulted to 900 [seconds], is the maximum
amount of time that the post-rebuild ssh connection test will wait for
before proceeding.
* pre_hook_command - This, when set to a command, such as /bin/date,
will execute that command on the host where the playbook is run
before starting any jobs.
* post_hook_command - Similar to the pre_hook_command variable, when
defined, will execute upon the completion of the upgrade job.
* online_upgrade - This setting tells the script to attempt an online upgrade
of the node. At present this is only known to work on compute nodes.
Online Upgrade
--------------
When an upgrade *does not* require a kernel update, the Online Upgrade feature
can be utilized to upgrade compute nodes while leaving their virtual machines
in a running state. The result is a short one to two minute loss of network
connectivity for the virtual machines as os-refresh-config stops and
restarts key services which causes the loss in network connectivity.
This operation is performed by uploading the new image to the /tmp folder on
the node, syncing file contents over while preserving key files, and then
restarting services. This is only known to work on compute nodes.
Nova Powercontrol
-----------------
A module named nova_powercontrol has been included which is intended to utilize
nova for all instance power control operations. This utility module also records
the previous state of the instance and has a special flag which allows the user
to resume or restart all virtual machines that are powered off/suspended upon the
completion of the upgrade if the module is utilized to shut down the instances.
To Use:
From the tripleo-ansible folder, execute the command:
bash scripts/retrieve_oc_vars
The script will then inform you of a file you need to source into your current
user environment, it will contain the overcloud API credentials utilizing modified
variable names which the playbook knows how to utilize.
source /root/oc-stackrc-tripleo-ansible
Now that the environment variables are present, add the following to the
ansible-playbook command line for the playbooks to utilize the nova_powercontrol
module:
-e use_nova_powercontrol=True
The contents of this repository are still available in the Git source code
management system. To see the contents of this repository before it reached
its end of life, please check out the previous commit with
"git checkout HEAD^1".

View File

@ -1,578 +0,0 @@
Retrying failed actions
=======================
In some cases, steps may fail as some components may not yet be ready for
use due to initialization times, which can vary based on hardware and volume
In the event of this occurring, two options exist that allows a user to
optionally re-attempt or resume playbook executions.
* Solutions:
* Ansible ansible-playbook command option --start-at-task="TASK NAME"
allows resumption of a playbook, when used with the -l limit option.
* Ansible ansible-playbook command option --step allows a user to confirm
each task executed by Ansible before it is executed upon.
A node goes to ERROR state during rebuild
=========================================
This can happen from time to time due to network errors or temporary
overload of the undercloud.
* Symptoms:
* After error, `nova list` shows node in ERROR
* Solution:
* Verify hardware is in working order.
* Verify that approximately 20% of the disk space is free on the Ironic
server node.
* Get the image ID of the machine with `nova show`::
nova show $node_id
* Rebuild manually::
nova rebuild --preserve-ephemeral $node_id $image_id
A node times out after rebuild
==============================
While rare, there is the possibility that something unexpected happened
and the host has failed to reboot as expected from a rebuild.
* Symptoms:
* Error Message: `msg: Timeout waiting for the server to come up.. Please
check manually`
* Solution:
* Follow the steps detailed above in "A node goes to ERROR state during
rebuild"
MySQL CLI configuration file missing
====================================
Should the post-rebuild restart fail, the possibility exists that the
MySQL CLI configuration file is missing.
* Symptoms:
* Attempts to access the MySQL CLI command return an error::
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
* Solution:
* Verify that the MySQL CLI config file stored on the state drive
is present and has content within the file. You can do this
by executing the command below to display the contents in your
terminal.::
sudo cat /mnt/state/root/metadata.my.cnf
* If the file is empty, run the command below which will retrieve current
metadata and update config files on disk.::
sudo os-collect-config --force --one --command=os-apply-config
* Verify that the MySQL CLI config file is present in the root user
directory by executing the following command::
sudo cat /root/.my.cnf
* If that file does not exist or is empty, two options exist.
* Add the following to your MySQL CLI command line::
--defaults-extra-file=/mnt/state/root/metadata.my.cnf
* Alternatively, copy configuration from the state drive.::
sudo cp -f /mnt/state/root/metadata.my.cnf /root/.my.cnf
MySQL fails to start upon retrying update
=========================================
If the update was aborted or failed during the Update sequence before a
single MySQL controller was operational, MySQL will fail to start upon retrying.
* Symptoms:
* Update is being re-attempted.
* The following error messages having been observed.
* `msg: Starting MySQL (Percona XtraDB Cluster) database server: mysqld . . . . The server quit without updating PID file (/var/run/mysqld/mysqld.pid)`
* `stderr: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)`
* `FATAL: all hosts have already failed -- aborting`
* Update automatically aborts.
* *WARNING*:
* The command `/etc/init.d/mysql bootstrap-pxc` which is mentioned below
should only ever be executed when an entire MySQL cluster is down, and
then only on the last node to have been shut down. Running this command
on multiple nodes will cause the MySQL cluster to enter a split brain
scenario effectively breaking the cluster which will result in
unpredictable behavior.
* Solution:
* Use `nova list` to determine the IP of the controllerMgmt node, then ssh into it::
ssh heat-admin@$IP
* Verify MySQL is down by running the mysql client as root. It _should_ fail::
sudo mysql -e "SELECT 1"
* Attempt to restart MySQL in case another cluster node is online.
This should fail in this error state, however if it succeeds your
cluster should again be operational and the next step can be skipped.::
sudo /etc/init.d/mysql start
* Start MySQL back up in single node bootstrap mode::
sudo /etc/init.d/mysql bootstrap-pxc
MySQL/Percona/Galera is out of sync
===================================
OpenStack is configured to store all of its state in a multi-node
synchronous replication Percona XtraDB Cluster database, which uses
Galera for replication. This database must be in sync and have the full
complement of servers before updates can be performed safely.
* Symptoms:
* Update fails with errors about Galera and/or MySQL being "Out of Sync"
* Solution:
* use `nova list` to determine IP of controllerMgmt node, then SSH to it::
ssh heat-admin@$IP
* Verify replication is out of sync::
sudo mysql -e "SHOW STATUS like 'wsrep_%'"
* Stop mysql::
sudo /etc/init.d/mysql stop
* Verify it is down by running the mysql client as root. It _should_ fail::
sudo mysql -e "SELECT 1"
* Start controllerMgmt0 MySQL back up in single node bootstrap mode::
sudo /etc/init.d/mysql bootstrap-pxc
* On the remaining controller nodes observed to be having issues, utilize
the IP address via `nova list` and login to them.::
ssh heat-admin@$IP
* Verify replication is out of sync::
sudo mysql -e "SHOW STATUS like 'wsrep_%'"
* Stop mysql::
sudo /etc/init.d/mysql stop
* Verify it is down by running the mysql client as root. It _should_ fail::
sudo mysql -e "SELECT 1"
* Start MySQL back up so it attempts to connect to controllerMgmt0::
sudo /etc/init.d/mysql start
* If restarting MySQL fails, then the database is most certainly out of sync
and the MySQL error logs, located at /var/log/mysql/error.log, will need
to be consulted. In this case, never attempt to restart MySQL with
`sudo /etc/init.d/mysql bootstrap-pxc` as it will bootstrap the host
as a single node cluster thus worsening what already appears to be a
split-brain scenario.
MysQL "Node appears to be the last node in a cluster" error
===========================================================
This error occurs when one of the controller nodes does not have MySQL running.
The playbook has detected that the current node is the last running node,
although based on sequence it should not be the last node. As a result the
error is thrown and update aborted.
* Symptoms:
* Update Failed with error message "Galera Replication - Node appears to be the last node in a cluster - cannot safely proceed unless overridden via single_controller setting - See README.rst"
* Actions:
* Run the pre-flight_check.yml playbook. It will attempt to restart MySQL
on each node in the "Ensuring MySQL is running -" step. If that step
succeeeds, you should be able to re-run the playbook and not encounter
"Node appears to be last node in a cluster" error.
* IF pre-flight_check fails to restart MySQL, you will need to consult the
MySQL logs (/var/log/mysql/error.log) to determine why the other nodes
are not restarting.
SSH Connectivity is lost
========================
Ansible uses SSH to communicate with remote nodes. In heavily loaded, single
host virtualized environments, SSH can lose connectivity. It should be noted
that similar issues in a physical environment may indicate issues in the
underlying network infrastructure.
* Symptoms:
* Ansible update attempt fails.
* Error output::
fatal: [192.0.2.25] => SSH encountered an unknown error. The
output was: OpenSSH_6.6.1, OpenSSL 1.0.1i-dev xx XXX xxxx
debug1: Reading configuration data /etc/ssh/ssh_config debug1:
/etc/ssh/ssh_config line 19: Applying options for * debug1:
auto-mux: Trying existing master debug2: fd 3 setting
O_NONBLOCK mux_client_hello_exchange: write packet: Broken
pipe FATAL: all hosts have already failed aborting
* Solution:
* You will generally be able to re-run the playbook and complete the
upgrade, unless SSH connectivity is lost while all MySQL nodes are
down. (See 'MySQL fails to start upon retrying update' to correct
this issue.)
* Early Ubuntu Trusty kernel versions have known issues with KVM which
will severely impact SSH connectivity to instances. Test hosts should
have a minimum kernel version of 3.13.0-36-generic.
The update steps, as root, are::
apt-get update
apt-get dist-upgrade
reboot
* If this issue is repeatedly encountered on a physical environment, the
network infrastructure should be inspected for errors.
* Similar error messages to the error noted in the Symptom may occur with
long running processes, such as database creation/upgrade steps. These
cases will generally have partial program execution log output
immediately before the broken pipe message visible.
Should this be the case, Ansible and OpenSSH may need to have their
configuration files tuned to meet the needs of the environment.
Consult the Ansible configuration file to see available connection settings
ssh_args, timeout, and possibly pipelining..::
https://github.com/ansible/ansible/blob/release1.7.0/examples/ansible.cfg
As Ansible uses OpenSSH, Please reference the ssh_config manual, in
paricular the ServerAliveInterval and ServerAliveCountMax options.
Postfix fails to reload
=======================
Occasionally the postfix mail transfer agent will fail to reload because
it is not running when the system expects it to be running.
* Symptoms:
* Step in /var/log/upstart/os-collect-config.log shows that 'service postfix reload' failed.
Solution:
* Start postfix::
sudo service postfix start
Apache2 Fails to start
======================
Apache2 requires some self-signed SSL certificates to be put in place
that may not have been configured yet due to earlier failures in the
setup process.
* Error Message:
* failed: [192.0.2.25] => (item=apache2) => {"failed": true, "item": "apache2"}
* msg: start: Job failed to start
* Symptoms:
* apache2 service fails to start
* /etc/ssl/certs/ssl-cert-snakeoil.pem is missing or empty
* Solution:
* Re-run `os-collect-config` to reassert the SSL certificates::
sudo os-collect-config --force --one
RabbitMQ still running when restart is attempted
================================================
There are certain system states that cause RabbitMQ to fail to die on normal kill signals.
* Symptoms:
* Attempts to start rabbitmq fail because it is already running
* Solution:
* Find any processes running as `rabbitmq` on the box, and kill them, forcibly if need be.
Instance reported with status == "SHUTOFF" and task_state == "powering on"
==========================================================================
If nova attempts to restart an instance when the compute node is not ready,
it is possible that nova could entered a confused state where it thinks that
an instance is starting when in fact the compute node is doing nothing.
* Symptoms:
* Command `nova list --all-tenants` reports instance(s) with STATUS ==
"SHUTOFF" and task_state == "powering on".
* Instance cannot be pinged.
* No instance appears to be running on the compute node.
* Nova hangs upon retrieving logs or returns old logs from the previous
boot.
* Console session cannot be established.
* Solution:
* On a controller logged in as root, after executing `source stackrc`:
* Execute `nova list --all-tenants` to obtain instance ID(s)
* Execute `nova show <instance-id>` on each suspected ID to identify
suspected compute nodes.
* Log into the suspected compute node(s) and execute:
`os-collect-config --force --one`
* Return to the controller node that you were logged into previously, and
using the instancce IDs obtained previously, take the following steps.
* Execute `nova reset-state --active <instance-id>`
* Execute `nova stop <instance-id>`
* Execute `nova start <instance-id>`
* Once the above steps have been taken in order, you should see the
instance status return to ACTIVE and the instance become accessible
via the network.
state drive /mnt is not mounted
===============================
In the rare event that something bad happened between the state drive being
unmounted and the rebuild command being triggered, the /mnt volume on the
instance that was being executed upon at that time will be in an unmounted
state.
In such a state, pre-flight checks will fail attempting to start MySQL and
RabbitMQ.
* Error Messages:
* Pre-flight check returns an error similar to::
failed: [192.0.2.24] => {"changed": true, "cmd":
"rabbitmqctl -n rabbit@$(hostname) status" stderr: Error:
unable to connect to node
'rabbit@overcloud-controller0-vahypr34iy2x': nodedown
* Attempting to manually start MySQL or RabbitMQ return::
start: Job failed to start
* Upgrade execution returns with an error indicating::
TASK: [fail msg="Galera Replication - Node appears to be the
last node in a cluster - cannot safely proceed unless
overriden via single_controller setting - See README.rst"] ***
* Symptom:
* Execution of the `df` command does not show a volume mounted as /mnt.
* Unable to manually start services.
* Solution:
* Execute the os-collect config which will re-mount the state drive. This
command may fail without additional intervention, however it should mount
the state drive which is all that is needed to proceed to the next step.::
sudo os-collect-config --force --one
* At this point, the /mnt volume should be visible in the output of the `df`
command.
* Start MySQL by executing::
sudo /etc/init.d/mysqld start
* If MySQL fails to start, and it has been verified that MySQL is not
running on any controller nodes, then you will need to identify the
*last* node that MySQL was stopped on and consult the section "MySQL
fails to start upon retrying update" for guidance on restarting the
cluster.
* Start RabbitMQ by executing::
service rabbitmq-server start
* If rabbitmq-server fails to start, then the cluster may be down. If
this is the case, then the *last* node to be stopped will need to be
identified and started before attempting to restart RabbitMQ on this
node.
* At this point, re-execute the pre-flight check, and proceed with the
upgrade.
VMs may not shut down properly during upgrade
=============================================
During the upgrade process, VMs on compute nodes are shut down
gracefully. If the VMs do not shut down, this can cause the upgrade to
stop.
* Error Messages:
* A playbook run ends with a message similar to::
failed: [10.23.210.31] => {"failed": true} msg: The ephemeral
storage of this system failed to be cleaned up properly and
processes or files are still in use. The previous ansible play
should have information to help troubleshoot this issue.
* The output of the playbook run prior to this message contains a
process listing and a listing of open files.
* Symptoms:
* The state drive on the compute node, /mnt, is still in use and
cannot be unmounted. You can confirm this by executing::
lsof -n | grep /mnt
* VMs are running on the node. To see which VMs are running, run::
virsh list
* If `virsh list` fails, you may need to restart libvirt-bin or
libvirtd depending on which process you are running. Do
so by running::
service libvirt-bin restart
or
service libvirtd restart
* Solution:
* Manual intervention is required. You will need to determine why
the VMs did not shut down properly, and resolve the issue.
* Unresponsive VMs can be forcibly shutdown using `virsh destroy
<id>`. Note that this can corrupt filesystems on the VM.
* Resume the playbook run once the VMs have been shut down.
Instances are inaccessible via network
======================================
Upon restarting, it is possible that the virtual machine is
unreachable due to Open vSwitch not being ready for the virtual machine
networking.
* Symptom:
* After a restart, instances won't ping.
* Solution:
* To resolve:
* Log into a controller node and execute `source /root/stackrc`
* Stop all virtual machines on a compute node utilizing `nova
hypervisor-servers <hostname>` and `nova stop <id>`
* Log into the undercloud node and execute `source /root/stackrc`
* Obtain a list of nodes by executing `nova list`
* Execute `nova stop <id>` for the affected compute node.
* Once the compute node has stopped, execute `nova start <id>` to
reboot the compute node.
Online Upgrade fails with message saying glanceclient is not found.
===================================================================
* Symptoms:
* Online upgrade has been attempted, however the playbook
execution failed when attempting to download the new image from
Glance reporting that glanceclient was not found.
* Solution:
* If you are attempting to execute the Ansible playbook on the seed or
undercloud node, source the Ansible virtual environment by executing
`source /opt/stack/venvs/ansible/bin/activate`
* Once the Ansible virtual environment has been sourced, execute
`sudo pip install python-glanceclient` on the node you are attempting
to execute Ansible from.
Online Upgrade of compute node failed
=====================================
In the event that an online upgrade of a compute node somehow failed, the node
can be recovered utilizing a traditional rebuild.
* Symptoms:
* Online upgrade was performed.
* Compute node cannot be logged into, or is otherwise in a
non-working state.
* Solution:
* From the undercloud:
* Execute `source /root/stackrc`
* Identify the instance ID of the broken compute node via `nova list`
* Execute the command `nova stop <instance-id>` to stop the instance.
* Return to the host that you ran the upgrade from and re-run the playbook
without the "-e online_upgrade=True" option.
* Additionally, you may need to utilize the "-e force_rebuild=True" option
to force the instance to rebuild.

View File

@ -1,3 +0,0 @@
[defaults]
timeout = 300
pipelining = True

View File

@ -1 +0,0 @@
[python: **.py]

View File

@ -1,75 +0,0 @@
# -*- coding: utf-8 -*-
# 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.
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
#'sphinx.ext.intersphinx',
'oslosphinx'
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'tripleo-ansible'
copyright = u'2013, OpenStack Foundation'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -1,4 +0,0 @@
============
Contributing
============
.. include:: ../../CONTRIBUTING.rst

View File

@ -1,24 +0,0 @@
.. tripleo-ansible documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to tripleo-ansible's documentation!
========================================================
Contents:
.. toctree::
:maxdepth: 2
readme
installation
usage
contributing
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,12 +0,0 @@
============
Installation
============
At the command line::
$ pip install tripleo-ansible
Or, if you have virtualenvwrapper installed::
$ mkvirtualenv tripleo-ansible
$ pip install tripleo-ansible

View File

@ -1 +0,0 @@
.. include:: ../../README.rst

View File

@ -1,7 +0,0 @@
========
Usage
========
To use tripleo-ansible in a project::
import tripleo_ansible

View File

@ -1,6 +0,0 @@
Install tripleo-ansible repository
Configuration
-------------
At present, there is no configuration for this element.

View File

@ -1,2 +0,0 @@
source-repositories
ansible

View File

@ -1,28 +0,0 @@
#!/bin/bash
#
# Copyright 2014 Hewlett-Packard Development Company, L.P.
# 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.
#
set -eux
set -o pipefail
VENV=/opt/stack/venvs/ansible
set +u
source $VENV/bin/activate
set -u
$VENV/bin/pip install -r /opt/stack/tripleo-ansible/requirements.txt

View File

@ -1 +0,0 @@
tripleo-ansible git /opt/stack/tripleo-ansible https://github.com/SpamapS/tripleo-ansible.git

View File

@ -1,20 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
--
os_username: admin
os_password: admin
os_tenant_name: admin
os_region_name: region.x
os_auth_url: http://127.0.0.1:35357/v2.0/

View File

@ -1,28 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: rebuild a nova instance
hosts: localhost
tasks:
- name: rebuild an instance
nova_rebuild:
region_name: regionOne
login_username: admin
login_password: setpassword
login_tenant_name: admin
auth_url: http://192.0.2.3:5000/v2.0
name: overcloud-NovaCompute-setvmname
image_id: 6663f30c-fff8-4c67-b0a9-fc72193b9eea
preserve_ephemeral: yes
wait_for: 200

View File

@ -1,53 +0,0 @@
A simple iterator for running a playbook.
=========================================
Getting Started
---------------
You will need:
* Stack environment variables loaded.
Example: source $TRIPLEO_ROOT/tripleo-incubator/undercloudrc
* An Ansible Inventory file defining localhost which makes use of a local connection. This file is passed in as the -i option to the included script. You can view such a file at ../hosts_local.
Example Content: "localhost ansible_connection=local"
More information can be found at http://docs.ansible.com/intro_inventory.html
* A file containing a list of instances you wish to run the playbook against.
Example: instances.txt
* A configuration file named update_config.cfg in the folder where your executing the script from. This file has sections that are based upon a portion of the instance name, such as "controller" and "NovaCompute". With-in each section is a "image_id" option which is where you would place the new image ID to rebuild the instance with. Image IDs can be obtained via `glance image-list` once you have the appropriate environment variables loaded.
Example: update_config.cfg
* A playbook, expecting expecting the following
* image_id - glance image id.
* name - instance name
* A slightly modified copy of the simeple_rebuild.yml example playbook exists as main.yml
Putting it all together
-----------------------
source $TRIPLEO_ROOT/tripleo-incubator/undercloudrc
python ./simple_update.py -p ./main.yml -l instances.txt -i ../hosts_local
A Few notes
-----------
1) The variables defined in main.yml before the tasks level are presently
redundant, as the underlying nova_rebuild module supports retrieval of the
configuration from environment variables, although they could be useful for
modules that do not presently support such functionality, or modules that
need to execute remotely.
2) If an inventory is populated of each machine into ansible, then it would
be easy to modify the playbook to connect out and perform actions on each
instance, such as backup a database, fetch files, replace files, etc.

View File

@ -1,4 +0,0 @@
overcloud-NovaCompute0-sbepht5ngm5v
overcloud-NovaCompute1-7d2o5lpz32yt
overcloud-NovaCompute2-wssjjvfecxwk
overcloud-controller0-blhq6zj26lhh

View File

@ -1,33 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: rebuild an instance
hosts: localhost
vars:
os_username: "{{ lookup('env','OS_USERNAME') }}"
os_tenant_name: "{{ lookup('env','OS_TENANT_NAME') }}"
os_password: "{{ lookup('env','OS_PASSWORD') }}"
os_auth_url: "{{ lookup('env','OS_AUTH_URL') }}"
tasks:
- name: rebuild an instance
nova_rebuild:
region_name: regionOne
login_username: "{{ os_username }}"
login_password: "{{ os_password }}"
login_tenant_name: "{{ os_tenant_name}}"
auth_url: "{{ os_auth_url }}"
name: "{{ name }}"
image_id: "{{ image_id }}"
preserve_ephemeral: yes
wait_for: 300

View File

@ -1,64 +0,0 @@
#!/usr/bin/env python
#
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
import argparse
import ConfigParser
import subprocess
parser = argparse.ArgumentParser(description='Exmaple iterative updater')
parser.add_argument('-p', dest='playbook', help='main.yml', required=True)
parser.add_argument(
'-l',
dest='instances',
help='instances.txt',
required=True
)
parser.add_argument(
'-i',
dest='inventory',
help='inventory.ini',
required=True
)
parser.add_argument(
'-c',
dest='configfile',
help='update_config.cfg',
required=False,
default='update_config.cfg'
)
results = parser.parse_args()
config = ConfigParser.RawConfigParser()
config.read(results.configfile)
with open(results.instances) as list:
for host in list:
for section in config.sections():
if section in host:
hostname = host.strip('\n')
image_id = config.get(section, 'image_id')
args = (
'ansible-playbook',
results.playbook,
'-e',
"name=%s image_id=%s" % (hostname, image_id),
'-i',
results.inventory
)
print('Executing:\n')
print(args)
subprocess.call(args)

View File

@ -1,26 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
# Each server name "class" should be a section with an underlying
# image_id property that contains the Glance Image ID to be utilized.
# You can obtain a list of loaded image ids utilizing the
# `glance image-list` command.
[controller]
image_id=7732e7ca-52fa-4acf-beeb-9cfd82e0e3df
[NovaCompute]
image_id=0e09dcac-b4de-42c4-b7ad-d86a33c49ae0

View File

@ -1,185 +0,0 @@
#!/usr/bin/env python
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
try:
from novaclient.v1_1 import client as nova_client
from novaclient import exceptions
import time
except ImportError:
print("failed=True msg='novaclient is required for this module'")
DOCUMENTATION = '''
---
module: nova_facts
short_description: Return facts from Nova
description:
- Returns instance state and metadata from Openstack Nova.
options:
login_username:
description:
- login username to authenticate to keystone
required: true
default: admin
login_password:
description:
- Password of login user
required: true
default: 'yes'
login_tenant_name:
description:
- The tenant name of the login user
required: true
default: 'yes'
auth_url:
description:
- The keystone url for authentication
required: false
default: 'http://127.0.0.1:35357/v2.0/'
region_name:
description:
- Name of the region
required: false
default: None
name:
description:
- Name of the instance for which facts will be retrieved.
default: None
instance_id:
description:
- Instance ID of the instance for which facts will be retrieved.
default: None
requirements: ["novaclient"]
'''
EXAMPLES = '''
# Rebuilds an existing VM with a new image
- nova_facts:
login_username: admin
login_password: admin
login_tenant_name: admin
name: vm1
image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
'''
# The following openstack_ is a copy paste from an upcoming
# core module "lib/ansible/module_utils/openstack.py" Once that's landed,
# these should be replaced with a line at the bottom of the file:
# from ansible.module_utils.openstack import *
def openstack_argument_spec():
# Consume standard OpenStack environment variables.
# This is mainly only useful for ad-hoc command line operation as
# in playbooks one would assume variables would be used appropriately
OS_AUTH_URL = os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
OS_PASSWORD = os.environ.get('OS_PASSWORD', None)
OS_REGION_NAME = os.environ.get('OS_REGION_NAME', None)
OS_USERNAME = os.environ.get('OS_USERNAME', 'admin')
OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME', OS_USERNAME)
spec = dict(
login_username=dict(default=OS_USERNAME),
auth_url=dict(default=OS_AUTH_URL),
region_name=dict(default=OS_REGION_NAME),
availability_zone=dict(default=None),
)
if OS_PASSWORD:
spec['login_password'] = dict(default=OS_PASSWORD)
else:
spec['login_password'] = dict(required=True)
if OS_TENANT_NAME:
spec['login_tenant_name'] = dict(default=OS_TENANT_NAME)
else:
spec['login_tenant_name'] = dict(required=True)
return spec
def _nova_facts(module, nova):
server = None
try:
if module.params.get('instance_id') is None:
servers = nova.servers.list(True, {'name': module.params['name']})
if servers:
# the {'name': module.params['name']} will also return servers
# with names that partially match the server name, so we have to
# strictly filter here
servers = [
x for x in servers if x.name == module.params['name']
]
if servers:
server = servers[0]
else:
server = nova.servers.get(module.params['instance_id'])
except Exception, e:
module.fail_json(
msg="Error in getting the server list: %s" % e.message
)
if not server:
module.exit_json(changed=False, result="not present")
try:
server = nova.servers.get(server.id)
except Exception, e:
module.fail_json(msg="not present")
facts = {'ansible_facts': {}}
facts['ansible_facts']['instance_status'] = server.status
facts['ansible_facts']['instance_metadata'] = server.metadata
module.exit_json(**facts)
def main():
argument_spec = openstack_argument_spec()
argument_spec.update(dict(
name=dict(),
instance_id=dict(),
))
module = AnsibleModule(argument_spec=argument_spec)
nova = nova_client.Client(module.params['login_username'],
module.params['login_password'],
module.params['login_tenant_name'],
module.params['auth_url'],
region_name=module.params['region_name'],
service_type='compute')
try:
nova.authenticate()
except exceptions.Unauthorized, e:
module.fail_json(
msg="Invalid OpenStack Nova credentials.: %s" % e.message
)
except exceptions.AuthorizationFailure, e:
module.fail_json(msg="Unable to authorize user: %s" % e.message)
_nova_facts(module, nova)
# this is magic, see lib/ansible/module_common.py
from ansible.module_utils.basic import *
main()

View File

@ -1,6 +0,0 @@
[DEFAULT]
# The list of modules to copy from oslo-incubator.git
# The base module to hold the copy of openstack.common
base=tripleo_ansible

View File

@ -1,44 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Check if using lvm based storage
stat: path=/mnt/state/var/lib/cinder/cinder-volumes-backing-file
register: lvm_backing_file
- name: Re-create cinder loopdevice
command: losetup -f /mnt/state/var/lib/cinder/cinder-volumes-backing-file
when: lvm_backing_file.stat.exists
sudo: yes
- pause: seconds=5
when: lvm_backing_file.stat.exists
- name: Re-scan for volume groups
command: pvscan
when: lvm_backing_file.stat.exists
sudo: yes
- pause: seconds=5
- name: Re-enable volume groups
command: vgchange -a y
when: lvm_backing_file.stat.exists
sudo: yes
- pause: seconds=5
when: lvm_backing_file.stat.exists
- name: Get all cinder lvm volumes
shell: "lvdisplay | grep cinder-volumes | grep 'LV Path' | awk '{print $3}'"
when: lvm_backing_file.stat.exists
register: cinder_volumes
sudo: yes
- name: Activate cinder lvm volumes
shell: lvchange -a y {{ item }}
with_items: cinder_volumes.stdout_lines
when: lvm_backing_file.stat.exists
sudo: yes

View File

@ -1,17 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- hosts: all
tasks:
- include: disable_os_collect_config.yml

View File

@ -1,17 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- hosts: all
tasks:
- include: refresh_config.yml

View File

@ -1,36 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Remove any cinder volume mounts that may be present"
sudo: yes
script: files/cleanup_cinder_devices.sh
register: test_cinder_cleanup
ignore_errors: yes
- name: "If cinder cleanup failed, collect volume group data"
command: vgdisplay -v
when: instance_status == "ACTIVE" and test_cinder_cleanup.rc != 0
- include: step_fail_unmount.yml
when: instance_status == "ACTIVE" and test_cinder_cleanup.rc != 0
- name: "Detach any loop devices in use"
sudo: yes
script: files/cleanup_loop_devices.sh
register: test_loop_device_cleanup
- name: "Collect list of loop devices"
sudo: yes
command: losetup -a
ignore_errors: yes
when: test_loop_device_cleanup.rc != 0
- include: step_fail_unmount.yml
when: instance_status == "ACTIVE" and test_loop_device_cleanup.rc != 0

View File

@ -1,31 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Determine if node is part of a cluster
shell: grep -q "$(hostname)" "/mnt/state/var/lib/rabbitmq/mnesia/rabbit@$(hostname)/cluster_nodes.config"
ignore_errors: yes
register: rabbit_cluster_test
- name: Collect names of post-configure.d rabbitmq files
shell: ls "{{os_refresh_config_folder}}/post-configure.d/"|grep '\-rabbitmq$'
register: test_rabbitmq_script_list
when: single_controller is not defined and rabbit_cluster_test.rc == 0
- name: If node rabbitmq cluster config was present, re-enable os-refresh-config post-configure.d.
sudo: yes
file: mode=0755 path="{{os_refresh_config_folder}}/post-configure.d/{{item}}"
when: single_controller is not defined and rabbit_cluster_test.rc == 0
with_items: test_rabbitmq_script_list.stdout_lines
- name: "Removing temporary rabbitmq-server override"
sudo: yes
file: path=/etc/init/rabbitmq-server.override state=absent

View File

@ -1,37 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
# Stop and disable os-collect-config
#
# Run from the tripleo-ansible directory:
#
- name: "Disable os-collect-config service"
sudo: yes
service: name=os-collect-config enabled=no state=stopped
- name: "Remove file that allows os-collect-config start via upstart"
shell: os-svc-enable-upstart os-collect-config disable
sudo: yes
- name: "Ensure os-collect-config local-data folder is present"
sudo: yes
file: path=/var/lib/os-collect-config/local-data state=directory owner=root group=root mode=0700
when: online_upgrade is defined
- name: "Reconfigure os-collect-config for local collector"
sudo: yes
copy:
src: files/os-collect-config.conf
dest: /etc/os-collect-config.conf
- name: "Install os-collect-config disable sentinel file"
sudo: yes
file: path=/mnt/state/disable-os-collect-config owner=root group=root mode=644 state=touch

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Create file that allows os-collect-config start via upstart"
shell: os-svc-enable-upstart os-collect-config enable
sudo: yes
- name: "Enable os-collect-config via upstart and start the service"
service: name=os-collect-config state=started
sudo: yes

View File

@ -1,7 +0,0 @@
#!/bin/bash
set -eux
for CINDER_VOLUME in `lvdisplay | grep cinder-volumes | grep 'LV Path' | awk '{print $3}'`; do
lvchange -a n $CINDER_VOLUME
done
vgchange -a n

View File

@ -1,6 +0,0 @@
#!/bin/bash
set -eux
for loopdevice in `losetup -a| cut -d ':' -f 1`; do
losetup --detach $loopdevice
done

View File

@ -1,176 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
import grp
import optparse
import os
import pwd
import stat
def get_object_ids(file):
stat_information = os.stat(file)
return(stat_information.st_uid, stat_information.st_gid)
def get_username_from_uid(old_uid, old_password_file):
file = open(old_password_file)
passwd_file = file.readlines()
for user_entry in passwd_file:
(
user,
passwd,
uid,
gid,
gecos,
home,
shell
) = user_entry.split(':')
if old_uid == int(uid):
return user
return "ErrUserNotFound"
def get_groupname_from_gid(old_gid, old_group_file):
file = open(old_group_file)
group_file = file.readlines()
for group_entry in group_file:
(
group,
passwd,
gid,
members
) = group_entry.split(':')
if old_gid == int(gid):
return group
return "ErrUserNotFound"
def get_new_uid(username):
return pwd.getpwnam(username).pw_uid
def get_new_gid(groupname):
return grp.getgrnam(groupname).gr_gid
def run_check(object, old_password_file, old_group_file):
(old_uid, old_gid) = get_object_ids(object)
old_username = get_username_from_uid(old_uid, old_password_file)
old_groupname = get_groupname_from_gid(old_uid, old_group_file)
try:
new_uid = get_new_uid(old_username)
new_gid = get_new_gid(old_groupname)
if old_uid != new_uid:
if old_username in object:
return(True, old_username, new_uid, old_groupname, new_gid)
return(False, old_username, new_uid, old_groupname, old_gid)
except:
return(False, old_username, -1, old_groupname, -1)
def recursive_update(directory, new_uid, new_gid):
os.chown(directory, new_uid, new_gid)
for root, dirs, files in os.walk(directory):
for dir in dirs:
os.chown(os.path.join(root, dir), new_uid, new_gid)
for file in files:
os.chown(os.path.join(root, file), new_uid, new_gid)
def main():
usage = "Usage: %prog -f old_password_file -d directory_to_update"
parser = optparse.OptionParser(usage)
parser.add_option(
"-f",
action="store",
default=False,
dest="old_password_file",
help="Path to previous system password file"
)
parser.add_option(
"-g",
action="store",
default=False,
dest="old_group_file",
help="Path to previous system password file"
)
parser.add_option(
"-d",
action="store",
default=False,
dest="directory",
help="Directory to check and apply permission updates to"
)
(options, args) = parser.parse_args()
if not options.directory:
print("Error: please define a directory to run the program with -d")
parser.print_help()
return -1
if not options.old_password_file:
print("Error: please define a directory to run the program with -d")
parser.print_help()
return -1
if not options.old_group_file:
print("Error: please define a directory to run the program with -d")
parser.print_help()
return -1
for object in os.listdir(options.directory):
if os.path.isdir(os.path.join(options.directory, object)):
(changed, old_user, new_uid, old_groupname, new_gid) = run_check(
os.path.join(options.directory, object),
options.old_password_file,
options.old_group_file
)
if changed:
print("Updating %s/%s for ownership to uid %s for %s" % (
options.directory,
object,
new_uid,
old_user
)
)
try:
recursive_update(
os.path.join(options.directory, object),
new_uid,
new_gid
)
except:
print("Failed to update ownership of %s/%s " % (
options.directory,
object
)
)
else:
print("ignoring %s/%s" % (
options.directory,
object
)
)
else:
print("Ignoring %s/%s as it is not a directory" % (
options.directory,
object
)
)
main()

View File

@ -1,24 +0,0 @@
#!/bin/bash
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
set -eux
set -o pipefail
PATH=/usr/local/bin/:$PATH
# Execute database creation step although suppress output
# that may contain passwords.
sed -i 's/| mysql$/| mysql --defaults-file=\/mnt\/state\/root\/metadata.my.cnf/' /usr/local/bin/os-db-create
reset-db -c 2>&1 |grep -v "db_pass" |grep -v "os-db-create"
reset-db -m 2>&1 |grep -v "db_pass" |grep -v "os-db-create"

View File

@ -1,27 +0,0 @@
#!/usr/bin/python
import argparse
import json
import os
parser = argparse.ArgumentParser()
parser.add_argument('path', default='/var/lib/os-collect-config/local-data')
parser.add_argument('--deployments-key', default='deployments')
args = parser.parse_args()
for fname in os.listdir(args.path):
f = os.path.join(args.path, fname)
with open(f) as infile:
x = json.loads(infile.read())
dp = args.deployments_key
final_list = []
if dp in x:
if isinstance(x[dp], list):
for d in x[dp]:
name = d['name']
if d.get('group', 'Heat::Ungrouped') in ('os-apply-config', 'Heat::Ungrouped'):
final_list.append((name, d['config']))
for oname, oconfig in final_list:
with open('%s%s' % (f, oname), 'w') as outfile:
outfile.write(json.dumps(oconfig))

View File

@ -1,4 +0,0 @@
[DEFAULT]
collectors = ec2
collectors = local
command = os-refresh-config

View File

@ -1,31 +0,0 @@
#!/bin/bash
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
set -eux
set -o pipefail
# This turns on an internal heartbeat mechanism in the ssh client
# to prevent the client from believing inactivity is a connection
# failure.
if ! grep -q '^\s*ServerAliveInterval' /etc/ssh/ssh_config; then
echo " ServerAliveInterval 30" >>/etc/ssh/ssh_config
fi
# This causes the connection to wait until the defined number of
# heartbeats are missed before terminating the connection.
if ! grep -q '^\s*ServerAliveCountMax' /etc/ssh/ssh_config; then
echo " ServerAliveCountMax 6" >>/etc/ssh/ssh_config
fi

View File

@ -1 +0,0 @@
post-start exec /bin/true

View File

@ -1,36 +0,0 @@
#!/bin/bash
set -eux
set -o pipefail
# Get and return the wsrep_local_state.
function get_state() {
mysql --defaults-file=/mnt/state/root/metadata.my.cnf --socket /var/run/mysqld/mysqld.sock -N -e "SHOW STATUS LIKE 'wsrep_local_state'"|cut -f2
}
# Loop until timed out, exit if wsrep_local_state equals Synced "4"
function wait_for_wsrep_synced() {
COUNT=0
while true;
do
if [ "4" -eq $(get_state) ]; then
echo "Local wsrep_local_state has reached Synced, breaking out of loop."
break
fi
echo ".... Sleeping 30 seconds"
sleep 30
COUNT=$((COUNT + 1))
if [ $COUNT -gt 61 ]; then
echo "Aborting, exiting 1, waited for a 30 minutes. You can re-attempt this setup using ansible-playbook options --start-at-task or --step."
fi
done
}
if ! which mysql &>/dev/null; then
echo "Failure - MySQL CLI not found"
exit 1
fi
echo "Beginning MySQL wait - Time: $(date)"
wait_for_wsrep_synced
echo "Exiting MySQL wait - Time: $(date)"

View File

@ -1,38 +0,0 @@
- name: Rename MySQL upstart script
sudo: yes
command: mv -f /etc/init/mysql.conf /etc/init/mysql-boot-control.conf removes=/etc/init/mysql.conf
- service: name=mysql state=started
ignore_errors: yes
- name: Fetch Galera sync status from MySQL
sudo: yes
command: mysql --defaults-file=/mnt/state/root/metadata.my.cnf --socket /var/run/mysqld/mysqld.sock -N -e "SHOW STATUS LIKE 'wsrep_local_state'"
when: helion is not defined
register: wsrep_local_state
- set_fact: galera_status="Synced"
when: helion is not defined and wsrep_local_state.stdout == "wsrep_local_state\t4"
- set_fact: galera_status="Out of Sync"
when: helion is not defined and wsrep_local_state.stdout != "wsrep_local_state\t4"
- name: Fetch Galera cluster size from MySQL
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf --socket /var/run/mysqld/mysqld.sock -N -e "SHOW STATUS LIKE 'wsrep_cluster_size'"|cut -f2
when: helion is not defined
register: wsrep_cluster_size
- set_fact: galera_cluster_size="{{wsrep_cluster_size.stdout}}"
when: helion is not defined
- name: Fetch Galera sync status from MySQL - Helion
sudo: yes
command: mysql --defaults-file=/mnt/state/root/metadata.my.cnf -N -e "SHOW STATUS LIKE 'wsrep_local_state'"
when: helion is defined
register: wsrep_local_state
- set_fact: galera_status="Synced"
when: helion is defined and wsrep_local_state.stdout == "wsrep_local_state\t4"
- set_fact: galera_status="Out of Sync"
when: helion is defined and wsrep_local_state.stdout != "wsrep_local_state\t4"
- name: Fetch Galera cluster size from MySQL - Helion
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf -N -e "SHOW STATUS LIKE 'wsrep_cluster_size'"|cut -f2
when: helion is defined
register: wsrep_cluster_size
- set_fact: galera_cluster_size="{{wsrep_cluster_size.stdout}}"
when: helion is defined

View File

@ -1,245 +0,0 @@
#!/usr/bin/env python
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
try:
import glanceclient.v2.client as glanceclient
except ImportError:
print("failed=True msg='module glanceclient is required for this module'")
try:
from keystoneclient.v3 import client as ksclient
except ImportError:
print(
"failed=True msg='module keystoneclient is required for this module'"
)
import hashlib
import os
try:
from novaclient.v1_1 import client as nova_client
from novaclient import exceptions
except ImportError:
print("failed=True msg='module novaclient is required for this module'")
import time
DOCUMENTATION = '''
---
module: glance_download
short_description: Download file from Glance
description:
- Return the requested file from Glance to a location defined by the user.
options:
login_username:
description:
- login username to authenticate to keystone
required: true
default: admin
login_password:
description:
- Password of login user
required: true
default: 'yes'
login_tenant_name:
description:
- The tenant name of the login user
required: true
default: 'yes'
auth_url:
description:
- The keystone url for authentication
required: false
default: 'http://127.0.0.1:35357/v2.0/'
region_name:
description:
- Name of the region
required: false
default: None
image_id:
description:
- Glance file ID that you wish to download.
required: true
default: None
path:
description:
- Location where to save the file from Glance to
required: true
default: None
requirements: ["glanceclient"]
'''
EXAMPLES = '''
# Downloads a glance image to the defined path
- glance_download:
login_username: admin
login_password: admin
login_tenant_name: admin
image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
path: /tmp/4f905f38-e52a-43d2-b6ec-754a13ffb529.qcow2
'''
# The following openstack_ is a copy paste from an upcoming
# core module "lib/ansible/module_utils/openstack.py" Once that's landed,
# these should be replaced with a line at the bottom of the file:
# from ansible.module_utils.openstack import *
def openstack_argument_spec():
# Consume standard OpenStack environment variables.
# This is mainly only useful for ad-hoc command line operation as
# in playbooks one would assume variables would be used appropriately
OS_AUTH_URL = os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
OS_PASSWORD = os.environ.get('OS_PASSWORD', None)
OS_REGION_NAME = os.environ.get('OS_REGION_NAME', None)
OS_USERNAME = os.environ.get('OS_USERNAME', 'admin')
OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME', OS_USERNAME)
spec = dict(
login_username=dict(default=OS_USERNAME),
auth_url=dict(default=OS_AUTH_URL),
region_name=dict(default=OS_REGION_NAME),
availability_zone=dict(default=None),
)
if OS_PASSWORD:
spec['login_password'] = dict(default=OS_PASSWORD)
else:
spec['login_password'] = dict(required=True)
if OS_TENANT_NAME:
spec['login_tenant_name'] = dict(default=OS_TENANT_NAME)
else:
spec['login_tenant_name'] = dict(required=True)
return spec
def _glance_get_image_checksum(glance, image_id):
return glance.images.get(image_id).checksum
def _md5sum_file(path):
try:
with open(path) as file_object:
checksum = hashlib.md5()
while True:
data = file_object.read(65535)
if not data:
break
checksum.update(data)
return checksum.hexdigest()
except Excption, e:
print("Checksum operaction failed: %s" % e.message)
def _glance_download(module, glance, image_id, path):
image_checksum = _glance_get_image_checksum(glance, image_id)
if os.path.isfile(path):
file_checksum = _md5sum_file(path)
if image_checksum == file_checksum:
module.exit_json(
ansible_facts={
'returned_checksum': file_checksum
}
)
try:
file_data = glance.images.data(image_id)
glanceclient.utils.save_image(file_data, path)
except:
module.fail_json(
msg="Retrieval of image from Glance failed."
)
file_checksum = _md5sum_file(path)
if image_checksum == file_checksum:
module.exit_json(
ansible_facts={
'returned_checksum': file_checksum
}
)
else:
module.fail_json(
msg="Glance checksum %s != %s checksum %s" % (
image_checksum,
path,
file_checksum
)
)
def main():
argument_spec = openstack_argument_spec()
argument_spec.update(dict(
image_id=dict(required=True),
path=dict(required=True)
))
module = AnsibleModule(argument_spec=argument_spec)
try:
if '/v2.0' in module.params['auth_url']:
module.params['auth_url'] = module.params['auth_url'].replace(
'/v2.0',
'/v3'
)
keystone = ksclient.Client(
username=module.params['login_username'],
password=module.params['login_password'],
tenant=module.params['login_tenant_name'],
auth_url=module.params['auth_url'],
region_name=module.params['region_name']
)
keystone.authenticate()
except:
module.fail_json(
msg="Failed to Authenticate to Keystone"
)
try:
glance_endpoint = keystone.service_catalog.url_for(
service_type='image',
endpoint_type='publicURL'
)
except:
module.fail_json(
msg="Failed to retrieve image server URL"
)
try:
glance = glanceclient.Client(
endpoint=glance_endpoint,
token=keystone.auth_token
)
except:
module.fail_json(
msg="Failed to connect to Glance"
)
_glance_download(
module,
glance,
module.params['image_id'],
module.params['path']
)
from ansible.module_utils.basic import *
main()

View File

@ -1,350 +0,0 @@
#!/usr/bin/env python
# This code is part of Ansible, but is an independent component. This
# particular file snippet, and this file snippet only, is BSD
# licensed. Modules you write using this snippet, which is embedded
# dynamically by Ansible still belong to the author of the module, and
# may assign their own license to the complete work.
#
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os
try:
from novaclient.v1_1 import client as nova_client
from novaclient import exceptions
import time
except ImportError:
print("failed=True msg='novaclient is required for this module'")
DOCUMENTATION = '''
---
module: nova_powercontrol
short_description: Stops/Starts virtual machines via nova.
description:
- Controls the power state of virtual machines via nova.
options:
login_username:
description:
- login username to authenticate to keystone
required: true
default: admin
login_password:
description:
- Password of login user
required: true
default: 'yes'
login_tenant_name:
description:
- The tenant name of the login user
required: true
default: 'yes'
auth_url:
description:
- The keystone url for authentication
required: false
default: 'http://127.0.0.1:35357/v2.0/'
region_name:
description:
- Name of the region
required: false
default: None
state:
description:
- The desired state for the instance to be set to.
required: true
default: None
instance_id:
description:
- Instance ID of a single instance to control.
default: None
hypervisor:
description:
- Hypervisor ID of the instances to control.
default: None
zone:
description:
- zone name of the instances to control.
default: None
all_instances:
description:
- Any value to affirm decision to act upon all instances.
default: None
requirements: ["novaclient"]
'''
EXAMPLES = '''
# Changes the power state via nova
- nova_power_control:
login_username: admin
login_password: admin
login_tenant_name: admin
instance_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
state: stopped
'''
# The following two openstack_ are copy pasted from an upcoming
# core module "lib/ansible/module_utils/openstack.py" Once that's landed,
# these should be replaced with a line at the bottom of the file:
# from ansible.module_utils.openstack import *
def openstack_argument_spec():
# Consume standard OpenStack environment variables.
# This is mainly only useful for ad-hoc command line operation as
# in playbooks one would assume variables would be used appropriately
OS_AUTH_URL = os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
OS_PASSWORD = os.environ.get('OS_PASSWORD', None)
OS_REGION_NAME = os.environ.get('OS_REGION_NAME', None)
OS_USERNAME = os.environ.get('OS_USERNAME', 'admin')
OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME', OS_USERNAME)
spec = dict(
login_username=dict(default=OS_USERNAME),
auth_url=dict(default=OS_AUTH_URL),
region_name=dict(default=OS_REGION_NAME),
availability_zone=dict(default=None),
)
if OS_PASSWORD:
spec['login_password'] = dict(default=OS_PASSWORD)
else:
spec['login_password'] = dict(required=True)
if OS_TENANT_NAME:
spec['login_tenant_name'] = dict(default=OS_TENANT_NAME)
else:
spec['login_tenant_name'] = dict(required=True)
return spec
def _get_server(nova, instance_id):
try:
return nova.servers.get(instance_id)
except Exception, e:
module.fail_json(
msg="Error accessing instance %s: %s" % (instance_id, e.message)
)
def _write_metadata(nova, server):
nova.servers.set_meta(
server.id,
{'ansible_previous_state': server.status}
)
def _suspend_instance(nova, instance_id):
try:
server = None
server = _get_server(nova, instance_id)
if server.status != "ACTIVE":
if server.status != "PAUSED":
return False
_write_metadata(nova, server)
nova.servers.suspend(server.id)
return (True, nova.servers.suspend(server.id))
except Exception, e:
return (False, e.message)
def _resume_instance(nova, instance_id):
try:
server = None
server = _get_server(nova, instance_id)
if server.status != "SUSPENDED":
return False
_write_metadata(nova, server)
return (True, nova.servers.resume(server.id))
except Exception, e:
return (False, e.message)
def _stop_instance(nova, instance_id):
try:
server = None
server = _get_server(nova, instance_id)
if server.status != "ACTIVE":
if server.status != "PAUSED":
return False
_write_metadata(nova, server)
return (True, nova.servers.stop(server.id))
except Exception, e:
return (False, e.message)
def _start_instance(nova, instance_id):
try:
server = None
server = _get_server(nova, instance_id)
if server.status != "STOPPED":
if server.status != "SUSPENDED":
if server.status != "PAUSED":
return False
_write_metadata(nova, server)
return (True, nova.servers.start(server.id))
except Exception, e:
return (False, e.message)
def _previous_state(nova, instance_id):
"""
Attempts to return instances to their previous state if they were
stopped or suspended.
"""
try:
server = _get_server(nova, instance_id)
if server.metadata["ansible_previous_state"] == "ACTIVE":
if server.status != "ACTIVE":
if server.status == "STOPPED":
return _start_instance(nova, instance_id)
if server.status == "SUSPENDED":
return _resume_instance(nova, instance_id)
return (False, None)
except Exception, e:
return (False, e.message)
def _determine_task(nova, instance_id, action):
choice = {
'running': _start_instance,
'start': _start_instance,
'on': _start_instance,
'stopped': _stop_instance,
'stop': _stop_instance,
'off': _stop_instance,
'resume': _resume_instance,
'previous': _previous_state
}
return choice[action](nova, instance_id)
def _many_servers(module, nova, servers):
"""
Enumerates through the list of services and calls
_determine_task.
"""
results = []
for server in servers:
result = _determine_task(nova, server.id, module.params['state'])
results.append(results)
module.exit_json(changed=True, output=results)
def _all_instances(module, nova):
"""
Retrieves the entire list of servers and changes and applies the
desired state.
"""
results = []
for server in nova.servers.list():
_determine_task(nova, server.id, module.params['state'])
results.append(results)
module.exit_json(changed=True, output=results)
def _nova_powercontrol(module, nova):
state = module.params['state']
if module.params['instance_id'] is not None:
(status, message) = _determine_task(
nova,
module.params['instance_id'],
state
)
if status:
module.exit_json(changed=True, output=message)
else:
module.fail_json(
msg="Instance %s failed to update with error %s" % (
module.params['instance_id'],
message
)
)
elif module.params['hypervisor'] is not None:
try:
hypervisor = nova.hypervisors.search(
True,
module.params['hypervisor'],
servers=True
)
_many_servers(module, nova, hypervisor.servers)
except:
module.fail_json(
msg="Unable to find zone %s" % module.params['hypervisor']
)
elif module.params['zone'] is not None:
try:
servers = nova.servers.list(
True,
{'OS-EXT-AZ:availability_zone': module.params['zone']}
)
_many_servers(module, nova, servers)
except:
module.fail_json(
msg="Unable to find zone %s" % module.params['zone']
)
elif module.params['all_instances'] is not None:
_all_instances(module, nova)
else:
module.fail_json(
msg="Unable to proceed: Requires instance_id, hypervisor, "
"zone, or special flag all_instances."
)
def main():
argument_spec = openstack_argument_spec()
argument_spec.update(dict(
state=dict(required=True),
instance_id=dict(),
hypervisor=dict(),
zone=dict(),
all_instances=dict()
))
module = AnsibleModule(argument_spec=argument_spec)
nova = nova_client.Client(module.params['login_username'],
module.params['login_password'],
module.params['login_tenant_name'],
module.params['auth_url'],
region_name=module.params['region_name'],
service_type='compute')
try:
nova.authenticate()
except exceptions.Unauthorized, e:
module.fail_json(
msg="Invalid OpenStack Nova credentials.: %s" % e.message
)
except exceptions.AuthorizationFailure, e:
module.fail_json(
msg="Unable to authorize user: %s" % e.message
)
_nova_powercontrol(module, nova)
# this is magic, see lib/ansible/module_common.py
from ansible.module_utils.basic import *
main()

View File

@ -1,268 +0,0 @@
#!/usr/bin/env python
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import sys
import traceback
try:
from novaclient.v1_1 import client as nova_client
from novaclient import exceptions
import time
except ImportError:
print("failed=True msg='novaclient is required for this module'")
DOCUMENTATION = '''
---
module: nova_rebuild
short_description: Rebuild VMs from OpenStack
description:
- Rebuild (re-image) virtual machines from Openstack.
options:
login_username:
description:
- login username to authenticate to keystone
required: true
default: admin
login_password:
description:
- Password of login user
required: true
default: 'yes'
login_tenant_name:
description:
- The tenant name of the login user
required: true
default: 'yes'
auth_url:
description:
- The keystone url for authentication
required: false
default: 'http://127.0.0.1:35357/v2.0/'
region_name:
description:
- Name of the region
required: false
default: None
name:
description:
- Name of the instance to be rebuilt
default: None
instance_id:
description:
- Instance ID of the instance to be rebuilt
default: None
image_id:
description:
- The id of the image that has to be cloned
required: true
default: None
preserve_ephemeral:
description:
- Whether to preserve ephemeral storage on the instance
required: false
default: false
wait:
description:
- If the module should wait for the VM to be created.
required: false
default: 'yes'
wait_for:
description:
- Number of seconds the module should wait for the VM to get into active state
required: false
default: 600
requirements: ["novaclient"]
'''
EXAMPLES = '''
# Rebuilds an existing VM with a new image
- nova_rebuild:
login_username: admin
login_password: admin
login_tenant_name: admin
name: vm1
image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
wait_for: 200
'''
# The following two openstack_ are copy paste from an upcoming
# core module "lib/ansible/module_utils/openstack.py" Once that's landed,
# these should be replaced with a line at the bottom of the file:
# from ansible.module_utils.openstack import *
def openstack_argument_spec():
# Consume standard OpenStack environment variables.
# This is mainly only useful for ad-hoc command line operation as
# in playbooks one would assume variables would be used appropriately
OS_AUTH_URL=os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
OS_PASSWORD=os.environ.get('OS_PASSWORD', None)
OS_REGION_NAME=os.environ.get('OS_REGION_NAME', None)
OS_USERNAME=os.environ.get('OS_USERNAME', 'admin')
OS_TENANT_NAME=os.environ.get('OS_TENANT_NAME', OS_USERNAME)
spec = dict(
login_username = dict(default=OS_USERNAME),
auth_url = dict(default=OS_AUTH_URL),
region_name = dict(default=OS_REGION_NAME),
availability_zone = dict(default=None),
)
if OS_PASSWORD:
spec['login_password'] = dict(default=OS_PASSWORD)
else:
spec['login_password'] = dict(required=True)
if OS_TENANT_NAME:
spec['login_tenant_name'] = dict(default=OS_TENANT_NAME)
else:
spec['login_tenant_name'] = dict(required=True)
return spec
def openstack_find_nova_addresses(addresses, ext_tag, key_name=None):
ret = []
for (k, v) in addresses.iteritems():
if key_name and k == key_name:
ret.extend([addrs['addr'] for addrs in v])
else:
for interface_spec in v:
if 'OS-EXT-IPS:type' in interface_spec and interface_spec['OS-EXT-IPS:type'] == ext_tag:
ret.append(interface_spec['addr'])
return ret
def _rebuild_server(module, nova):
server = None
last_error = None
last_stacktrace = None
try:
if module.params.get('instance_id') is None:
servers = nova.servers.list(True, {'name': module.params['name']})
if servers:
# the {'name': module.params['name']} will also return servers
# with names that partially match the server name, so we have to
# strictly filter here
servers = [x for x in servers if x.name == module.params['name']]
if servers:
server = servers[0]
else:
server = nova.servers.get(module.params['instance_id'])
except Exception, e:
module.fail_json(msg = "Error in getting the server list: %s" % e.message)
if not server:
module.exit_json(changed = False, result = "not present")
bootargs = [server, module.params['image_id']]
bootkwargs = {
'preserve_ephemeral' : module.params['preserve_ephemeral'],
}
try:
server = nova.servers.rebuild(*bootargs, **bootkwargs)
server = nova.servers.get(server.id)
except Exception, e:
module.fail_json( msg = "Error in rebuilding instance: %s " % e.message)
if module.params['wait'] == 'yes':
expire = time.time() + int(module.params['wait_for'])
while time.time() < expire:
try:
server = nova.servers.get(server.id)
except Exception, last_error:
# This logic attempts to retry a failed status query
# once before aborting and returning an error to
# Ansible. This helps prevent momentarilly transient
# issues from creating spurious issues.
#
# Ideally, we would change this logic to something
# along the lines of wait_for, although logging
# would need to be addressed so issues can be
# identified should errors occur.
last_error = traceback.format_exc
time.sleep(2)
try:
server = nova.servers.get(server.id)
except Exception, error:
module.fail_json(
msg = ("Error in getting info for instance: %s\n"
"Initial error: %s\n"
"Stack backtrace: %s\n"
"Terminal error: %s\n"
"Terminal stack backtrace: %s") % (
last_stracetrace,
last_error.message,
error.message,
traceback.format_exc
)
)
if server.status == 'ACTIVE':
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
module.exit_json(changed = True, id = server.id, private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
if server.status == 'ERROR':
module.fail_json(msg = "Instance exited Nova Rebuild in an ERROR state, please check OpenStack logs")
time.sleep(2)
module.fail_json(msg = "Timeout waiting for the server to come up.. Please check manually")
if server.status == 'ERROR':
module.fail_json(msg = "Error in rebuilding the server.. Please check manually")
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
module.exit_json(changed = True, id = info['id'], private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
def main():
argument_spec = openstack_argument_spec()
argument_spec.update(dict(
name = dict(),
instance_id = dict(),
image_id = dict(required=True),
preserve_ephemeral = dict(default=False, choices=[True, False]),
wait = dict(default='yes', choices=['yes', 'no']),
wait_for = dict(default=600),
))
module = AnsibleModule(argument_spec=argument_spec)
nova = nova_client.Client(module.params['login_username'],
module.params['login_password'],
module.params['login_tenant_name'],
module.params['auth_url'],
region_name=module.params['region_name'],
service_type='compute')
try:
nova.authenticate()
except exceptions.Unauthorized, e:
module.fail_json(msg = "Invalid OpenStack Nova credentials.: %s" % e.message)
except exceptions.AuthorizationFailure, e:
module.fail_json(msg = "Unable to authorize user: %s" % e.message)
_rebuild_server(module, nova)
# this is magic, see lib/ansible/module_common.py
from ansible.module_utils.basic import *
main()

View File

@ -1,42 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
import subprocess
def main():
existing_services = set()
for init_filename in os.listdir('/etc/init.d'):
if init_filename[0] == '.':
continue
existing_services.add(init_filename)
try:
initctl_list = subprocess.Popen(['initctl', 'list'],
stdout=subprocess.PIPE)
for upstart_job in initctl_list.stdout:
existing_services.add(upstart_job.split(' ', 1)[0])
except subprocess.CalledProcessError as e:
if e.errno != 2:
raise e
module = AnsibleModule(argument_spec={})
module.exit_json(ansible_facts={'existing_services':
list(existing_services)})
from ansible.module_utils.basic import *
main()

View File

@ -1,17 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Ensure /root/.my.cnf is present"
sudo: yes
command: cp -a /mnt/state/root/metadata.my.cnf /root/.my.cnf creates=/root/.my.cnf

View File

@ -1,17 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Rename MySQL upstart script
sudo: yes
command: mv -f /etc/init/mysql.conf /etc/init/mysql-boot-control.conf removes=/etc/init/mysql.conf

View File

@ -1,124 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: localhost
roles:
- { role: pre_flight_disk_check, fail_percent: 20, exclude_mounts: [] }
- hosts: undercloud
roles:
- { role: pre_flight_disk_check, fail_percent: 20, exclude_mounts: [], when: instance_status == "ACTIVE" }
- hosts: controller
vars:
num_bootstrap_hosts: "{{ groups['controller-bootstrap'] | length }}"
expected_bootstrap_hosts: 1
num_controller_hosts: "{{ groups['controller'] | length }}"
expected_controller_hosts: 2
tasks:
- name: "Verify correct number of controller bootstrap nodes"
fail: >
msg="The number of bootstrap nodes is "{{ num_bootstrap_hosts }}" \
must be exactly "{{ expected_bootstrap_hosts }}"!"
when: num_bootstrap_hosts | int != expected_bootstrap_hosts
- name: "Verify correct number of controller non-bootstrap nodes"
fail: >
msg="The number of controller non-bootstrap nodes is \
"{{ num_controller_hosts }}" must be exactly \
"{{ expected_controller_hosts }}"!"
when: num_controller_hosts | int != expected_controller_hosts
- hosts: controller-bootstrap:controller
name: "Check Controller Node Status - Ensuring MySQL is running"
sudo: yes
gather_facts: yes
max_fail_percentage: 0
tasks:
- name: "Verify controller nodes are ACTIVE"
fail: >
msg="One of more controller nodes don't have a status of \
ACTIVE in nova, cannot proceed with update"
when: instance_status != "ACTIVE"
- name: "Rename MySQL upstart configuration, if necessary, to obtain correct results."
sudo: yes
command: mv -f /etc/init/mysql.conf /etc/init/mysql-boot-control.conf removes=/etc/init/mysql.conf
when: instance_status == "ACTIVE"
- name: "Ensuring MySQL is running - If this fails, the cluster is likely not in a healthy state, and manual checks/recovery will be required."
service: name=mysql state=started
when: instance_status == "ACTIVE"
- hosts: controller-bootstrap
name: Check RabbitMQ Bootstrap Node
sudo: yes
gather_facts: yes
max_fail_percentage: 0
tasks:
- name: "Execute RabbitMQ status Check to verify RabbitMQ is running."
sudo: yes
shell: rabbitmqctl -n rabbit@$(hostname) status
when: instance_status == "ACTIVE"
register: rabbitmq_status
ignore_errors: yes
- name: "Attempting to start RabbitMQ - Bootstrap Node"
service: name=rabbitmq-server state=started
when: rabbitmq_status.rc != 0
- name: "Checking RabbitMQ Cluster Status - Bootstrap Node"
shell: rabbitmqctl -n rabbit@$(hostname) status
- hosts: controller
name: "Check RabbitMQ server status"
sudo: yes
gather_facts: yes
max_fail_percentage: 0
tasks:
- name: "Execute RabbitMQ status Check to verify RabbitMQ is running."
shell: rabbitmqctl -n rabbit@$(hostname) status
when: instance_status == "ACTIVE"
register: rabbitmq_status
ignore_errors: yes
- name: "Attempting to start RabbitMQ"
service: name=rabbitmq-server state=started
when: rabbitmq_status.rc != 0
- name: "Checking RabbitMQ Cluster Status"
shell: rabbitmqctl -n rabbit@$(hostname) status
- hosts: controller-bootstrap:controller
name: Check controller MySQL Sync status
gather_facts: no
max_fail_percentage: 0
tasks:
- name: "Querying MySQL to determine Galera cluster status"
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf --socket /var/run/mysqld/mysqld.sock -N -e "SHOW STATUS LIKE 'wsrep_local_state'"|cut -f2
when: helion is not defined
register: wsrep_local_state
- name: "Querying MySQL to determine Galera cluster size"
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf --socket /var/run/mysqld/mysqld.sock -N -e "SHOW STATUS LIKE 'wsrep_cluster_size'"|cut -f2
when: helion is not defined
register: wsrep_cluster_size
- fail: msg="Galera wsrep_local_state is not indicating a healthy state, cluster node may be out of sync, manual intervention required."
when: helion is not defined and wsrep_local_state.stdout != "4"
- fail: msg="Galera cluster size is being reported as a single node. The cluster is in an unsafe, possibly split brain state."
when: helion is not defined and wsrep_cluster_size.stdout == "1"
# Helion
- name: "Querying MySQL to determine Galera cluster status - Helion"
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf -N -e "SHOW STATUS LIKE 'wsrep_local_state'"|cut -f2
when: helion is defined
register: wsrep_local_state
- name: "Querying MySQL to determine Galera cluster size - Helion"
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf -N -e "SHOW STATUS LIKE 'wsrep_cluster_size'"|cut -f2
when: helion is defined
register: wsrep_cluster_size
- fail: msg="Galera wsrep_local_state is not indicating a healthy state, cluster node may be out of sync, manual intervention required."
when: helion is defined and wsrep_local_state.stdout != "4"
- fail: msg="Galera cluster size is being reported as a single node. The cluster is in an unsafe, possibly split brain state."
when: helion is defined and wsrep_cluster_size.stdout == "1"

View File

@ -1,33 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Removing any pre-existing host key backup directory"
sudo: yes
file: path=/mnt/state/_ssh_host_keys state=absent
- name: "Create ssh host key backup directory"
sudo: yes
file:
path=/mnt/state/_ssh_host_keys
state=directory
owner=root
group=root
mode=0700
- name: "Preserve ssh host keys"
sudo: yes
action: shell cp -a /etc/ssh/ssh_host_* /mnt/state/_ssh_host_keys/
- name: "Issue Sync to OS in order to help mitigate unsafe disk caching in virtualized environments."
command: sync
- name: "Pausing for 15 seconds to allow for any delayed IO in unsafe disk caches to be written to disk."
pause: seconds=15

View File

@ -1,26 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Determine if node is part of a cluster
shell: grep -q "$(hostname)" "/mnt/state/var/lib/rabbitmq/mnesia/rabbit@$(hostname)/cluster_nodes.config"
ignore_errors: yes
register: rabbit_cluster_test
- name: Collect names of post-configure.d rabbitmq files
shell: ls "{{os_refresh_config_folder}}/post-configure.d/"|grep '\-rabbitmq$'
register: test_rabbitmq_script_list
when: rabbit_cluster_test.rc == 0
- name: If node rabbitmq cluster config was present, prevent os-refresh-config post-configure.d job from executing.
file: mode=0644 path="{{os_refresh_config_folder}}/post-configure.d/{{item}}"
when: rabbit_cluster_test.rc == 0
with_items: test_rabbitmq_script_list.stdout_lines

View File

@ -1,13 +0,0 @@
# Additional Steps for controller nodes only to rejoin the cluster
- name: Get the bootstrap hostname
set_fact:
bootstrap_hostname={{ hostvars[groups['controller-bootstrap'][0]]['ansible_hostname'] }}
- name: Stop the RabbitMQ application to enable rejoining the cluster
command: rabbitmqctl stop_app
sudo: yes
- name: Re-join the RabbitMQ cluster
command: rabbitmqctl join_cluster "rabbit@{{ bootstrap_hostname }}"
failed_when: bootstrap_hostname is not defined
- name: Start the RabbitMQ application
command: rabbitmqctl start_app
sudo: yes

View File

@ -1,47 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Setting default fact indicating no rebuild has yet taken place"
set_fact: instance_rebuilt=false
- name: "Call nova_rebuild if instance needs to be updated"
nova_rebuild:
instance_id: "{{ instance_id }}"
image_id: "{{ rebuild_image_id }}"
preserve_ephemeral: true
wait: "yes"
wait_for: 900
delegate_to: localhost
when: instance_image_id != rebuild_image_id and force_rebuild is not defined
register: test_rebuild_normal
- name: "Record that instance was rebuilt under normal circumstances"
set_fact: instance_rebuilt=true
when: test_rebuild_normal.changed == true
- name: "Call nova_rebuild if rebuild is mandated"
nova_rebuild:
instance_id: "{{ instance_id }}"
image_id: "{{ rebuild_image_id }}"
preserve_ephemeral: true
wait: "yes"
wait_for: 900
delegate_to: localhost
when: force_rebuild is defined
register: test_rebuild_forced
- name: "Record that instance was rebuilt under normal circumstances"
set_fact: instance_rebuilt=true
when: test_rebuild_forced.changed == true
- name: "If we did not rebuild, and the image IDs already match, trigger the ephemeral disk to remount."
sudo: yes
command: "{{os_refresh_config_folder}}/pre-configure.d/00-fix-ephemeral-mount"
when: instance_image_id == rebuild_image_id and force_rebuild is not defined or instance_rebuilt == false

View File

@ -1,34 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
# Update the collect files to contain metadata obtained from Heat
#
- name: "Ensure heat local-data directory exists"
sudo: yes
file: path=/var/lib/os-collect-config/local-data state=directory
- name: "Copy deployments exploder script"
sudo: yes
copy:
src: files/explode-deployments.py
dest: /usr/local/bin/explode-deployments
mode: 0755
- name: "Write out metadata"
sudo: yes
template:
src: templates/host_metadata.json.j2
dest: /var/lib/os-collect-config/local-data/host_metadata.json
- name: "Explode deployments"
sudo: yes
command: /usr/local/bin/explode-deployments /var/lib/os-collect-config/local-data

View File

@ -1,23 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Tell the cloud to shutdown via nova_powercontrol.
nova_powercontrol:
login_username: "{{ lookup('env',OC_OS_USERNAME'}}"
login_password: "{{ lookup('env',OC_OS_PASSWORD'}}"
login_tenant_name: "{{ lookup('env',OC_OS_TENANT_NAME'}}"
auth_url: "{{ lookup('env',OC_OS_AUTH_URL'}}"
all_instances: yes
state: previous
when: use_nova_powercontrol is defined

View File

@ -1,24 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Restore ssh host keys"
sudo: yes
action: shell mv /mnt/state/_ssh_host_keys/ssh_host_* /etc/ssh/
- name: "Remove ssh host key backup directory"
sudo: yes
file:
path=/mnt/state/_ssh_host_keys
state=absent

View File

@ -1,28 +0,0 @@
Pre-flight disk check
=====================
This role can be used to check for sufficient free disk space on
hosts, and will fail if there is not enough space. The amount of space
may be specified as a fixed amount (in bytes) using the `fail_size`
variable, or as a percentage of the total, using the `fail_percent`
variable. Additionally, mounted filesystems can be excluded by mount
name, if specified, in `exclude_mounts`.
To use the role, either include as usual (to use the default values
specified in defaults/main.yml::
- hosts: hostgroup
roles:
- preflight_disk_check
Or specify your own values when you add the role, as follows::
- hosts: hostgroup
roles:
- { role: preflight_disk_check, fail_percent: 10,
exclude_mounts: [ "/mnt" ], when: instance_status == "ACTIVE"
}
This will allow you to easily set different parameters for different
types of hosts in your playbook. Note that only one of `fail_percent`
or `fail_size` will be used.

View File

@ -1,20 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
fail_percent: 10
fail_size:
exclude_mounts: []

View File

@ -1,23 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Check if free disk percentage is too low
fail: msg="ERROR - {{ item.size_available|filesizeformat }} is not enough (need at least {{ fail_percent }}% free)"
with_items: "hostvars[inventory_hostname].ansible_mounts"
when: item.mount not in exclude_mounts and fail_percent is defined and "{{ ((item.size_available / item.size_total) * 100)|round|int }}"|int < fail_percent
- name: Check if free disk size is too low
fail: msg="ERROR - {{ item.size_available|filesizeformat }} is not enough (need at least {{ fail_size }} free)"
with_items: "hostvars[inventory_hostname].ansible_mounts"
when: item.mount not in exclude_mounts and fail_size is defined and "{{ item.size_available }}"|int < fail_size

View File

@ -1,36 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: controller
name: Enable Overcloud Controller
sudo: yes
tasks:
- service: name={{ item }} enabled=yes state=started
with_items: overcloud_controller_services
- hosts: nova-compute
name: Enable Overcloud Compute
sudo: yes
tasks:
- name: "Run os-collect-config"
sudo: yes
command: os-collect-config --force --one
- service: name={{ item }} enabled=yes state=started
with_items: overcloud_compute_services
- hosts: undercloud
name: Enable Undercloud
sudo: yes
tasks:
- service: name={{ item }} enabled=yes state=started
with_items: undercloud_services

View File

@ -1,19 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Rename MySQL upstart script
sudo: yes
command: mv -f /etc/init/mysql.conf /etc/init/mysql-boot-control.conf removes=/etc/init/mysql.conf
- service: name=mysql state=started enabled=yes
sudo: yes

View File

@ -1,38 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Determine if node is part of a cluster
shell: grep -q "$(hostname)" "/mnt/state/var/lib/rabbitmq/mnesia/rabbit@$(hostname)/cluster_nodes.config"
ignore_errors: yes
register: rabbit_cluster_test
- name: Collect names of post-configure.d rabbitmq files
shell: ls "{{os_refresh_config_folder}}/post-configure.d/"|grep '\-rabbitmq$'
register: test_rabbitmq_script_list
when: rabbit_cluster_test.rc == 0
- name: If node rabbitmq cluster config was present, prevent os-refresh-config post-configure.d job from executing.
file: mode=0644 path="{{os_refresh_config_folder}}/post-configure.d/{{item}}"
when: rabbit_cluster_test.rc == 0
with_items: test_rabbitmq_script_list.stdout_lines
sudo: yes
- name: "Enable rabbitmq"
command: os-svc-enable -n rabbitmq-server
sudo: yes
- name: "Replace rabbitmq-server override to avoid conditions where RabbitMQ can block upgrade."
copy: src=files/rabbitmq-server.override dest=/etc/init/ owner=root group=root mode=0644
sudo: yes
- name: Start rabbitmq before os-collect-config if previously configured
service: name=rabbitmq-server state=started
sudo: yes
- name: Wait for Rabbit to listen on its usual port
wait_for: port=5672 state=started timeout=90 delay=10

View File

@ -1,35 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: undercloud
name: Check we have undercloud image ID for rebuild
tasks:
- fail: msg="undercloud_rebuild_image_id is not defined"
when: undercloud_rebuild_image_id is not defined or undercloud_rebuild_image_id == "" or undercloud_rebuild_image_id == None
- hosts: controller
name: Check we have controller image ID for rebuild
tasks:
- fail: msg="controller_rebuild_image_id is not defined"
when: controller_rebuild_image_id is not defined or controller_rebuild_image_id == "" or controller_rebuild_image_id == None
- hosts: swift-storage
name: Check we have swift storage image ID for rebuild
tasks:
- fail: msg="swift_storage_rebuild_image_id is not defined"
when: swift_storage_rebuild_image_id is not defined or swift_storage_rebuild_image_id == "" or swift_storage_rebuild_image_id == None
- hosts: nova-compute
name: Check we have nova compute image ID for rebuild
tasks:
- fail: msg="nova_compute_rebuild_image_id is not defined"
when: nova_compute_rebuild_image_id is not defined or nova_compute_rebuild_image_id == "" or nova_compute_rebuild_image_id == None

View File

@ -1,25 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Cleaning up /mnt/state/_upgrade_recovery"
sudo: yes
file:
path: /mnt/state/_upgrade_recovery
state: absent
- name: "Cleaning up /tmp/upgrade_image.qcow2"
sudo: yes
file:
path: /tmp/upgrade_image.qcow2
state: absent

View File

@ -1,24 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Remove ssh from cloud-init job."
sudo: yes
command: sed -i 's/^ - ssh$/# - ssh/' /etc/cloud/cloud.cfg
- name: "Remove ssh-authkey-fingerprints from cloud-init job."
sudo: yes
command: sed -i 's/^ - ssh-authkey-fingerprints$/# - ssh-authkey-fingerprints/' /etc/cloud/cloud.cfg
- name: "Initiate cloudinit"
sudo: yes
command: /usr/bin/cloud-init init

View File

@ -1,26 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Pausing for 60 seconds to give MySQL time to become ready - Helion"
pause: seconds=60 prompt="Pausing for 60 seconds to give MySQL time to become ready"
when: helion is defined
- name: "Execute script to wait for MySQL to enter a Synced state"
sudo: yes
script: files/wait_for_database-helion.sh
when: helion is defined
- name: Triggering os-create-db on databases
sudo: yes
script: files/create-databases.sh
when: helion is defined

View File

@ -1,22 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Collect Open File List"
sudo: yes
shell: lsof -n|grep /mnt
- name: "Collect process list"
command: ps auxf
- name: "Fail"
fail: msg="The ephemeral storage of this system failed to be cleaned up properly and processes or files are still in use. The previous ansible play should have information to help troubleshoot this issue."

View File

@ -1,24 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
# This is primarilly due to the fact that we can possibly interrupt existing
# start-up sequences before this is done depending on system performance, and
# as a result be unable later on to start services such as rabbitmq-server.
#
# This at some point should be replaced with comperable code in Ansible
# to have the same end effect.
- name: Trigger hosts file generation
sudo: yes
command: "{{os_refresh_config_folder}}/configure.d/51-hosts"

View File

@ -1,18 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Initiate os-apply-config"
command: os-collect-config --force --one --command=os-apply-config
ignore_errors: yes
when: instance_rebuilt == true

View File

@ -1,7 +0,0 @@
---
- name: "Test Connectivity to all hosts"
hosts: all
serial: 1
tasks:
ping:
where: instance_status == "ACTIVE"

View File

@ -1,26 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Execute LOCAL command on this node"
hosts: localhost
gather_facts: no
sudo: yes
max_fail_percentage: 0
tasks:
- name: "Execute Locally defined command"
command: "{{ post_hook_command }}"
delegate_to: 127.0.0.1
when: post_hook_command is defined

View File

@ -1,26 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Execute LOCAL command on this node"
hosts: localhost
sudo: yes
gather_facts: no
max_fail_percentage: 0
tasks:
- name: "Execute Locally defined command"
command: "{{ pre_hook_command }}"
delegate_to: 127.0.0.1
when: pre_hook_command is defined

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Ensure /mnt/state/etc/iscsi/ exists"
sudo: yes
file: path=/mnt/state/etc/iscsi/ state=directory mode=0755
- name: "Backup /etc/iscsi/initiatorname.iscsi to /mnt/state/etc/iscsi/initiatorname.iscsi"
sudo: yes
command: cp -a /etc/iscsi/initiatorname.iscsi /mnt/state/etc/iscsi/initiatorname.iscsi

View File

@ -1,23 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Ensure /mnt/state/etc exists"
sudo: yes
file: path=/mnt/state/etc owner=root group=root mode=0755 state=directory
- name: "Saving a copy of /etc/passwd to /mnt/state/etc/passwd.backup"
sudo: yes
command: cp -a /etc/passwd /mnt/state/etc/passwd.backup
- name: "Saving a copy of /etc/group to /mnt/state/etc/passwd.backup"
sudo: yes
command: cp -a /etc/group /mnt/state/etc/group.backup

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Correcting Permissions for /mnt/state/var/log"
sudo: yes
script: files/correct_mnt_state_permissions.py -f /mnt/state/etc/passwd.backup -g /mnt/state/etc/group.backup -d /mnt/state/var/log
- name: "Correcting Permissions for /mnt/state/var/lib"
sudo: yes
script: files/correct_mnt_state_permissions.py -f /mnt/state/etc/passwd.backup -g /mnt/state/etc/group.backup -d /mnt/state/var/lib
- include: step_preserve_password_file.yml

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Restoring the open-iscsi initiator name file"
sudo: yes
command: cp -a /mnt/state/etc/iscsi/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
- name: "Restarting the open-iscsi service"
sudo: yes
service: name=open-iscsi state=restarted

View File

@ -1,35 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Remove os-collect-config disable sentinel file
file: path=/mnt/state/disable-os-collect-config state=absent
sudo: yes
- name: "Setting default fact to run os-collect-config"
set_fact: test_bypass_os_collect_config="False"
- name: "Evaluate if os-collect-config needs to be run"
command: grep -q -i "Completed phase migration" "{{os_collect_config_log}}"
register: test_did_os_collect_config_complete
ignore_errors: yes
when: online_upgrade is not defined
- name: "Setting fact to bypass os-collect-config if applicable"
set_fact: test_bypass_os_collect_config="True"
when: online_upgrade is not defined and test_did_os_collect_config_complete.rc == 0
- name: "Execute os-collect-config"
command: os-collect-config --force --one
when: test_bypass_os_collect_config != true
register: test_occ_results
until: test_occ_results.rc == 0
retries: 2
delay: 15

View File

@ -1,23 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Write image ID to instance disk for online upgrades to check"
sudo: yes
copy:
content: "{{ rebuild_image_id }}"
dest: /etc/tripleo_image_id
owner: root
group: root
mode: 0644

View File

@ -1,24 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
#
# Work around bug in init script that causes status to malfunction on tgt
# The service will happily start over and over but stopping is tricky
---
# After shutdown of neutron services, neutron-ns-metadata-proxy is still present
# This services logs to the ephemeral partition, so un-mounting is not possible
# No upstart scripts for this service, so needs to be killed.
- name: Kill neutron metadata proxy service
command: pkill -9 -f neutron-ns-metadata-proxy
ignore_errors: yes

View File

@ -1,27 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Collect Service Facts"
sudo: yes
service_facts:
when: instance_status == "ACTIVE"
- name: "Stop services"
sudo: yes
service: name={{ item }} enabled=no state=stopped
with_items: services_to_stop
when: instance_status == "ACTIVE" and item in existing_services
- include: stop_tgt.yml
when: instance_status == "ACTIVE"
sudo: yes

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Purge previous backup folder"
sudo: yes
file: path=/mnt/state/_upgrade_backup_tftpboot.tar.bz state=absent
- name: "Backup /tftpboot"
sudo: yes
command: tar --exclude='pxelinux.0' -cvjf /mnt/state/_upgrade_backup_tftpboot.tar.bz /tftpboot

View File

@ -1,25 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
# These steps are to address Ironic bug
# https://bugs.launchpad.net/ironic/+bug/1382698
- name: Reset Ironic Reservations
sudo: yes
command: mysql --defaults-file=/mnt/state/root/metadata.my.cnf --socket /var/run/mysqld/mysqld.sock ironic -e 'update nodes set reservation=NULL where reservation="{{ ansible_fqdn }}";'
when: helion is not defined
- name: Reset Ironic Reservations - Helion
sudo: yes
shell: mysql --defaults-file=/mnt/state/root/metadata.my.cnf ironic -e 'update nodes set reservation=NULL where reservation="{{ ansible_fqdn }}";'
when: helion is defined

View File

@ -1,18 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Restore /tftpboot contents"
sudo: yes
command: tar -C / -xvjf /mnt/state/_upgrade_backup_tftpboot.tar.bz tftpboot

View File

@ -1,23 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Change /mnt to be a read-only mount-point"
sudo: yes
command: umount /mnt
ignore_errors: True
register: test_remount
when: instance_status == "ACTIVE" and online_upgrade is not defined
- include: step_fail_unmount.yml
when: instance_status == "ACTIVE" and online_upgrade is not defined and test_remount.rc != 0

View File

@ -1,197 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Fail upgrade if node status is not ACTIVE"
fail: "Failure: Node MUST be in ACTIVE state to proceed. Online upgrade cannot be completed, please consider a standard image rebuild upgrade."
when: instance_status != "ACTIVE"
- name: "Setting default fact indicating no rebuild has yet taken place"
set_fact: instance_rebuilt=false
- name: "Setting default policy to run upgrade"
set_fact: test_run_upgrade=true
- name: "Compare, if applicable, the currently deployed image id"
command: grep -q "{{ rebuild_image_id }}" /etc/tripleo_image_id
when: force_rebuild is not defined
register: test_check_version
ignore_errors: yes
- name: "Set action to false if rebuild is not being forced and currently deployed version matches what is being deployed"
set_fact: test_run_upgrade=false
when: force_rebuild is not defined and test_check_version.rc == 0
- name: "Ensure qemu-utils and rsync are installed"
sudo: yes
# This will require gather_facts to have logic at some point to
# support operating systems that do not use apt.
apt: pkg={{ item }} state=present
with_items:
- qemu-utils
- rsync
when: test_run_upgrade == true
- name: "Load nbd kernel module"
sudo: yes
modprobe:
name: nbd
state: present
params: "max_part=16"
when: test_run_upgrade == true
- name: "Triggering upload of image to node"
sudo: yes
include: step_upload_image.yml
vars:
update_image: "/tmp/image-{{ rebuild_image_id }}.qcow2"
when: online_upgrade is defined and test_run_upgrade == true
- name: "Creating directory for update to run from on node"
sudo: yes
file:
path: /tmp/update_image
state: directory
when: test_run_upgrade == true
- name: "Ensuring that the mountpoint is not already mounted"
sudo: yes
command: umount /tmp/update_image
ignore_errors: yes
when: test_run_upgrade == true
- name: "Ensuring that the image is not already attached"
sudo: yes
command: /usr/bin/qemu-nbd -d /dev/nbd4
ignore_errors: yes
when: test_run_upgrade == true
- name: "Attaching update image"
sudo: yes
command: /usr/bin/qemu-nbd -c /dev/nbd4 "{{ default_update_file_location }}"
when: test_run_upgrade == true
- name: "Preserving ssh keys in case online upgrade fails and full rebuild is required to recover"
include: preserve_ssh_host_keys.yml
when: online_upgrade is defined and test_run_upgrade == true
- name: "Ensure that a previous online upgrade folder does not exist"
sudo: yes
file: path=/mnt/state/_upgrade_recovery state=absent
when: test_run_upgrade == true
- name: "Make an upgrade recovery folder on the ephemeral disk"
sudo: yes
file: path=/mnt/state/_upgrade_recovery state=directory owner=root group=root mode=0700
when: test_run_upgrade == true
- name: "Backup /etc to /mnt/state/_upgrade_recovery"
sudo: yes
shell: cp -a /etc /mnt/state/_upgrade_recovery/
- name: "Backup /var/log to /mnt/state/_upgrade_recovery"
sudo: yes
shell: mkdir /mnt/state/_upgrade_recovery/var ; cp -a /var/log /mnt/state/_upgrade_recovery/var/
- name: "Attaching image to mount point"
sudo: yes
command: mount /dev/nbd4 /tmp/update_image
when: test_run_upgrade == true
# The next several steps are intended as a feature to prevent an
# image from being utilized in this fashion that is is known to be
# incompatible (i.e. incompatible base library changes that would
# normally result in a system being left in a damaged state).
- name: "Verify that the disk image does not contain a warning flag"
shell: test -x /tmp/update_image/boot/tripleo_incompatible_upgrade
when: test_run_upgrade == true
register: test_abort_incompatible
ignore_errors: yes
- name: "If aborting, detach update image mountpoint"
sudo: yes
command: umount /tmp/update_image
when: test_run_upgrade == true and test_abort_incompatible.rc == 0
- name: "If aborting, detach image"
sudo: yes
command: /usr/bin/qemu-nbd -d /dev/nbd4
when: test_run_upgrade == true and test_abort_incompatible.rc == 0
- name: "If aborting, fail."
fail: "Image is marked as being incompatible for online upgrades. Please attempt a normal upgrade."
when: test_run_upgrade == true and test_abort_incompatible.rc == 0
- name: "Ensure folder exists for rsync log to be housed"
sudo: yes
file: path=/mnt/state/var/log/online_upgrade state=directory owner=root group=root mode=0700
when: test_run_upgrade == true
- name: "Pre-flight check that we appear to have an image mounted"
shell: test -e /tmp/update_image/boot
when: test_run_upgrade == true
register: test_is_update_image
ignore_errors: yes
- name: "Fail if image does not appear to be valid"
fail: "ERROR: Upgrade image did not mount, or is not valid."
when: test_run_upgrade == true and test_is_update_image.rc != 0
- name: "Initiating update of files, this may take a while."
sudo: yes
# The following list of files excluded are to ensure access by Ansible
# and continuation of existing processes with minimal impact.
# * /tmp - Excluded as this is the source folder
# * /etc/hosts - Excluded as it is normally populated with host information
# by os-collect-config, and being in a reverted state causes latency while
# the host is attempting to resolve the IP address of the node connecting.
# * /etc/ssh/ssh_host_* - This is to preserve the ssh host keys so Ansible
# is able to reconnect.
# * /etc/passwd /etc/shadow /etc/group - These are preserved so Ansible
# is able to log back into the system after the system after the sync
# has been completed as the heat-admin user is not bured into the image.
# * /home/heat-admin - Same case as above.
# * /mnt - Excluded as it is the ephemeral volume mount point.
# * /var/log - Excluded to preserve logs.
# * /lib/modules/$(uname -r) - The current running kernel's modules, which
# need to be kept on disk until a kernel upgrade takes place.
# * /var/lib/heat-* /var/lib/os-collect-config /var/lib/cloud - These
# folders are preserved in order to give the instance a head start on
# starting back up. Additionally /var/lib/cloud contains semaphor locks
# that block operations that would be unsafe to perform at the time of an
# upgrade.
# * /dev - Excluded as the image contains a basic /dev folder, but the host
# operates with devfs. Removal of files from devfs will result in
# unpredictable behavior.
# /var/cache/libvirt/qemu/capabilties /var/lib/libvirt - Removal of these
# files will cause the current virtual machines to stop as they contain
# state information.
# * /var/lib/dhcpd/*.leases - Excluded as we want the DHCP client to attempt
# a renewal instead of requesting a new address.
# * /var/lib/openvswitch - Excluded as it contains the state information for
# openvswitch and we want openvswitch to be running as long as possible
# for minimal connectivity impact to the running virtual machines.
shell: rsync -axHAXv /tmp/update_image/ / --exclude=/tmp --exclude=/etc/hosts --exclude='/etc/ssh/ssh_host_*' --exclude=/etc/passwd --exclude=/etc/shadow --exclude=/etc/group --exclude=/etc/sudoers --exclude=/home/heat-admin --exclude=/mnt --exclude=/var/log --exclude="/lib/modules/$(uname -r)" --exclude='/var/lib/heat-*' --exclude='/dev/' --exclude='/var/cache/libvirt/qemu/capabilities' --exclude='/var/lib/os-collect-config' --exclude='/var/lib/cloud' --exclude='/var/lib/libvirt' --exclude='/var/lib/dhcp/*.leases' --exclude='/var/lib/openvswitch' --delete-after | tee -a /mnt/state/var/log/online_upgrade/rsync.log ; cp -at /etc/ssh/ /mnt/state/_ssh_host_keys/ssh_host_* ; cp -at /etc/ /mnt/state/_upgrade_recovery/etc/hosts /mnt/state/_upgrade_recovery/etc/mtab
when: test_run_upgrade == true
register: test_rsync_completed
- name: "Record that instance was rebuilt under normal circumstances"
set_fact: instance_rebuilt=true
when: test_rsync_completed.rc == 0
- name: "Restart ssh service"
sudo: yes
service: name=ssh state=restarted
# Note: gather_facts will be required to support restarting on
# systems that use different names for their ssh services.
when: test_run_upgrade == true
- name: "Detach update image mountpoint"
sudo: yes
command: umount /tmp/update_image
when: test_run_upgrade == true
# bounce any core services like ssh TODO
- name: "Remove the post-rsync folder"
sudo: yes
file:
path: /tmp/update_image
state: absent
when: test_run_upgrade == true
- name: "Ensure qemu-utils is installed"
sudo: yes
# This will require gather_facts to have logic at some point to
# support operating systems that do not use apt.
apt: pkg={{ item }} state=present
with_items:
- qemu-utils
when: test_run_upgrade == true
- name: "Detach upgrade image"
sudo: yes
command: /usr/bin/qemu-nbd -d /dev/nbd4
when: test_run_upgrade == true
# NOTE: Should TripleO one day support booting from the local block
# device, then this is roughly the locaion where support for updating
# the boot loader would be added.

View File

@ -1,24 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
#
# NOTE: This playbook MUST be executed one instance at a time as it
# is notsafe to allow multiple machines to execute this task at one
# time.
---
- name: "Download Image"
glance_download:
image_id: "{{ nova_compute_rebuild_image_id }}"
path: "/tmp/image-{{ rebuild_image_id }}.qcow2"
delegate_to: localhost

View File

@ -1,26 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- include: preserve_ssh_host_keys.yml
when: instance_status == "ACTIVE"
- include: step_unmount.yml
when: instance_status == "ACTIVE"
- { include: rebuild.yml, instance_id: "{{ instance_id }}", when: instance_status != "REBUILD" }
- local_action: wait_for port=22 timeout="{{ ssh_timeout }}" host="{{ inventory_hostname }}" search_regex=TRIPLEO_HK_RESTORED delay=10
when: wait_for_hostkey is defined
ignore_errors: yes
- local_action: wait_for port=22 timeout="{{ ssh_timeout }}" host="{{ inventory_hostname }}" search_regex=OpenSSH delay=10
when: wait_for_hostkey is not defined
ignore_errors: yes
- include: refresh_config.yml

View File

@ -1,22 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: "Upload Image to remote host"
synchronize:
compress: yes
checksum: yes
archive: yes
src: "{{ update_image }}"
dest: "{{ default_update_file_location }}"

View File

@ -1,30 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: controller
name: "Disable OpenStack Controller Services"
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: control-services
- hosts: nova-compute
name: "Disable OpenStack Compute"
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: compute-services
- hosts: undercloud
name: "Disable OpenStack Undercloud Services"
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: undercloud-services

View File

@ -1,21 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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: Stopping mysql and disabling via upstart
service: name=mysql state=stopped enabled=no
sudo: yes
- name: Removing mysql starting via sysv
command: update-rc.d mysql remove
sudo: yes
when: helion is defined

View File

@ -1,23 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
#
# Work around bug in init script that causes status to malfunction on tgt
# The service will happily start over and over but stopping is tricky
- name: Stop TGT
sudo: yes
service: name=tgt state=stopped enabled=no
ignore_errors: yes
- name: Wait for TGT to be down
wait_for: port=3260 state=stopped timeout=300

View File

@ -1,56 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- service_facts:
when: instance_status == "ACTIVE"
- name: Ensure libvirt daemon is running
sudo: yes
service: name={{ item }} state=started enabled=yes
when: use_nova_powercontrol is not defined and item in existing_services
with_items: hypervisor_daemons
- name: Collect list of VMs
sudo: yes
virt: command=list_vms
register: virtual_machines
when: use_nova_powercontrol is not defined
- name: Issue graceful shutdowns
sudo: yes
virt: state=shutdown name={{item}}
when: use_nova_powercontrol is not defined
with_items: virtual_machines.list_vms
- name: Tell the cloud to shutdown via nova_powercontrol.
nova_powercontrol:
login_username: "{{ lookup('env',OC_OS_USERNAME'}}"
login_password: "{{ lookup('env',OC_OS_PASSWORD'}}"
login_tenant_name: "{{ lookup('env',OC_OS_TENANT_NAME'}}"
auth_url: "{{ lookup('env',OC_OS_AUTH_URL'}}"
all_instances: yes
state: stopped
when: use_nova_powercontrol is defined
- name: Pausing for 60 seconds to give VMs time to stop.
pause: seconds=60
- name: Collect list of VMs
sudo: yes
virt: command=list_vms
register: virtual_machines
when: use_nova_powercontrol is not defined
- name: Issue graceful shutdowns
sudo: yes
virt: state=shutdown name={{item}}
when: use_nova_powercontrol is not defined
with_items: virtual_machines.list_vms
register: test_from_second_shutdown_call
- name: "Fail if virtual machines were still running"
fail: msg="If the ansible playbook has failed and exited at this point, virtual machines were still running on the compute node after sixty seconds passed from the shutdown commands having been initiated. Please retry and/or manually ensure that virtual machines on the nodes to be updated have been shut down."
when: use_nova_powercontrol is not defined and test_from_second_shutdown_call.changed == true

View File

@ -1,12 +0,0 @@
{
"deployments": [],
"os-collect-config": {
"cfn": {
"stack_name": "{% stack_name %},
"metadata_url": "{% metadata_url %},
"access_key_id": "{% access_key_id %},
"secret_access_key": "{% sercret_access_key %}",
"path": "{% path %}"
}
}
}

Some files were not shown because too many files have changed in this diff Show More