commit e97c013f673f03fd3dfd8abfc92a33c47f83a304 Author: Kevin Carter Date: Thu Feb 1 22:12:31 2018 -0600 First commit Signed-off-by: Kevin Carter diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5421f90 --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so +*.pyc +build/ +dist/ +doc/build/ + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite +logs/* + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +.idea +.tox +*.sublime* +*.egg-info +Icon? +ehthumbs.db +Thumbs.db +.eggs + +# User driven backup files # +############################ +*.bak +*.swp + +# Generated by pbr while building docs +###################################### +AUTHORS +ChangeLog + +# Files created by releasenotes build +releasenotes/build + +# Test temp files +tests/common +tests/*.retry + +# Vagrant artifacts +.vagrant + +# Git clones +openstack-ansible-ops diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..f696c70 --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=review.openstack.org +port=29418 +project=openstack/openstack-ansible-nspawn_hosts.git diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..bec9fb3 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,83 @@ +OpenStack nspawn host setup +########################### + +contributor guidelines +^^^^^^^^^^^^^^^^^^^^^^ + +Filing Bugs +----------- + +Bugs should be filed on Launchpad, not GitHub: "https://bugs.launchpad.net/openstack-ansible" + + +When submitting a bug, or working on a bug, please ensure the following criteria are met: + * The description clearly states or describes the original problem or root cause of the problem. + * Include historical information on how the problem was identified. + * Any relevant logs are included. + * The provided information should be totally self-contained. External access to web services/sites should not be needed. + * Steps to reproduce the problem if possible. + + +Submitting Code +--------------- + +Changes to the project 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 and closed without regard. + + +Extra +----- + +Tags: + If it's a bug that needs fixing in a branch in addition to Master, add a '\-backport-potential' tag (eg ``juno-backport-potential``). There are predefined tags that will autocomplete. + +Status: + Please leave this alone, it should be New till someone triages the issue. + +Importance: + Should only be touched if it is a Blocker/Gating issue. If it is, please set to High, and only use Critical if you have found a bug that can take down whole infrastructures. + + +Style guide +----------- + +When creating tasks and other roles for use in Ansible please create then using the YAML dictionary format. + +Example YAML dictionary format: + .. code-block:: yaml + + - name: The name of the tasks + module_name: + thing1: "some-stuff" + thing2: "some-other-stuff" + tags: + - some-tag + - some-other-tag + + +Example **NOT** in YAML dictionary format: + .. code-block:: yaml + + - name: The name of the tasks + module_name: thing1="some-stuff" thing2="some-other-stuff" + tags: + - some-tag + - some-other-tag + + +Usage of the ">" and "|" operators should be limited to Ansible conditionals and command modules such as the ansible ``shell`` module. + + +Issues +------ + +When submitting an issue, or working on an issue please ensure the following criteria are met: + * The description clearly states or describes the original problem or root cause of the problem. + * Include historical information on how the problem was identified. + * Any relevant logs are included. + * If the issue is a bug that needs fixing in a branch other than Master, add the ‘backport potential’ tag TO THE ISSUE (not the PR). + * The provided information should be totally self-contained. External access to web services/sites should not be needed. + * If the issue is needed for a hotfix release, add the 'expedite' label. + * Steps to reproduce the problem if possible. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + 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. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..ff25b8f --- /dev/null +++ b/README.rst @@ -0,0 +1,20 @@ +======================== +Team and repository tags +======================== + +.. image:: http://governance.openstack.org/badges/openstack-ansible-nspawn_hosts.svg + :target: http://governance.openstack.org/reference/tags/index.html + +.. Change things from this point on + +=========================== +OpenStack-Ansible nspawn hosts +=========================== + +Ansible role that configures a host for running nspawn containers. + +Documentation for the project can be found at: + https://docs.openstack.org/openstack-ansible-nspawn_hosts/latest + +The project home is at: + http://launchpad.net/openstack-ansible diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..79d67de --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,49 @@ +# Note: +# This file is maintained in the openstack-ansible-tests repository. +# https://git.openstack.org/cgit/openstack/openstack-ansible-tests/tree/Vagrantfile +# +# If you need to perform any change on it, you should modify the central file, +# then, an OpenStack CI job will propagate your changes to every OSA repository +# since every repo uses the same Vagrantfile + +# Verify whether required plugins are installed. +required_plugins = [ "vagrant-disksize" ] +required_plugins.each do |plugin| + if not Vagrant.has_plugin?(plugin) + raise "The vagrant plugin #{plugin} is required. Please run `vagrant plugin install #{plugin}`" + end +end + +Vagrant.configure(2) do |config| + config.vm.provider "virtualbox" do |v| + v.memory = 4096 + v.cpus = 2 + end + + config.vm.synced_folder ".", "/vagrant", type: "rsync" + + config.vm.provision "shell", + privileged: false, + inline: <<-SHELL + cd /vagrant + ./run_tests.sh + SHELL + + config.vm.define "ubuntu1604" do |xenial| + xenial.disksize.size = "40GB" + xenial.vm.box = "ubuntu/xenial64" + end + + config.vm.define "opensuse422" do |leap422| + leap422.vm.box = "opensuse/openSUSE-42.2-x86_64" + end + + config.vm.define "opensuse423" do |leap423| + leap423.vm.box = "opensuse/openSUSE-42.3-x86_64" + end + + config.vm.define "centos7" do |centos7| + centos7.vm.box = "centos/7" + end + +end diff --git a/bindep.txt b/bindep.txt new file mode 100644 index 0000000..5a05c5a --- /dev/null +++ b/bindep.txt @@ -0,0 +1,52 @@ +# This file facilitates OpenStack-CI package installation +# before the execution of any tests. +# +# See the following for details: +# - https://docs.openstack.org/infra/bindep/ +# - https://git.openstack.org/cgit/openstack-infra/bindep +# +# Even if the role does not make use of this facility, it +# is better to have this file empty, otherwise OpenStack-CI +# will fall back to installing its default packages which +# will potentially be detrimental to the tests executed. +# +# Note: +# This file is maintained in the openstack-ansible-tests repository. +# https://git.openstack.org/cgit/openstack/openstack-ansible-tests/tree/bindep.txt +# If you need to remove or add extra dependencies, you should modify +# the central file instead and once your change is accepted then update +# this file as well. The purpose of this file is to ensure that Python and +# Ansible have all their necessary binary requirements on the test host before +# tox executes. Any binary requirements needed by services/roles should be +# installed by those roles in their applicable package install tasks, not through +# using this file. +# + +# The gcc compiler +gcc + +# Base requirements for Ubuntu +git-core [platform:dpkg] +libssl-dev [platform:dpkg] +libffi-dev [platform:dpkg] +python2.7 [platform:dpkg] +python-apt [platform:dpkg] +python-dev [platform:dpkg] +python3 [platform:dpkg] +python3-apt [platform:dpkg] +python3-dev [platform:dpkg] + +# Base requirements for RPM distros +gcc-c++ [platform:rpm] +git [platform:rpm] +libffi-devel [platform:rpm] +openssl-devel [platform:rpm] +python-devel [platform:rpm] +python2-dnf [platform:fedora] + +# For SELinux +libselinux-python [platform:redhat] +libsemanage-python [platform:redhat] + +# Required for compressing collected log files in CI +gzip diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..c29bcf3 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,53 @@ +--- +# Copyright 2018, Rackspace US, Inc. +# +# 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. + +nspawn_networks: + nspawn_address: + # The name of the bridge network, by default this is the interface with the default route + bridge: "{{ ansible_default_ipv4.interface | default('br-nspawn') }}" + # Optional | Enable or disable dhcp on this network + enable_dhcp: true + # Optional | When dhcp is enabled set the IP address range + dhcp_range: 10.0.4.2,10.0.4.129 + # Optional | Set the address for the macvlan network + address: 10.0.4.1 + # Optional | Set the netmask for the macvlan network + netmask: 255.255.255.0 + +# See all available options here: +# https://www.freedesktop.org/software/systemd/man/systemd.netdev.html#%5BMACVLAN%5D%20Section%20Options +nspawn_macvlan_mode: bridge + +nspawn_host_machine_volume_size: 64G + +nspawn_host_machine_quota_disabled: true +nspawn_hosts_validate_certs: true +nspawn_hosts_package_state: "latest" + +nspawn_image_cache_refresh: false +nspawn_image_cache_server_mirrors: + - https://us.images.linuxcontainers.org + - https://uk.images.linuxcontainers.org + +nspawn_cache_default_variant: "default" +nspawn_cache_prep_pre_commands: "" +nspawn_cache_prep_post_commands: "" +nspawn_cache_prep_dns: + - "208.67.222.222" + - "8.8.8.8" + +nspawn_container_base_name: "{{ nspawn_cache_map.distro }}-{{ nspawn_cache_map.release }}-{{ nspawn_cache_map.arch }}" + +nspawn_container_cache_files_from_host: [] diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..eb9a59e --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,195 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/openstack-ansible-nspawn_hosts.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/openstack-ansible-nspawn_hosts.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/openstack-ansible-nspawn_hosts" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/openstack-ansible-nspawn_hosts" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +livehtml: html + sphinx-autobuild -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..dc9c887 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,328 @@ +#!/usr/bin/env python3 + +# 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 file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import pbr.version +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'openstackdocstheme', + 'sphinx.ext.autodoc', + 'sphinxmark' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +author = 'OpenStack-Ansible Contributors' +category = 'Miscellaneous' +copyright = '2014-2016, OpenStack-Ansible Contributors' +description = 'OpenStack-Ansible deploys OpenStack environments using Ansible.' +project = 'OpenStack-Ansible' +role_name = 'nspawn_hosts' +target_name = 'openstack-ansible-' + role_name +title = 'OpenStack-Ansible Documentation: ' + role_name + 'role' + +# The link to the browsable source code (for the left hand menu) +oslosphinx_cgit_link = ( + "https://git.openstack.org/cgit/openstack/{}".format(target_name) +) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version_info = pbr.version.VersionInfo(target_name) +# The full version, including alpha/beta/rc tags. +release = version_info.version_string_with_vcs() +# The short X.Y version. +version = version_info.canonical_version_string() + +# openstackdocstheme options +repository_name = 'openstack/' + target_name +bug_project = project.lower() +bug_tag = '' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# default_role = None + +# 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 + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'openstackdocs' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%Y-%m-%d %H:%M' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' +# html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +# html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +# html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = target_name + '-docs' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # 'preamble': '', + + # Latex figure (float) alignment + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, target_name + '.tex', + title, author, 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, target_name, + title, [author], 1) +] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, target_name, + title, author, project, + description, category), +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False + + +watermark = os.popen("git branch --contains $(git rev-parse HEAD)\ +| awk -F/ '/stable/ {print $2}'").read().strip(' \n\t').capitalize() +if watermark == "": + watermark = "Pre-release" + +# -- Options for sphinxmark ----------------------------------------------- +sphinxmark_enable = True +sphinxmark_div = 'docs-body' +sphinxmark_image = 'text' +sphinxmark_text = watermark +sphinxmark_text_color = (128, 128, 128) +sphinxmark_text_size = 70 diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..713edb7 --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,26 @@ +============================== +OpenStack-Ansible nspawn hosts +============================== + +Ansible role that configures a host for running nspawn containers. + +To clone or view the source code for this repository, visit the role repository +for `nspawn_hosts `_. + +Default variables +~~~~~~~~~~~~~~~~~ + +.. literalinclude:: ../../defaults/main.yml + :language: yaml + :start-after: under the License. + +Dependencies +~~~~~~~~~~~~ + +This role needs pip >= 7.1 installed on the target host. + +Example playbook +~~~~~~~~~~~~~~~~ + +.. literalinclude:: ../../examples/playbook.yml + :language: yaml diff --git a/examples/playbook.yml b/examples/playbook.yml new file mode 100644 index 0000000..92377eb --- /dev/null +++ b/examples/playbook.yml @@ -0,0 +1,5 @@ +- name: Basic nspawn host setup + hosts: "hosts" + user: root + roles: + - { role: "nspawn_hosts" } diff --git a/files/nspawn-attach.sh b/files/nspawn-attach.sh new file mode 100644 index 0000000..aeadcf3 --- /dev/null +++ b/files/nspawn-attach.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Copyright 2018, Rackspace US, Inc. +# +# 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. + +# Enter a container using a friendly universal syntax +CPID=$(machinectl status $1 | awk '/Leader:/ {print $2}') +nsenter --mount=/proc/$CPID/ns/mnt \ + --net=/proc/$CPID/ns/net \ + --pid=/proc/$CPID/ns/pid \ + --uts=/proc/$CPID/ns/uts \ + --ipc=/proc/$CPID/ns/ipc diff --git a/files/systemd-machined.service b/files/systemd-machined.service new file mode 100644 index 0000000..5477de8 --- /dev/null +++ b/files/systemd-machined.service @@ -0,0 +1,23 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Virtual Machine and Container Registration Service +Documentation=man:systemd-machined.service(8) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/machined +Wants=machine.slice +After=machine.slice + +[Service] +ExecStart=/lib/systemd/systemd-machined +BusName=org.freedesktop.machine1 +CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID +WatchdogSec=3min + +# Note that machined cannot be placed in a mount namespace, since it +# needs access to the host's mount namespace in order to implement the +# "machinectl bind" operation. diff --git a/files/var-lib-machines.mount b/files/var-lib-machines.mount new file mode 100644 index 0000000..7eba68f --- /dev/null +++ b/files/var-lib-machines.mount @@ -0,0 +1,16 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Virtual Machine and Container Storage +ConditionPathExists=/var/lib/machines.raw + +[Mount] +What=/var/lib/machines.raw +Where=/var/lib/machines +Type=btrfs +Options=loop diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..0edb630 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,73 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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: Restart networkd + service: + name: systemd-networkd + state: restarted + enabled: true + +- name: Reload systemd units + systemd: + name: it_does_not_matter + daemon_reload: true + +- name: Restart machined + systemd: + name: "systemd-machined.service" + state: "restarted" + enabled: true + +- name: Restart machines mount + systemd: + name: "var-lib-machines.mount" + state: "restarted" + enabled: true + +- name: Disable host dnsmasq service + systemd: + name: "dnsmasq.service" + state: "stopped" + enabled: false + masked: true + daemon_reload: true + +- name: Remove rootfs archive + file: + path: "/tmp/rootfs.tar.xz" + state: "absent" + +- name: Enable macvlan service + systemd: + name: "nspawn-macvlan.service" + state: "started" + enabled: true + daemon_reload: true + +- name: Enable network dnsmasq service + systemd: + name: "dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.service" + state: "started" + enabled: true + daemon_reload: true + when: + - item.value.enable_dhcp | default(false) | bool + with_dict: "{{ container_networks | combine(nspawn_networks) }}" + +- name: Remove policy-rc + file: + path: "/usr/sbin/policy-rc.d" + state: absent + changed_when: false diff --git a/manual-test.rc b/manual-test.rc new file mode 100644 index 0000000..7016c45 --- /dev/null +++ b/manual-test.rc @@ -0,0 +1,33 @@ +export VIRTUAL_ENV=$(pwd) +export ANSIBLE_HOST_KEY_CHECKING=False +export ANSIBLE_SSH_CONTROL_PATH=/tmp/%%h-%%r + +# TODO (odyssey4me) These are only here as they are non-standard folder +# names for Ansible 1.9.x. We are using the standard folder names for +# Ansible v2.x. We can remove this when we move to Ansible 2.x. +export ANSIBLE_ACTION_PLUGINS=${HOME}/.ansible/plugins/action +export ANSIBLE_CALLBACK_PLUGINS=${HOME}/.ansible/plugins/callback +export ANSIBLE_FILTER_PLUGINS=${HOME}/.ansible/plugins/filter +export ANSIBLE_LOOKUP_PLUGINS=${HOME}/.ansible/plugins/lookup + +# This is required as the default is the current path or a path specified +# in ansible.cfg +export ANSIBLE_LIBRARY=${HOME}/.ansible/plugins/library + +# This is required as the default is '/etc/ansible/roles' or a path +# specified in ansible.cfg +export ANSIBLE_ROLES_PATH=${HOME}/.ansible/roles:$(pwd)/.. + +export ANSIBLE_SSH_ARGS="-o ControlMaster=no \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + -o ServerAliveInterval=64 \ + -o ServerAliveCountMax=1024 \ + -o Compression=no \ + -o TCPKeepAlive=yes \ + -o VerifyHostKeyDNS=no \ + -o ForwardX11=no \ + -o ForwardAgent=yes" + +echo "Run manual functional tests by executing the following:" +echo "# ./.tox/functional/bin/ansible-playbook -i tests/inventory tests/test.yml" diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..0096143 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,42 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +galaxy_info: + author: rcbops + description: Deployment of nspawn hosts for use in Rackspace Private Cloud + company: Rackspace + license: Apache2 + min_ansible_version: 2.2.0 + platforms: + - name: Ubuntu + versions: + - xenial + - name: EL + versions: + - 7 + - name: opensuse + versions: + - 42.1 + - 42.2 + - 42.3 + categories: + - cloud + - nspawn + - development + - openstack +dependencies: + - role: apt_package_pinning + when: + - ansible_pkg_mgr == 'apt' diff --git a/meta/openstack-ansible.yml b/meta/openstack-ansible.yml new file mode 100644 index 0000000..e0d5afa --- /dev/null +++ b/meta/openstack-ansible.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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. +# +# (c) 2017, Jean-Philippe Evrard + +maturity_info: + status: development + created_during: queens diff --git a/releasenotes/notes/.placeholder b/releasenotes/notes/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/releasenotes/source/_static/.placeholder b/releasenotes/source/_static/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/releasenotes/source/_templates/.placeholder b/releasenotes/source/_templates/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py new file mode 100644 index 0000000..487a50f --- /dev/null +++ b/releasenotes/source/conf.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 + +# 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 file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'openstackdocstheme', + 'reno.sphinxext', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +author = 'OpenStack-Ansible Contributors' +category = 'Miscellaneous' +copyright = '2014-2016, OpenStack-Ansible Contributors' +description = 'OpenStack-Ansible deploys OpenStack environments using Ansible.' +project = 'OpenStack-Ansible' +role_name = 'nspawn_hosts' +target_name = 'openstack-ansible-' + role_name +title = 'OpenStack-Ansible Release Notes: ' + role_name + 'role' + +# The link to the browsable source code (for the left hand menu) +oslosphinx_cgit_link = ( + "https://git.openstack.org/cgit/openstack/{}".format(target_name) +) + +# Release notes do not need a version number in the title, they +# cover multiple releases. +# The full version, including alpha/beta/rc tags. +release = '' +# The short X.Y version. +version = '' + +# openstackdocstheme options +repository_name = 'openstack/' + target_name +bug_project = project.lower() +bug_tag = '' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# default_role = None + +# 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 + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'openstackdocs' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%Y-%m-%d %H:%M' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = target_name + '-docs' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # 'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, target_name + '.tex', + title, author, 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, target_name, + title, [author], 1) +] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, target_name, + title, author, project, + description, category), +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False + +# -- Options for Internationalization output ------------------------------ +locale_dirs = ['locale/'] diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst new file mode 100644 index 0000000..71f7357 --- /dev/null +++ b/releasenotes/source/index.rst @@ -0,0 +1,8 @@ +================================ + OpenStack-Ansible Release Notes +================================ + +.. toctree:: + :maxdepth: 1 + + unreleased diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst new file mode 100644 index 0000000..cd22aab --- /dev/null +++ b/releasenotes/source/unreleased.rst @@ -0,0 +1,5 @@ +============================== + Current Series Release Notes +============================== + +.. release-notes:: diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..4b72d3f --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# Copyright 2015, Rackspace US, Inc. +# +# 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 file is maintained in the openstack-ansible-tests repository. +# https://git.openstack.org/cgit/openstack/openstack-ansible-tests/tree/run_tests.sh +# If you need to modify this file, update the one in the openstack-ansible-tests +# repository and then update this file as well. The purpose of this file is to +# prepare the host and then execute all the tox tests. +# + +## Shell Opts ---------------------------------------------------------------- +set -xeu + +## Vars ---------------------------------------------------------------------- + +export WORKING_DIR=${WORKING_DIR:-$(pwd)} + +## Main ---------------------------------------------------------------------- + +source /etc/os-release || source /usr/lib/os-release + +install_pkg_deps() { + pkg_deps="git" + + # Prefer dnf over yum for CentOS. + which dnf &>/dev/null && RHT_PKG_MGR='dnf' || RHT_PKG_MGR='yum' + + case ${ID,,} in + *suse*) pkg_mgr_cmd="zypper -n in" ;; + centos|rhel|fedora) pkg_mgr_cmd="${RHT_PKG_MGR} install -y" ;; + ubuntu|debian) pkg_mgr_cmd="apt-get install -y" ;; + *) echo "unsupported distribution: ${ID,,}"; exit 1 ;; + esac + + eval sudo $pkg_mgr_cmd $pkg_deps +} + +# Install the host distro package dependencies +install_pkg_deps + +# Clone the tests repo for access to the common test script +source tests/tests-repo-clone.sh + +# Execute the common test script +source tests/common/run_tests_common.sh + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..d9b62ba --- /dev/null +++ b/setup.cfg @@ -0,0 +1,24 @@ +[metadata] +name = openstack-ansible-nspawn_hosts +summary = Role for setting up nspawn Hosts +description-file = + README.rst +author = OpenStack +author-email = openstack-dev@lists.openstack.org +home-page = https://docs.openstack.org/openstack-ansible-nspawn_hosts/latest/ +classifier = + Intended Audience :: Developers + Intended Audience :: System Administrators + License :: OSI Approved :: Apache Software License + Operating System :: POSIX :: Linux + +[build_sphinx] +all_files = 1 +build-dir = doc/build +source-dir = doc/source + +[pbr] +warnerrors = True + +[wheel] +universal = 1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..566d844 --- /dev/null +++ b/setup.py @@ -0,0 +1,29 @@ +# Copyright (c) 2013 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 FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT +import setuptools + +# In python < 2.7.4, a lazy loading of package `pbr` will break +# setuptools if some other modules registered functions in `atexit`. +# solution from: http://bugs.python.org/issue15881#msg170215 +try: + import multiprocessing # noqa +except ImportError: + pass + +setuptools.setup( + setup_requires=['pbr>=2.0.0'], + pbr=True) diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..3666836 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,95 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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(cloudnull): At this time the nspawn implementation does not support suse. +# When we can use networkd on suse this should be revised. +- name: Check if os is suse + fail: + msg: >- + At this time the nspawn implementation does not support suse. + when: + - ansible_pkg_mgr == 'zypper' + +- name: Pull systemd version + command: "systemctl --version" + changed_when: false + register: systemd_version + tags: + - skip_ansible_lint + +- name: Set facts + set_fact: + nspawn_systemd_version: "{{ systemd_version.stdout_lines[0].split()[-1] }}" + +- name: Gather variables for each operating system + include_vars: "{{ item }}" + with_first_found: + - "{{ hostvars[physical_host]['ansible_distribution'] | lower }}-{{ hostvars[physical_host]['ansible_distribution_version'] | lower }}.yml" + - "{{ hostvars[physical_host]['ansible_distribution'] | lower }}-{{ hostvars[physical_host]['ansible_distribution_major_version'] | lower }}.yml" + - "{{ hostvars[physical_host]['ansible_os_family'] | lower }}-{{ hostvars[physical_host]['ansible_distribution_major_version'] | lower }}.yml" + - "{{ hostvars[physical_host]['ansible_distribution'] | lower }}.yml" + - "{{ hostvars[physical_host]['ansible_os_family'] | lower }}.yml" + tags: + - always + +- name: Prevent service from starting on install + copy: + content: | + #!/bin/bash + exit 101 + dest: "/usr/sbin/policy-rc.d" + mode: "0755" + when: + - ansible_pkg_mgr == 'apt' + notify: + - Remove policy-rc + +- name: Install distro packages + package: + pkg: "{{ nspawn_hosts_distro_packages }}" + state: "{{ nspawn_hosts_package_state }}" + register: install_packages + until: install_packages|success + retries: 5 + delay: 2 + notify: + - Disable host dnsmasq service + - Restart networkd + +- name: Move nspawn-attach into place + copy: + src: nspawn-attach.sh + dest: /usr/local/bin/nspawn-attach + mode: '0755' + +- name: Create networkd and nspawn directories + file: + path: "{{ item }}" + state: directory + with_items: + - /etc/systemd/nspawn + - /etc/systemd/network + +- include: nspawn_cache_prestage.yml + tags: + - always + +- include: nspawn_volume.yml + +- include: nspawn_networking.yml + +- include: nspawn_cache.yml + +- include: nspawn_networking.yml diff --git a/tasks/nspawn_cache.yml b/tasks/nspawn_cache.yml new file mode 100644 index 0000000..dec9a80 --- /dev/null +++ b/tasks/nspawn_cache.yml @@ -0,0 +1,93 @@ +--- +# Copyright 2018, Rackspace US, Inc. +# +# 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 old image cache + command: "btrfs subvolume delete /var/lib/machines/{{ nspawn_container_base_name }}" + register: cache_refresh_del + changed_when: cache_refresh_del.rc == 0 + failed_when: cache_refresh_del.rc not in [0, 1] + when: + - nspawn_image_cache_refresh | bool + +- name: Add image cache + command: "btrfs subvolume create /var/lib/machines/{{ nspawn_container_base_name }}" + register: cache_refresh_add + changed_when: cache_refresh_add.rc == 0 + failed_when: cache_refresh_add.rc not in [0, 1] + when: + - nspawn_image_cache_refresh | bool + +- name: Ensure image has been pre-staged + async_status: + jid: "{{ prestage_image.ansible_job_id }}" + register: job_result + until: job_result.finished + retries: 60 + when: + - nspawn_image_cache_refresh | bool + +- name: Place container rootfs + unarchive: + src: "/tmp/rootfs.tar.xz" + dest: "/var/lib/machines/{{ nspawn_container_base_name }}" + remote_src: True + notify: + - Remove rootfs archive + when: + - nspawn_image_cache_refresh | bool + +- name: Cached image preparation script + template: + src: "prep-scripts/nspawn_{{ nspawn_cache_map.distro }}_prep.sh.j2" + dest: "/var/lib/machines/{{ nspawn_container_base_name }}/usr/local/bin/cache-prep-commands.sh" + mode: "0755" + when: + - nspawn_image_cache_refresh | bool + +# This task runs several commands against the cached image to speed up the +# nspawn_container_create playbook. +- name: Prepare cached image setup commands + shell: "chroot /var/lib/machines/{{ nspawn_container_base_name }} /usr/local/bin/cache-prep-commands.sh > /var/log/nspawn-cache-prep-commands.log 2>&1" + changed_when: false + when: + - nspawn_image_cache_refresh | bool + +- name: Sync files from the host into the container cache + shell: | + if [[ -e "{{ item }}" ]]; then + rsync -av "{{ item }}" "/var/lib/machines/{{ nspawn_container_base_name }}{{ item }}" + else + exit 3 + fi + changed_when: _rsync_container_cache.rc == 0 + failed_when: _rsync_container_cache.rc not in [0, 3] + register: _rsync_container_cache + args: + executable: "/bin/bash" + with_items: "{{ (nspawn_copy_from_host | union(nspawn_container_cache_files_from_host)) | list }}" + when: + - nspawn_image_cache_refresh | bool + +- name: Create networkd directory + file: + path: "/var/lib/machines/{{ nspawn_container_base_name }}/etc/systemd/network" + state: directory + +- name: Create static MACs in the container + template: + src: "templates/systemd-nspawn-default.link.j2" + dest: "/var/lib/machines/{{ nspawn_container_base_name }}/etc/systemd/network/99-default.link" + notify: + - Restart networkd diff --git a/tasks/nspawn_cache_prestage.yml b/tasks/nspawn_cache_prestage.yml new file mode 100644 index 0000000..e57597f --- /dev/null +++ b/tasks/nspawn_cache_prestage.yml @@ -0,0 +1,98 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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 cached image status + command: "machinectl image-status {{ nspawn_container_base_name }}" + register: cache_check + changed_when: false + failed_when: false + +- name: Set cache refresh fact + set_fact: + nspawn_image_cache_refresh: true + when: + - cache_check.rc != 0 + +- name: Set nspawn cache path fact + set_fact: + cache_index_item: "{{ nspawn_cache_map.distro }};{{ nspawn_cache_map.release }};{{ nspawn_cache_map.arch }};{{ nspawn_cache_default_variant }};" + cache_time: "{{ ansible_date_time.epoch }}" + when: + - nspawn_image_cache_refresh | bool + +- name: Fetch nspawn image-index + shell: > + aria2c + --max-connection-per-server=4 + --allow-overwrite=true + --dir=/tmp + --out=index-system + --check-certificate={{ (nspawn_hosts_validate_certs | bool) | lower }} + {% for server in nspawn_image_cache_server_mirrors %}{{ server }}/meta/1.0/index-system {% endfor %} + args: + warn: no + when: + - nspawn_image_cache_refresh | bool + tags: + - skip_ansible_lint + +- name: Retrieve the index + slurp: + src: "/tmp/index-system" + changed_when: false + register: image_index + when: + - nspawn_image_cache_refresh | bool + +# Example index lines: +# ubuntu;xenial;amd64;default;20180123_08:05;/images/ubuntu/xenial/amd64/default/20180123_08:05/ +# As there may be multiple images, and they use a timestamp, we can sort +# the resulting list in reverse order and use the first item in the list +# as it will be the latest available. +- name: Set image index fact + set_fact: + nspawn_images: > + {%- set images = [] %} + {%- for image in (image_index.content | b64decode).splitlines() %} + {%- if image | match("^" + cache_index_item) %} + {%- set _ = images.append(image) %} + {%- endif %} + {%- endfor %} + {{- images | sort(reverse=True) -}} + when: + - nspawn_image_cache_refresh | bool + +# We only want to download a single image, rather than downloading +# each of them in turn and they overwrite each other as they all +# download to the same file name and path. +- name: Pre-stage the nspawn image on the system + shell: > + aria2c + --max-connection-per-server=4 + --allow-overwrite=true + --dir=/tmp + --out=rootfs.tar.xz + --check-certificate={{ (nspawn_hosts_validate_certs | bool) | lower }} + {% for server in nspawn_image_cache_server_mirrors %}{{ server }}{{ nspawn_images[0].split(';')[-1] }}rootfs.tar.xz {% endfor %} + > /var/log/aria2c-image-prestage.log 2>&1 + args: + warn: no + register: prestage_image + async: 300 + poll: 0 + when: + - nspawn_image_cache_refresh | bool + tags: + - skip_ansible_lint diff --git a/tasks/nspawn_networking.yml b/tasks/nspawn_networking.yml new file mode 100644 index 0000000..c9bd770 --- /dev/null +++ b/tasks/nspawn_networking.yml @@ -0,0 +1,94 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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. + +- block: + - name: Create machined proxy override unit directories + file: + path: "/etc/systemd/system/{{ item }}" + owner: root + group: root + mode: '0755' + state: directory + with_items: + - systemd-machined.service.d + - systemd-importd.service.d + + - name: Drop the machined proxy override units + template: + src: systemd-proxy-unit.conf.j2 + dest: /etc/systemd/system/{{ item }}/proxy.conf + owner: root + group: root + mode: '0644' + with_items: + - systemd-machined.service.d + - systemd-importd.service.d + when: + - (deployment_environment_variables | default({})).keys() | length > 0 + +- name: Create static MACs on the host + template: + src: "templates/systemd-nspawn-default.link.j2" + dest: /etc/systemd/network/99-default.link + notify: + - Restart networkd + +- name: Create MACVLAN net device(s) + template: + src: "templates/systemd-nspawn-mv.netdev.j2" + dest: "/etc/systemd/network/{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.netdev" + with_dict: "{{ container_networks | combine(nspawn_networks) }}" + notify: + - Restart networkd + +- name: Create MACVLAN network(s) + template: + src: "templates/systemd-nspawn-mv.network.j2" + dest: "/etc/systemd/network/{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.network" + with_dict: "{{ container_networks | combine(nspawn_networks) }}" + notify: + - Restart networkd + +- name: Create macvlan service + template: + src: "nspawn-macvlan-systemd-init.j2" + dest: "/etc/systemd/system/nspawn-macvlan.service" + notify: + - Enable macvlan service + +- name: Create systemd-nspawn@ service + template: + src: "systemd-nspawn@.service.j2" + dest: "/lib/systemd/system/systemd-nspawn@.service" + +- name: Create dnsmasq config(s) + template: + src: "dnsmasq-config.conf.j2" + dest: "/etc/dnsmasq.d/dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.conf" + with_dict: "{{ container_networks | combine(nspawn_networks) }}" + when: + - item.value.enable_dhcp | default(false) | bool + notify: + - Enable network dnsmasq service + +- name: Create dnsmasq systemd config(s) + template: + src: "nspawn-dnsmasq-systemd-init.j2" + dest: "/etc/systemd/system/dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.service" + with_dict: "{{ container_networks | combine(nspawn_networks) }}" + when: + - item.value.enable_dhcp | default(false) | bool + notify: + - Enable network dnsmasq service diff --git a/tasks/nspawn_volume.yml b/tasks/nspawn_volume.yml new file mode 100644 index 0000000..4ca916d --- /dev/null +++ b/tasks/nspawn_volume.yml @@ -0,0 +1,96 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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 machinectl mount point + command: mountpoint /var/lib/machines + failed_when: false + changed_when: false + register: machinectl_mount + +- name: Create systemd sparse file + block: + - name: Set volume size + shell: machinectl set-limit {{ nspawn_host_machine_volume_size }} + changed_when: false + register: machines_create + args: + executable: /bin/bash + rescue: + - name: Create volume file (fallback) + shell: | + truncate -s '>{{ nspawn_host_machine_volume_size }}' /var/lib/machines.raw + register: machines_create + args: + executable: /bin/bash + +- name: Disable the machinectl quota system + block: + - name: Disable the machinectl quota system + command: "btrfs quota {{ nspawn_host_machine_quota_disabled | bool | ternary('disable', 'enabled') }} /var/lib/machines" + changed_when: false + register: machines_create + args: + executable: /bin/bash + rescue: + - name: Notice quota system was not disabled + debug: + msg: >- + The machinectl quota system could not be disabled. This typically + means it is already off or not available on the system. + +- name: Systemd machinectl mount + block: + - name: Format the machines sparse file + filesystem: + fstype: btrfs + dev: /var/lib/machines.raw + + - name: Create machines mount point + file: + path: "/var/lib/machines" + state: "directory" + recurse: true + + - name: Move machines mount into place + copy: + src: var-lib-machines.mount + dest: /etc/systemd/system/var-lib-machines.mount + register: mount_unit + notify: + - Reload systemd units + - Restart machines mount + + - name: Move machined service into place + copy: + src: systemd-machined.service + dest: /etc/systemd/system/systemd-machined.service + register: machined_unit + notify: + - Reload systemd units + - Restart machined + when: + - machinectl_mount.rc != 0 + +- meta: flush_handlers + +# NOTE(cloudnull): Because the machines mount may be a manually created sparse +# file we run an online resize to ensure the machines mount is +# the size we expect. +- name: Ensure the machines fs is sized correctly + command: "btrfs filesystem resize max /var/lib/machines" + changed_when: false + failed_when: false + when: + - machines_create | changed diff --git a/templates/dnsmasq-config.conf.j2 b/templates/dnsmasq-config.conf.j2 new file mode 100644 index 0000000..3242494 --- /dev/null +++ b/templates/dnsmasq-config.conf.j2 @@ -0,0 +1,16 @@ +# {{ ansible_managed }} + +user=systemd-network +listen-address={{ item.value.address }} +dhcp-range={{ item.value.dhcp_range }} +dhcp-lease-max=128 +except-interface=lo +interface={{ 'mv-' + item.value.bridge.split('br-')[-1] }} +dhcp-leasefile=/var/lib/misc/nspawn-{{ item.value.bridge }}-dnsmasq.leases +strict-order +bind-interfaces +no-hosts +no-negcache +domain-needed +bogus-priv +no-poll diff --git a/templates/nspawn-dnsmasq-systemd-init.j2 b/templates/nspawn-dnsmasq-systemd-init.j2 new file mode 100644 index 0000000..a9bc639 --- /dev/null +++ b/templates/nspawn-dnsmasq-systemd-init.j2 @@ -0,0 +1,37 @@ +# {{ ansible_managed }} + +[Unit] +Description=nspawn dnsmasq service +After=syslog.target +After=network.target +After=nspawn-macvlan.service + +[Service] +Type=simple +User=root + +{% set addr_cidr = (item.value.address | string + '/' + item.value.netmask | string) | ipaddr('prefix') %} +ExecStartPre=-/sbin/iptables -t nat -A POSTROUTING -s {{ item.value.address }}/{{ addr_cidr }} ! -d {{ item.value.address }}/{{ addr_cidr }} -j MASQUERADE +ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq.d/dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.conf + +ExecStop=-/usr/bin/killall -u systemd-network --regexp ^dnsmasq +ExecStopPost=-/sbin/iptables -t nat -D POSTROUTING -s {{ item.value.address }}/{{ addr_cidr }} ! -d {{ item.value.address }}/{{ addr_cidr }} -j MASQUERADE + +PIDFile=/run/run/nspawn-{{ item.value.bridge }}-dnsmasq.pid + +# Give a reasonable amount of time for the server to start up/shut down +TimeoutSec=120 +Restart=on-failure +RestartSec=2 + +# This creates a specific slice which all services will operate from +# The accounting options give us the ability to see resource usage through +# the `systemd-cgtop` command. +Slice=nspawn-networking.slice +CPUAccounting=true +BlockIOAccounting=true +MemoryAccounting=false +TasksAccounting=true + +[Install] +WantedBy=multi-user.target diff --git a/templates/nspawn-macvlan-systemd-init.j2 b/templates/nspawn-macvlan-systemd-init.j2 new file mode 100644 index 0000000..d6a99ae --- /dev/null +++ b/templates/nspawn-macvlan-systemd-init.j2 @@ -0,0 +1,33 @@ +# {{ ansible_managed }} + +[Unit] +Description=nspawn macvlan service +After=syslog.target +After=network.target + +[Service] +Type=oneshot +User=root +RemainAfterExit=yes + +{% set seen_start_interfaces = [] %} +{% for key, value in (container_networks | combine(nspawn_networks)).items() %} +{% set interface = value.bridge.split('br-')[-1] %} +{% set mv_interface = 'mv-' + interface %} +{% if value.bridge not in seen_start_interfaces %} +{% set interface_from_ansible = 'ansible_' + value.bridge | replace('-', '_') %} +{% if hostvars[inventory_hostname][interface_from_ansible]['type'] == 'bridge' %} +ExecStart=-/sbin/ip link add dev "veth-{{ interface }}1" type veth peer name "veth-{{ interface }}2" +ExecStart=-/sbin/ip link set dev "veth-{{ interface }}1" up +ExecStart=-/sbin/ip link set dev "veth-{{ interface }}2" up +ExecStart=-/sbin/ip link set "veth-{{ interface }}1" master "{{ value.bridge }}" +ExecStart=-/sbin/ip link add "{{ mv_interface }}" link "veth-{{ interface }}2" type macvlan mode {{ nspawn_macvlan_mode }} +{% else %} +ExecStart=-/sbin/ip link add "{{ mv_interface }}" link "{{ value.bridge }}" type macvlan mode {{ nspawn_macvlan_mode }} +{% endif %} +{% set _ = seen_start_interfaces.append(value.bridge) %} +{% endif %} +{% endfor %} + +[Install] +WantedBy=multi-user.target diff --git a/templates/prep-scripts/nspawn_centos_prep.sh.j2 b/templates/prep-scripts/nspawn_centos_prep.sh.j2 new file mode 100644 index 0000000..9c2ca66 --- /dev/null +++ b/templates/prep-scripts/nspawn_centos_prep.sh.j2 @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +# Copyright 2018, Rackspace US, Inc. +# +# 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. + +# {{ ansible_managed }} + +set -e + +{{ nspawn_cache_prep_pre_commands }} + +mkdir -p /etc/ansible/facts.d +mkdir -p /var/backup + +if [ -a /etc/resolv.conf ]; then + mv /etc/resolv.conf /etc/resolv.conf.org +fi + +{% for resolver in nspawn_cache_prep_dns %} +echo "nameserver {{ resolver }}" >> /etc/resolv.conf +{% endfor %} + +rpm --import /etc/pki/rpm-gpg/* +# Prefer dnf over yum for CentOS. +which dnf &>/dev/null && RHT_PKG_MGR='dnf' || RHT_PKG_MGR='yum' +# Create yum/dnf transaction file and run it all at once +echo "update" > /tmp/package-transaction.txt +echo "install {{ nspawn_container_distro_packages | join(' ') }}" >> /tmp/package-transaction.txt +echo "run" >> /tmp/package-transaction.txt +$RHT_PKG_MGR -y shell /tmp/package-transaction.txt +yum-complete-transaction --cleanup-only +rm -f /tmp/package-transaction.txt + +rm -f /usr/bin/python || true + +ln -s /usr/bin/python2.7 /usr/bin/python + +chage -I -1 -d -1 -m 0 -M 99999 -E -1 root + +if [ -a /etc/resolv.conf.org ]; then + mv /etc/resolv.conf.org /etc/resolv.conf +else + rm -f /etc/resolv.conf +fi + +systemctl enable systemd-networkd.service + +{{ nspawn_cache_prep_post_commands }} diff --git a/templates/prep-scripts/nspawn_ubuntu_prep.sh.j2 b/templates/prep-scripts/nspawn_ubuntu_prep.sh.j2 new file mode 100644 index 0000000..dddf8c9 --- /dev/null +++ b/templates/prep-scripts/nspawn_ubuntu_prep.sh.j2 @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright 2018, Rackspace US, Inc. +# +# 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. + +# {{ ansible_managed }} + +set -e + +{{ nspawn_cache_prep_pre_commands }} + +mkdir -p /etc/ansible/facts.d +mkdir -p /var/backup + +if [ -a "/etc/resolv.conf" ]; then + mv /etc/resolv.conf /etc/resolv.conf.org +fi + +{% for resolver in nspawn_cache_prep_dns %} +echo "nameserver {{ resolver }}" >> /etc/resolv.conf +{% endfor %} + +# Update base distribution +export DEBIAN_FRONTEND=noninteractive +apt-get remove -y --purge snap* nspawn* lxd* || true +apt-get update +apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes {{ nspawn_container_distro_packages | join(' ') }} +apt-get upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes + +rm -f /usr/bin/python || true +ln -s /usr/bin/python2.7 /usr/bin/python + +mkdir -p /root/.ssh +chmod 700 /root/.ssh + +userdel --force --remove ubuntu || true +chage -I -1 -d -1 -m 0 -M 99999 -E -1 root + +if [ -a /etc/resolv.conf.org ]; then + mv /etc/resolv.conf.org /etc/resolv.conf +else + rm -f /etc/resolv.conf +fi + +systemctl enable systemd-networkd.service + +{{ nspawn_cache_prep_post_commands }} diff --git a/templates/systemd-nspawn-default.link.j2 b/templates/systemd-nspawn-default.link.j2 new file mode 100644 index 0000000..99e55d9 --- /dev/null +++ b/templates/systemd-nspawn-default.link.j2 @@ -0,0 +1,4 @@ +# {{ ansible_managed }} + +[Link] +MACAddressPolicy=persistent diff --git a/templates/systemd-nspawn-mv.netdev.j2 b/templates/systemd-nspawn-mv.netdev.j2 new file mode 100644 index 0000000..c268f11 --- /dev/null +++ b/templates/systemd-nspawn-mv.netdev.j2 @@ -0,0 +1,8 @@ +# {{ ansible_managed }} + +[NetDev] +Name={{ 'mv-' + item.value.bridge.split('br-')[-1] }} +Kind=macvlan + +[MACVLAN] +Mode=bridge diff --git a/templates/systemd-nspawn-mv.network.j2 b/templates/systemd-nspawn-mv.network.j2 new file mode 100644 index 0000000..288903d --- /dev/null +++ b/templates/systemd-nspawn-mv.network.j2 @@ -0,0 +1,23 @@ +# {{ ansible_managed }} + +[Match] +Name={{ 'mv-' + item.value.bridge.split('br-')[-1] }} + +[Network] +DHCP=no +IPForward=yes +IPMasquerade=yes +{% if item.value.gateway is defined %} +Gateway={{ item.value.gateway }} +{% endif %} + +{% if item.value.enable_dhcp | default(false) | bool %} +{% if item.value.address is defined %} +[Address] +{% set addr_cidr = (item.value.address | string + '/' + item.value.netmask | string) | ipaddr('prefix') %} +Address={{ item.value.address }}/{{ addr_cidr }} +{% endif %} +{% endif %} + +[Link] +ARP=yes diff --git a/templates/systemd-nspawn@.service.j2 b/templates/systemd-nspawn@.service.j2 new file mode 100644 index 0000000..ebc479d --- /dev/null +++ b/templates/systemd-nspawn@.service.j2 @@ -0,0 +1,49 @@ +# {{ ansible_managed }} + +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Container %I +Documentation=man:systemd-nspawn(1) +PartOf=machines.target +Before=machines.target +After=network.target + +[Service] +{% if nspawn_systemd_version | int > 219 %} +ExecStart=/usr/bin/systemd-nspawn --keep-unit --boot --link-journal=try-guest --settings=override --machine=%I +{% else %} +ExecStart=/usr/bin/systemd-nspawn --keep-unit --boot --link-journal=try-guest --machine=%I +{% endif %} +KillMode=mixed +Type=notify +RestartForceExitStatus=133 +SuccessExitStatus=133 +Slice=machine.slice +Delegate=yes +TasksMax=8192 + +# Enforce a strict device policy, similar to the one nspawn configures +# when it allocates its own scope unit. Make sure to keep these +# policies in sync if you change them! +DevicePolicy=strict +DeviceAllow=/dev/null rwm +DeviceAllow=/dev/zero rwm +DeviceAllow=/dev/full rwm +DeviceAllow=/dev/random rwm +DeviceAllow=/dev/urandom rwm +DeviceAllow=/dev/tty rwm +DeviceAllow=/dev/net/tun rwm +DeviceAllow=/dev/pts/ptmx rw +DeviceAllow=char-pts rw + +# nspawn itself needs access to /dev/loop-control and /dev/loop, to +# implement the --image= option. Add these here, too. +DeviceAllow=/dev/loop-control rw +DeviceAllow=block-loop rw +DeviceAllow=block-blkext rw diff --git a/templates/systemd-proxy-unit.conf.j2 b/templates/systemd-proxy-unit.conf.j2 new file mode 100644 index 0000000..cd243e4 --- /dev/null +++ b/templates/systemd-proxy-unit.conf.j2 @@ -0,0 +1,6 @@ +# {{ ansible_managed }} + +[Service] +{% for key, value in (deployment_environment_variables | default({})).items() %} +Environment={{ key }}={{ value }} +{% endfor %} diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..09d54c4 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,16 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. +bashate>=0.5.1 # Apache-2.0 +flake8<2.6.0,>=2.5.4 # MIT +pyasn1!=0.2.3,>=0.1.8 # BSD +pyOpenSSL>=16.2.0 # Apache-2.0 +requests>=2.14.2 # Apache-2.0 +ndg-httpsclient>=0.4.2;python_version<'3.0' # BSD + +# this is required for the docs build jobs +sphinx!=1.6.6,>=1.6.2 # BSD +openstackdocstheme>=1.18.1 # Apache-2.0 +doc8>=0.6.0 # Apache-2.0 +reno>=2.5.0 # Apache-2.0 +sphinxmark>=0.1.14 # Apache-2.0 diff --git a/tests/ansible-role-requirements.yml b/tests/ansible-role-requirements.yml new file mode 100644 index 0000000..3575966 --- /dev/null +++ b/tests/ansible-role-requirements.yml @@ -0,0 +1,8 @@ +- name: apt_package_pinning + src: https://git.openstack.org/openstack/openstack-ansible-apt_package_pinning + scm: git + version: master +- name: pip_install + src: https://git.openstack.org/openstack/openstack-ansible-pip_install + scm: git + version: master diff --git a/tests/files/container-file-copy-test.txt b/tests/files/container-file-copy-test.txt new file mode 100644 index 0000000..0a68a48 --- /dev/null +++ b/tests/files/container-file-copy-test.txt @@ -0,0 +1 @@ +This is a test file to verify that the container cache file copy worked. \ No newline at end of file diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..df8b5f6 --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +[all] +localhost ansible_connection=local diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..7fb6091 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,135 @@ +--- +# Copyright 2015, Rackspace US, Inc. +# +# 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: Playbook for role testing + hosts: localhost + connection: local + become: true + pre_tasks: + - name: Show host facts + debug: + var: hostvars + + - name: First ensure apt cache is always refreshed + apt: + update_cache: yes + when: + - ansible_pkg_mgr == 'apt' + + - name: Ensure root ssh key + user: + name: "{{ ansible_env.USER | default('root') }}" + generate_ssh_key: "yes" + ssh_key_bits: 2048 + ssh_key_file: ".ssh/id_rsa" + + - name: Get root ssh key + slurp: + src: '~/.ssh/id_rsa.pub' + register: _root_ssh_key + + - name: Prepare container ssh key fact + set_fact: + nspawn_container_ssh_key: "{{ _root_ssh_key['content'] | b64decode }}" + + # This is a very dirty hack due to images.linuxcontainers.org + # constantly failing to resolve in openstack-infra. + - name: Implement hard-coded hosts entries for consistently failing name + lineinfile: + path: "/etc/hosts" + line: "{{ item }}" + state: present + with_items: + - "91.189.91.21 images.linuxcontainers.org us.images.linuxcontainers.org" + - "91.189.88.37 images.linuxcontainers.org uk.images.linuxcontainers.org" + + # This is a temporary hack to override the nspawn image source to + # the reverse proxy if the test is run in OpenStack-Infra. + - name: Check if this is an OpenStack-CI nodepool instance + stat: + path: /etc/nodepool/provider + register: nodepool + + - name: Discover the nspawn_image_cache_server value when in nodepool + shell: | + source /etc/ci/mirror_info.sh + echo "${NODEPOOL_MIRROR_HOST}:8080/images.linuxcontainers" + args: + executable: /bin/bash + register: nspawn_reverse_proxy + when: + - nodepool.stat.exists | bool + tags: + - skip_ansible_lint + + - name: Set a fact to override nspawn_image_cache_server value when in nodepool + set_fact: + nspawn_image_cache_server_mirrors: ["http://{{ nspawn_reverse_proxy.stdout.strip('/') }}"] + when: + - nodepool.stat.exists | bool + + roles: + - role: "nspawn_hosts" + nspawn_net_address: 10.100.100.1 + nspawn_net_bridge: nspawnbr0 + nspawn_kernel_options: + - { key: 'fs.inotify.max_user_instances', value: 1024 } + nspawn_container_cache_files: + - src: files/container-file-copy-test.txt + dest: /tmp/file-copied-from-deployment-host.txt + + post_tasks: + - name: Get sysctl content + set_fact: + sysctl_conf: "{{ lookup('file', '/etc/sysctl.conf') }}" + + - name: Check for nspawn bridge + stat: + path: /sys/class/net/nspawnbr0/bridge/bridge_id + register: nspawn_bridge_file + + - name: Check dnsmasq is running + shell: ps auxfww | grep -w 'dnsmasq -u nspawn-dnsmasq' + changed_when: false + + - name: DEBIAN - Get deployed interface file contents, without Ansible managed line + set_fact: + interface_file: "{{ lookup('pipe', 'cat /etc/network/interfaces.d/nspawn-net-bridge.cfg | tail -n +3') }}" + when: ansible_os_family | lower == "debian" + + - name: RHEL - Get deployed interface file contents, without Ansible managed line + set_fact: + interface_file: "{{ lookup('pipe', 'cat /etc/sysconfig/network-scripts/ifcfg-nspawnbr0 | tail -n +3') }}" + when: ansible_os_family | lower == "redhat" + + - name: SUSE - Get deployed interface file contents, without Ansible managed line + set_fact: + interface_file: "{{ lookup('pipe', 'cat /etc/sysconfig/network/ifcfg-nspawnbr0 | tail -n +3') }}" + when: ansible_os_family | lower == "suse" + + - name: Get bridge interface facts + setup: + filter: ansible_nspawnbr0 + register: nspawnbr0_facts + + - name: Check role functions + assert: + that: + - interface_file | search('.*nspawnbr0.*') + - interface_file | search('.*10.100.100.1.*') + - interface_file | search('.*255.255.255.0.*') + - sysctl_conf | search('fs.inotify.max_user_instances.*') + - "nspawn_bridge_file.stat.exists" + - "nspawnbr0_facts.ansible_facts.ansible_nspawnbr0.ipv4.address | match('10.100.100.1')" diff --git a/tests/tests-repo-clone.sh b/tests/tests-repo-clone.sh new file mode 100755 index 0000000..3e4ffd6 --- /dev/null +++ b/tests/tests-repo-clone.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# Copyright 2017, Rackspace US, Inc. +# +# 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. + +# PURPOSE: +# This script clones the openstack-ansible-tests repository to the +# tests/common folder in order to be able to re-use test components +# for role testing. + +# WARNING: +# This file is maintained in the openstack-ansible-tests repository: +# https://git.openstack.org/cgit/openstack/openstack-ansible-tests +# If you need to change this script, then propose the change there. +# Once it merges, the change will be replicated to the other repositories. + +## Shell Opts ---------------------------------------------------------------- + +set -e + +## Vars ---------------------------------------------------------------------- + +export TESTING_HOME=${TESTING_HOME:-$HOME} +export WORKING_DIR=${WORKING_DIR:-$(pwd)} +export CLONE_UPGRADE_TESTS=${CLONE_UPGRADE_TESTS:-no} +export ZUUL_TESTS_CLONE_LOCATION="/home/zuul/src/git.openstack.org/openstack/openstack-ansible-tests" + +## Functions ----------------------------------------------------------------- + +function create_tests_clonemap { + +# Prepare the clonemap for zuul-cloner to use +cat > ${TESTING_HOME}/tests-clonemap.yaml << EOF +clonemap: + - name: openstack/openstack-ansible-tests + dest: ${WORKING_DIR}/tests/common +EOF + +} + +## Main ---------------------------------------------------------------------- + +# If zuul-cloner is present, use it so that we +# also include any dependent patches from the +# tests repo noted in the commit message. +# We only want to use zuul-cloner if we detect +# zuul v2 running, so we check for the presence +# of the ZUUL_REF environment variable. +# ref: http://git.openstack.org/cgit/openstack-infra/zuul/tree/zuul/ansible/filter/zuul_filters.py?h=feature/zuulv3#n17 +if [[ -x /usr/zuul-env/bin/zuul-cloner ]] && [[ "${ZUUL_REF:-none}" != "none" ]]; then + + # Prepare the clonemap for zuul-cloner to use + create_tests_clonemap + + # Execute the clone + /usr/zuul-env/bin/zuul-cloner \ + --cache-dir /opt/git \ + --map ${TESTING_HOME}/tests-clonemap.yaml \ + git://git.openstack.org \ + openstack/openstack-ansible-tests + + # Clean up the clonemap. + rm -f ${TESTING_HOME}/tests-clonemap.yaml + +# Alternatively, use a simple git-clone. We do +# not re-clone if the directory exists already +# to prevent overwriting any local changes which +# may have been made. +elif [[ ! -d tests/common ]]; then + + # The tests repo doesn't need a clone, we can just + # symlink it. As zuul v3 clones into a folder called + # 'workspace' we have to use one of its environment + # variables to determine the project name. + if [[ "${ZUUL_SHORT_PROJECT_NAME:-none}" == "openstack-ansible-tests" ]] ||\ + [[ "$(basename ${WORKING_DIR})" == "openstack-ansible-tests" ]]; then + ln -s ${WORKING_DIR} ${WORKING_DIR}/tests/common + + # In zuul v3 any dependent repository is placed into + # /home/zuul/src/git.openstack.org, so we check to see + # if there is a tests checkout there already. If so, we + # symlink that and use it. + elif [[ -d "${ZUUL_TESTS_CLONE_LOCATION}" ]]; then + ln -s "${ZUUL_TESTS_CLONE_LOCATION}" ${WORKING_DIR}/tests/common + + # Otherwise we're clearly not in zuul or using a previously setup + # repo in some way, so just clone it from upstream. + else + git clone \ + https://git.openstack.org/openstack/openstack-ansible-tests \ + ${WORKING_DIR}/tests/common + fi +fi + +# If this test set includes an upgrade test, the +# previous stable release tests repo must also be +# cloned. +# Note: +# Dependent patches to the previous stable release +# tests repo are not supported. +if [[ "${CLONE_UPGRADE_TESTS}" == "yes" ]]; then + if [[ ! -d "${WORKING_DIR}/tests/common/previous" ]]; then + git clone -b stable/pike \ + https://git.openstack.org/openstack/openstack-ansible-tests \ + ${WORKING_DIR}/tests/common/previous + fi +fi diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..8e2c411 --- /dev/null +++ b/tox.ini @@ -0,0 +1,116 @@ +[tox] +minversion = 2.0 +skipsdist = True +envlist = docs,linters,functional + + +[testenv] +usedevelop = True +install_command = + pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} +deps = + -r{toxinidir}/test-requirements.txt +commands = + /usr/bin/find . -type f -name "*.pyc" -delete +passenv = + HOME + http_proxy + HTTP_PROXY + https_proxy + HTTPS_PROXY + no_proxy + NO_PROXY +whitelist_externals = + bash +setenv = + PYTHONUNBUFFERED=1 + ROLE_NAME=nspawn_hosts + TEST_IDEMPOTENCE=false + VIRTUAL_ENV={envdir} + WORKING_DIR={toxinidir} + # bug#1682108 + PYTHONPATH={envsitepackagesdir} + + +[testenv:docs] +commands= + bash -c "rm -rf doc/build" + doc8 doc + python setup.py build_sphinx + + +[doc8] +# Settings for doc8: +extensions = .rst + + +[testenv:releasenotes] +commands = + sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html + + +# environment used by the -infra templated docs job +[testenv:venv] +commands = + {posargs} + + +[testenv:pep8] +commands = + bash -c "{toxinidir}/tests/tests-repo-clone.sh" + bash -c "{toxinidir}/tests/common/test-pep8.sh" + + +[flake8] +# Ignores the following rules due to how ansible modules work in general +# F403 'from ansible.module_utils.basic import *' used; +# unable to detect undefined names +ignore=F403 + + +[testenv:bashate] +commands = + bash -c "{toxinidir}/tests/tests-repo-clone.sh" + bash -c "{toxinidir}/tests/common/test-bashate.sh" + + +[testenv:ansible] +deps = + {[testenv]deps} + -rhttps://git.openstack.org/cgit/openstack/openstack-ansible/plain/global-requirement-pins.txt + -rhttps://git.openstack.org/cgit/openstack/openstack-ansible-tests/plain/test-ansible-deps.txt + + +[testenv:ansible-syntax] +deps = + {[testenv:ansible]deps} +commands = + bash -c "{toxinidir}/tests/tests-repo-clone.sh" + bash -c "{toxinidir}/tests/common/test-ansible-syntax.sh" + + +[testenv:ansible-lint] +deps = + {[testenv:ansible]deps} +commands = + bash -c "{toxinidir}/tests/tests-repo-clone.sh" + bash -c "{toxinidir}/tests/common/test-ansible-lint.sh" + + +[testenv:functional] +deps = + {[testenv:ansible]deps} +commands = + bash -c "{toxinidir}/tests/tests-repo-clone.sh" + bash -c "{toxinidir}/tests/common/test-ansible-functional.sh" + + +[testenv:linters] +deps = + {[testenv:ansible]deps} +commands = + {[testenv:pep8]commands} + {[testenv:bashate]commands} + {[testenv:ansible-lint]commands} + {[testenv:ansible-syntax]commands} + {[testenv:docs]commands} diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..258b061 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2018, Rackspace US, Inc. +# +# 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. + +# Mappings from Ansible reported architecture to distro release architecture +nspawn_architecture_mapping: + x86_64: amd64 + ppc64le: ppc64el + s390x: s390x + armv7l: armhf diff --git a/vars/redhat-7.yml b/vars/redhat-7.yml new file mode 100644 index 0000000..377d905 --- /dev/null +++ b/vars/redhat-7.yml @@ -0,0 +1,52 @@ +--- +# Copyright 2016, Rackspace US, Inc. +# +# 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. + +nspawn_hosts_distro_packages: + - aria2 + - bridge-utils + - btrfs-progs + - dbus + - dnsmasq + - git + - libseccomp + - psmisc + - systemd-networkd + - unzip + - xz + +nspawn_container_distro_packages: + - ca-certificates + - cronie + - dbus + - epel-release + - openssh-server + - python2 + - rsync + - sudo + - systemd-networkd + - tar + - wget + - which + - yum-plugin-priorities + - yum-utils + +nspawn_cache_map: + distro: centos + arch: amd64 + release: 7 + +nspawn_copy_from_host: + - /etc/pki/rpm-gpg/ + - /etc/yum.repos.d/ diff --git a/vars/suse-42.yml b/vars/suse-42.yml new file mode 100644 index 0000000..1dd98d9 --- /dev/null +++ b/vars/suse-42.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2016, Rackspace US, Inc. +# Copyright 2017, SUSE LINUX GmbH. +# +# 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. + +# Unimplemented. We'll need to circle back on this once OpenSUSE supports networkd diff --git a/vars/ubuntu-16.04.yml b/vars/ubuntu-16.04.yml new file mode 100644 index 0000000..cb63c0b --- /dev/null +++ b/vars/ubuntu-16.04.yml @@ -0,0 +1,51 @@ +--- +# Copyright 2016, Rackspace US, Inc. +# +# 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. + +nspawn_hosts_distro_packages: + - aria2 + - bridge-utils + - btrfs-tools + - dbus + - dnsmasq + - git + - iptables + - irqbalance + - psmisc + - pxz + - systemd-container + +nspawn_container_distro_packages: + - apt-transport-https + - ca-certificates + - cron + - dbus + - openssh-server + - python2.7 + - python-apt + - rsync + - sudo + - tar + - wget + - debianutils + +nspawn_cache_map: + distro: ubuntu + arch: "{{ nspawn_architecture_mapping.get(ansible_architecture) }}" + release: xenial + +nspawn_copy_from_host: + - /etc/apt/apt.conf.d/ + - /etc/apt/preferences.d/ + - /etc/apt/sources.list diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml new file mode 100644 index 0000000..df9ceb1 --- /dev/null +++ b/zuul.d/jobs.yaml @@ -0,0 +1,42 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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. + +- job: + name: openstack-ansible-nspawn-container-create + parent: openstack-ansible-cross-repo-functional + required-projects: + - name: openstack/openstack-ansible-nspawn_container_create + vars: + osa_test_repo: "openstack/openstack-ansible-nspawn_container_create" + +- job: + name: openstack-ansible-nspawn-dir-ubuntu-xenial + parent: openstack-ansible-nspawn-container-create + vars: + tox_env: dir + +- job: + name: openstack-ansible-nspawn-dir-centos-7 + parent: openstack-ansible-nspawn-container-create + nodeset: centos-7 + vars: + tox_env: dir + +- job: + name: openstack-ansible-nspawn-dir-opensuse-423 + parent: openstack-ansible-nspawn-container-create + nodeset: opensuse-423 + vars: + tox_env: dir diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml new file mode 100644 index 0000000..5e95b96 --- /dev/null +++ b/zuul.d/project.yaml @@ -0,0 +1,30 @@ +--- +# Copyright 2017, Rackspace US, Inc. +# +# 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. + +- project: + name: openstack/openstack-ansible-nspawn_hosts + check: + jobs: + - openstack-ansible-linters + - openstack-ansible-functional-centos-7 + - openstack-ansible-functional-ubuntu-xenial + experimental: + jobs: + - openstack-ansible-integrated-deploy-aio + gate: + jobs: + - openstack-ansible-linters + - openstack-ansible-functional-centos-7 + - openstack-ansible-functional-ubuntu-xenial