From eb9f3d858bb39657ff44dffafff38b0458739f63 Mon Sep 17 00:00:00 2001 From: Kevin Carter Date: Tue, 3 Nov 2015 03:40:40 -0600 Subject: [PATCH] IRR for lxc_host The change moves the role out from the main repo lxc_host repository and into its own standalone repository. Items within this change: * The role has been updated to ensure it runs standalone. * Tests added to the role within tox. * Functional tests added to the role that can either be run via the run_tests.sh script or using tox. * dev requirements have been updated for testing usecases. * Docs added to both the README.rst file as well as the docs folder. Signed-off-by: Kevin Carter --- .DS_Store | Bin 0 -> 6148 bytes CONTRIBUTING.rst | 85 +++++++ LICENSE | 202 +++++++++++++++ README.rst | 14 ++ defaults/main.yml | 99 ++++++++ dev-requirements.txt | 6 + doc/Makefile | 195 +++++++++++++++ doc/source/conf.py | 290 ++++++++++++++++++++++ doc/source/index.rst | 23 ++ handlers/main.yml | 35 +++ meta/main.yml | 33 +++ run_tests.sh | 38 +++ setup.cfg | 24 ++ setup.py | 22 ++ tasks/lxc_cache.yml | 41 +++ tasks/lxc_cache_preparation.yml | 101 ++++++++ tasks/lxc_dnsmasq_cleanup.yml | 28 +++ tasks/lxc_install.yml | 50 ++++ tasks/lxc_kernel_tuning.yml | 24 ++ tasks/lxc_net.yml | 50 ++++ tasks/lxc_pre_install.yml | 93 +++++++ tasks/main.yml | 25 ++ templates/irqbalance.j2 | 12 + templates/lxc-net-bridge.cfg.j2 | 25 ++ templates/lxc-openstack.apparmor.j2 | 26 ++ templates/lxc-openstack.conf.j2 | 13 + templates/lxc-resolve-base.j2 | 3 + templates/lxc-system-manage.j2 | 371 ++++++++++++++++++++++++++++ templates/lxc.default.j2 | 12 + templates/manual-init.override.j2 | 9 + templates/sources.list.j2 | 5 + tests/ansible-role-requirements.yml | 6 + tests/ansible.cfg | 3 + tests/inventory | 2 + tests/test.yml | 62 +++++ tox.ini | 97 ++++++++ 36 files changed, 2124 insertions(+) create mode 100644 .DS_Store create mode 100644 CONTRIBUTING.rst create mode 100644 LICENSE create mode 100644 README.rst create mode 100644 defaults/main.yml create mode 100644 dev-requirements.txt create mode 100644 doc/Makefile create mode 100644 doc/source/conf.py create mode 100644 doc/source/index.rst create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 run_tests.sh create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tasks/lxc_cache.yml create mode 100644 tasks/lxc_cache_preparation.yml create mode 100644 tasks/lxc_dnsmasq_cleanup.yml create mode 100644 tasks/lxc_install.yml create mode 100644 tasks/lxc_kernel_tuning.yml create mode 100644 tasks/lxc_net.yml create mode 100644 tasks/lxc_pre_install.yml create mode 100644 tasks/main.yml create mode 100644 templates/irqbalance.j2 create mode 100644 templates/lxc-net-bridge.cfg.j2 create mode 100644 templates/lxc-openstack.apparmor.j2 create mode 100644 templates/lxc-openstack.conf.j2 create mode 100644 templates/lxc-resolve-base.j2 create mode 100644 templates/lxc-system-manage.j2 create mode 100644 templates/lxc.default.j2 create mode 100644 templates/manual-init.override.j2 create mode 100644 templates/sources.list.j2 create mode 100644 tests/ansible-role-requirements.yml create mode 100644 tests/ansible.cfg create mode 100644 tests/inventory create mode 100644 tests/test.yml create mode 100644 tox.ini diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0ef8d2ef7ae352fd40ef351bfdf77ff95f73d30b GIT binary patch literal 6148 zcmeHK&1%~~5Z?7qBUu-PCJ@L)*Mbi&vGG-L(__J)5L4>nN=S(pgk&t)rWk|Hd5ktc zz4jSG`VM`R+%mJfHa2dKDNUJy*>84sW>@-F>}VNdyfX>kGG;Tz3{b?93C$k_$5FSW zq&-+Z*jAD`HjmB?YDp#tnb_}y-)hx@h zcWa-$VLJ12Kc8eBfBZ@IL>L9y?)v#~X`iNPyt4h^OhmJRz4tCna$h9TcrCTx6G@oP zI_V?{v%aV1>xnQQ4($EzIGRFg*H5A|k%>UWBL8ZbhH07u`(QqAwpw+k**sd*oq4<6 z0Q;!DSlB-e_!u`RTEV0b=0!7{K$v0Y!8*77FFj0S*2>;&=rS1#G-aAUYad zjfFxO0pThYP^EHx#o#I({Em)uH5Lk0I^%L>m`AV7^$mr~)xqz`aK>GQ)Di>4z$OD_ z)wQwyzkmAvznMfmVt^RqF`L1aFqgvEX5FurT73; a3iur~09}oRLhyjlkAS3s8e-tDGVlmD!em?k literal 0 HcmV?d00001 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 00000000..9ba364b1 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,85 @@ +OpenStack LXC host setup +######################## +:tags: openstack, lxc, host, cloud, ansible +:category: \*nix + +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 00000000..8f71f43f --- /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 00000000..7ae5f47c --- /dev/null +++ b/README.rst @@ -0,0 +1,14 @@ +OpenStack LXC host setup +######################## +:tags: openstack, lxc, host, cloud, ansible +:category: \*nix + +Role for deployment and setup of an LXC host. + +.. code-block:: yaml + + - name: Basic lxc host setup + hosts: "hosts" + user: root + roles: + - { role: "lxc_hosts", tags: [ "lxc-host", "host-setup" ] } diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 00000000..c82829b3 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,99 @@ +--- +# 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. + +# lxc container rootfs directory and cache path +lxc_container_directory: "/var/lib/lxc" +lxc_container_cache_path: "/var/cache/lxc" + +# lxc container net network +lxc_net_bridge: lxcbr0 +lxc_net_bridge_port: none +lxc_net_address: 10.0.3.1 +lxc_net_netmask: 255.255.255.0 +lxc_net_gateway: none ## if "none" no gateway will on the LXC bridge, nat must be "false" to use a gateway. + +# lxc container nat enabled +lxc_net_nat: true ## If "true" nat rules will be created with the lxc network. + +# lxc container dhcp settings +lxc_net_dhcp_range: 10.0.3.2,10.0.3.253 +lxc_net_dhcp_max: 253 +lxc_net_dhcp_config: '' +lxc_net_dnsmasq_user: lxc-dnsmasq +lxc_net_domain: '' + +# lxc_container_net_link variable should be set to the lxc-net bridge. +lxc_container_net_link: "{{ lxc_net_bridge }}" ## name of the host bridge to attach to +lxc_container_net_type: veth ## lxc network interface type (veth, phys, vlan, macvlan, empty) +lxc_container_net_name: eth0 ## name of the interface inside the container. + +# System control kernel tuning +lxc_kernel_options: + - { key: 'fs.inotify.max_user_instances', value: 1024 } + +# Default image to build from +lxc_container_release: trusty +lxc_container_user_name: ubuntu +lxc_container_user_password: "{{ lookup('pipe', 'date --rfc-3339=ns | sha512sum | base64 | head -c 32') }}" +lxc_container_template_options: > + --release {{ lxc_container_release }} + --user {{ lxc_container_user_name }} + --password {{ lxc_container_user_password }} + +lxc_container_template_main_apt_repo: "https://mirror.rackspace.com/ubuntu" +lxc_container_template_security_apt_repo: "https://mirror.rackspace.com/ubuntu" + + +# Required apt packages. +lxc_apt_packages: + - apparmor-utils + - bridge-utils + - cgmanager + - cgroup-lite + - debootstrap + - dnsmasq + - git + - liblxc1 + - lxc + - lxc-dev + - lxc-templates + - python-dev + - python3-lxc + +# Commands to run against cached LXC image +lxc_cache_commands: + - apt-get update + - apt-get -y upgrade + - apt-get -y install python2.7 + - rm -f /usr/bin/python + - ln -s /usr/bin/python2.7 /usr/bin/python + +lxc_cache_resolvers: + - 'nameserver 8.8.8.8' + - 'nameserver 8.8.4.4' + +lxc_cache_sshd_configuration: + - { regexp: "^PermitRootLogin", line: "PermitRootLogin yes" } + - { regexp: "^TCPKeepAlive", line: "TCPKeepAlive yes" } + - { regexp: "^UseDNS", line: "UseDNS no" } + - { regexp: "^X11Forwarding", line: "X11Forwarding no" } + - { regexp: "^PasswordAuthentication", line: "PasswordAuthentication no" } + +# Prebuilt images to deploy onto hosts for use in containers. +# lxc_container_caches: +# - url: "https://rpc-repo.rackspace.com/container_images/rpc-trusty-container.tgz" +# name: "trusty.tgz" +# sha256sum: "56c6a6e132ea7d10be2f3e8104f47136ccf408b30e362133f0dc4a0a9adb4d0c" +# chroot_path: trusty/rootfs-amd64 diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 00000000..f9f762ea --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,6 @@ +ansible-lint +ansible>=1.9.1,<2.0.0 + +# this is required for the docs build jobs +sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 +oslosphinx>=2.5.0 # Apache-2.0 diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..4558cd5f --- /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-apt_package_pinning.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/openstack-ansible-apt_package_pinning.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-apt_package_pinning" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/openstack-ansible-apt_package_pinning" + @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 00000000..84882b02 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# openstack-ansible-apt_package_pinning documentation build configuration file, created by +# sphinx-quickstart on Mon Apr 13 20:42:26 2015. +# +# 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 = [ + 'sphinx.ext.autodoc', + 'oslosphinx' +] + +# The link to the browsable source code (for the left hand menu) +oslosphinx_cgit_link = 'http://git.openstack.org/cgit/openstack/openstack-ansible-apt_package_pinning' + +# 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. +project = 'openstack-ansible-apt_package_pinning' +copyright = '2015, openstack-ansible-apt_package_pinning contributors' +author = 'openstack-ansible-apt_package_pinning contributors' + +# 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 = 'master' +# The full version, including alpha/beta/rc tags. +release = 'master' + +# 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 = 'alabaster' + +# 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 = '%b %d, %Y' + +# 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 = 'openstack-ansible-apt_package_pinningdoc' + +# -- 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, 'openstack-ansible-apt_package_pinning.tex', + 'openstack-ansible-apt_package_pinning Documentation', + 'openstack-ansible-apt_package_pinning contributors', '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, 'openstack-ansible-apt_package_pinning', + 'openstack-ansible-apt_package_pinning Documentation', + [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, 'openstack-ansible-apt_package_pinning', + 'openstack-ansible-apt_package_pinning Documentation', + author, 'openstack-ansible-apt_package_pinning', 'One line description of project.', + 'Miscellaneous'), +] + +# 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 diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 00000000..65ff95af --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,23 @@ +lxc_host role docs +================== + +The lxc_host role is used to setup hosts that will be running LXC +within them. The role will configure and build everything needed +for the environment to be successful in deploying LXC containers. + +In the example the role is using an optional argument to create an +LXC cached image on the disk. The use of this extra variable will +download an image into place and update it. + + +Basic Role Example +^^^^^^^^^^^^^^^^^^ + +.. code-block:: yaml + + - role: "lxc_host" + lxc_container_caches: + - url: "{{ repo_pip_default_index | netorigin }}/container_images/rpc-trusty-container.tgz" + name: "trusty.tgz" + sha256sum: "56c6a6e132ea7d10be2f3e8104f47136ccf408b30e362133f0dc4a0a9adb4d0c" + chroot_path: trusty/rootfs-amd64 diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 00000000..19d0bdb8 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,35 @@ +--- +# 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. + +- name: Load lxc-openstack apparmor profile + command: apparmor_parser -Kr /etc/apparmor.d/lxc-containers + +- name: Restart apparmor + service: + name: "apparmor" + state: "restarted" + +- name: Init reload + command: "initctl reload-configuration" + +- name: Restart irqbalance + service: + name: "irqbalance" + state: "restarted" + pattern: "irqbalance" + enabled: "yes" + +- name: Bring bridge up + command: "ifup {{ lxc_net_bridge }}" diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 00000000..f18ace70 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,33 @@ +--- +# 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 LXC hosts for use in Rackspace Private Cloud + company: Rackspace + license: Apache2 + min_ansible_version: 1.6.6 + platforms: + - name: Ubuntu + versions: + - trusty + categories: + - cloud + - lxc + - development + - openstack +dependencies: + - apt_package_pinning + - pip_install diff --git a/run_tests.sh b/run_tests.sh new file mode 100644 index 00000000..2e24671f --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,38 @@ +#!/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. + +set -euov + +ROLE_NAME=$(basename $(pwd)) +FUNCTIONAL_TEST=${FUNCTIONAL_TEST:-true} + +pushd tests + ansible-galaxy install \ + --role-file=ansible-role-requirements.yml \ + --ignore-errors \ + --force + + ansible-playbook -i inventory \ + --syntax-check \ + --list-tasks \ + -e "rolename=${ROLE_NAME}" \ + test.yml + + ansible-lint test.yml + + if ${FUNCTIONAL_TEST}; then + ansible-playbook -i inventory -e "rolename=${ROLE_NAME}" test.yml + fi +popd diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..9cac47b0 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,24 @@ +[metadata] +name = openstack-ansible-apt_package_pinning +summary = APT package pinning for OpenStack Ansible +description-file = + README.rst +author = OpenStack +author-email = openstack-dev@lists.openstack.org +home-page = http://www.openstack.org/ +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 00000000..70c2b3f3 --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +# 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 + +setuptools.setup( + setup_requires=['pbr'], + pbr=True) diff --git a/tasks/lxc_cache.yml b/tasks/lxc_cache.yml new file mode 100644 index 00000000..affb2fa1 --- /dev/null +++ b/tasks/lxc_cache.yml @@ -0,0 +1,41 @@ +--- +# 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. + +- name: Download lxc cache(s) + get_url: + url: "{{ item.url }}" + dest: "/var/cache/lxc_{{ item.name }}" + mode: "0644" + force: no + sha256sum: "{{ item.sha256sum }}" + register: cache_download + retries: 3 + delay: 10 + until: cache_download|success + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-download + +- name: Move lxc cached image into place + unarchive: + src: "/var/cache/lxc_{{ item.name }}" + dest: "{{ lxc_container_cache_path }}/" + copy: "no" + with_items: lxc_container_caches + when: cache_download|changed + tags: + - lxc-cache + - lxc-cache-unarchive diff --git a/tasks/lxc_cache_preparation.yml b/tasks/lxc_cache_preparation.yml new file mode 100644 index 00000000..6d18be39 --- /dev/null +++ b/tasks/lxc_cache_preparation.yml @@ -0,0 +1,101 @@ +--- +# 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: Create apt repos in the cached container + template: + src: sources.list.j2 + dest: "{{ lxc_container_cache_path }}/{{ item.chroot_path }}/etc/apt/sources.list" + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-update + +- name: Update container resolvers + template: + src: lxc-resolve-base.j2 + dest: "{{ lxc_container_cache_path }}/{{ item.chroot_path }}/run/resolvconf/resolv.conf" + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-update + +- name: Update container resolvconf base + template: + src: lxc-resolve-base.j2 + dest: "{{ lxc_container_cache_path }}/{{ item.chroot_path }}/etc/resolvconf/resolv.conf.d/base" + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-update + +- name: Update container resolvconf tail + copy: + content: "# Null Tail" + dest: "{{ lxc_container_cache_path }}/{{ item.chroot_path }}/etc/resolvconf/resolv.conf.d/tail" + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-update + +- name: Update container resolvconf original + copy: + content: "# Null original" + dest: "{{ lxc_container_cache_path }}/{{ item.chroot_path }}/etc/resolvconf/resolv.conf.d/original" + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-update + +# This task runs several commands against the cached image to speed up the +# lxc_container_create playbook. +- name: Prepare cached image + command: "chroot {{ lxc_container_cache_path }}/{{ item[0].chroot_path }} {{ item[1] }}" + with_nested: + - lxc_container_caches + - lxc_cache_commands + when: cache_download|changed + tags: + - lxc-cache + - lxc-cache-update + +- name: Adjust sshd configuration in container + lineinfile: + dest: "{{ lxc_container_cache_path }}/{{ item[0].chroot_path }}/etc/ssh/sshd_config" + regexp: "{{ item[1].regexp }}" + line: "{{ item[1].line }}" + state: present + with_nested: + - lxc_container_caches + - lxc_cache_sshd_configuration + tags: + - lxc-cache + - lxc-cache-update + +- name: Obtain the system's ssh public key + set_fact: + lxc_container_ssh_key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}" + when: lxc_container_ssh_key is not defined + tags: + - lxc-cache + - lxc-cache-update + +- name: Deploy ssh public key into the cached image + lineinfile: + dest: "{{ lxc_container_cache_path }}/{{ item.chroot_path }}/root/.ssh/authorized_keys" + line: "{{ lxc_container_ssh_key }}" + with_items: lxc_container_caches + tags: + - lxc-cache + - lxc-cache-update diff --git a/tasks/lxc_dnsmasq_cleanup.yml b/tasks/lxc_dnsmasq_cleanup.yml new file mode 100644 index 00000000..7ef23a7d --- /dev/null +++ b/tasks/lxc_dnsmasq_cleanup.yml @@ -0,0 +1,28 @@ +--- +# 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. + +- name: Ensure dnsmasq stopped + service: + name: "dnsmasq" + state: "stopped" + enabled: "no" + +- name: Remove dnsmasq file(s) + file: + path: "{{ item }}" + state: "absent" + with_items: + - /var/run/dnsmasq/resolv.conf + - /etc/dnsmasq.conf diff --git a/tasks/lxc_install.yml b/tasks/lxc_install.yml new file mode 100644 index 00000000..04d5ea9d --- /dev/null +++ b/tasks/lxc_install.yml @@ -0,0 +1,50 @@ +--- +# 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. + +- name: Update apt sources + apt: + update_cache: yes + cache_valid_time: 600 + register: apt_update + until: apt_update|success + retries: 5 + delay: 2 + tags: + - lxc-apt-packages + +- name: Install apt packages + apt: + pkg: "{{ item }}" + state: present + register: install_packages + until: install_packages|success + retries: 5 + delay: 2 + with_items: lxc_apt_packages + tags: + - lxc-apt-packages + +# The functionality with changing the container cache has been added into the +# upstream LXC templates with patch [ https://github.com/lxc/lxc/pull/558 ] +# TODO: remove the below patch and pass lxc_container_cache_path to lxc +# templates as appropriate once the lxc update goes mainstream +- name: Patch lxc-ubuntu cache path + replace: + dest: /usr/share/lxc/templates/lxc-ubuntu + regexp: '\$LOCALSTATEDIR/cache/lxc' + replace: "{{ lxc_container_cache_path }}" + backup: yes + tags: + - lxc-cache-path diff --git a/tasks/lxc_kernel_tuning.yml b/tasks/lxc_kernel_tuning.yml new file mode 100644 index 00000000..2b05b992 --- /dev/null +++ b/tasks/lxc_kernel_tuning.yml @@ -0,0 +1,24 @@ +--- +# 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. + +- name: Tuning kernel for lxc + sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" + sysctl_set: "{{ item.set|default('yes') }}" + state: "{{ item.state|default('present') }}" + reload: "{{ item.reload|default('yes') }}" + ignore_errors: true + with_items: lxc_kernel_options diff --git a/tasks/lxc_net.yml b/tasks/lxc_net.yml new file mode 100644 index 00000000..1626c746 --- /dev/null +++ b/tasks/lxc_net.yml @@ -0,0 +1,50 @@ +--- +# 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. + +- name: Ensure networking includes interfaces.d + lineinfile: + dest: "/etc/network/interfaces" + line: "source /etc/network/interfaces.d/*.cfg" + backup: "yes" + tags: + - lxc-net + - lxc-interfaces + +- name: Check Container Bridge exists + file: + state: "file" + path: "/sys/class/net/{{ lxc_net_bridge }}/bridge/bridge_id" + register: bridge_check + failed_when: false + changed_when: bridge_check.state == 'absent' + notify: + - Bring bridge up + tags: + - lxc-net + - lxc-bridge + +- name: Drop lxc net bridge + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ item.owner|default('root') }}" + group: "{{ item.group|default('root') }}" + mode: "{{ item.mode|default('0644') }}" + with_items: + - { src: lxc-net-bridge.cfg.j2, dest: "/etc/network/interfaces.d/lxc-net-bridge.cfg" } + tags: + - lxc-files + - lxc-net + - lxc-bridge diff --git a/tasks/lxc_pre_install.yml b/tasks/lxc_pre_install.yml new file mode 100644 index 00000000..02ff8f73 --- /dev/null +++ b/tasks/lxc_pre_install.yml @@ -0,0 +1,93 @@ +--- +# 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. + +- name: Create base directories + file: + path: "{{ item }}" + state: "directory" + owner: "root" + group: "root" + with_items: + - /etc/lxc + - /usr/local/bin + - /etc/network/interfaces.d + - /etc/apparmor.d/lxc + - /usr/share/lxc/templates + - /openstack + - /openstack/backup + - "{{ lxc_container_directory }}" + - "{{ lxc_container_cache_path }}" + tags: + - lxc-directories + +- name: Ensure the lxc dnsmasq user exists + user: + name: "{{ lxc_net_dnsmasq_user }}" + comment: "LXC dnsmasq" + system: "yes" + shell: "/bin/false" + home: "/var/lib/lxc" + tags: + - lxc-dnsmasq-user + +- name: Drop base config file(s) + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ item.owner|default('root') }}" + group: "{{ item.group|default('root') }}" + mode: "{{ item.mode|default('0644') }}" + with_items: + - { src: lxc-openstack.conf.j2, dest: "/etc/lxc/lxc-openstack.conf" } + - { src: lxc.default.j2, dest: "/etc/default/lxc-net", mode: "0644" } + - { src: lxc-system-manage.j2, dest: "/usr/local/bin/lxc-system-manage", mode: "0755" } + - { src: manual-init.override.j2, dest: "/etc/init/lxc-net.override" } + tags: + - lxc-files + - lxc-config + +- name: Drop irqbalance config + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ item.owner|default('root') }}" + group: "{{ item.group|default('root') }}" + mode: "{{ item.mode|default('0644') }}" + with_items: + - { src: irqbalance.j2, dest: "/etc/default/irqbalance" } + notify: + - Restart irqbalance + tags: + - lxc-files + - lxc-irqbalance + +- name: Drop lxc-openstack app armor profile + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ item.owner|default('root') }}" + group: "{{ item.group|default('root') }}" + mode: "{{ item.mode|default('0644') }}" + with_items: + - { src: lxc-openstack.apparmor.j2, dest: "/etc/apparmor.d/lxc/lxc-openstack" } + notify: + - Load lxc-openstack apparmor profile + - Restart apparmor + tags: + - lxc-files + - lxc-apparmor + +# Ensure apparmor reindex runs before other things that may fail +- meta: flush_handlers diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 00000000..1f229691 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,25 @@ +--- +# 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. + +- include: lxc_pre_install.yml +- include: lxc_kernel_tuning.yml +- include: lxc_net.yml +- include: lxc_install.yml +- include: lxc_dnsmasq_cleanup.yml +- include: lxc_cache.yml +- include: lxc_cache_preparation.yml + when: lxc_container_caches is defined +- name: Flush handlers + meta: flush_handlers diff --git a/templates/irqbalance.j2 b/templates/irqbalance.j2 new file mode 100644 index 00000000..cf23a53d --- /dev/null +++ b/templates/irqbalance.j2 @@ -0,0 +1,12 @@ +# {{ ansible_managed }} + +#Configuration for the irqbalance daemon + +#Should irqbalance be enabled? +ENABLED="1" + +#Balance the IRQs only once? +ONESHOT="0" + +# Ignore hints +OPTIONS="--hintpolicy=ignore" diff --git a/templates/lxc-net-bridge.cfg.j2 b/templates/lxc-net-bridge.cfg.j2 new file mode 100644 index 00000000..afcb161b --- /dev/null +++ b/templates/lxc-net-bridge.cfg.j2 @@ -0,0 +1,25 @@ +# {{ ansible_managed }} + +auto {{ lxc_net_bridge }} +iface {{ lxc_net_bridge }} inet static + address {{ lxc_net_address }} + netmask {{ lxc_net_netmask }} +{% if lxc_net_nat == "true" %} +{% if lxc_net_gateway != "none" %} + gateway {{ lxc_net_gateway }} +{% endif %} + # nat rules start and stop + post-up /usr/local/bin/lxc-system-manage iptables-create + post-down /usr/local/bin/lxc-system-manage iptables-remove +{% endif %} + # dnsmasq start and stop + post-up /usr/local/bin/lxc-system-manage dnsmasq-start || true + post-up /usr/local/bin/lxc-system-manage iptables-create + post-down /usr/local/bin/lxc-system-manage dnsmasq-stop + post-down /usr/local/bin/lxc-system-manage iptables-remove + bridge_fd 0 + bridge_maxwait 0 + bridge_ports {{ lxc_net_bridge_port }} + bridge_hello 2 + bridge_maxage 12 + bridge_stp off diff --git a/templates/lxc-openstack.apparmor.j2 b/templates/lxc-openstack.apparmor.j2 new file mode 100644 index 00000000..62b6ec78 --- /dev/null +++ b/templates/lxc-openstack.apparmor.j2 @@ -0,0 +1,26 @@ +# Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which +# will source all profiles under /etc/apparmor.d/lxc + +profile lxc-openstack flags=(attach_disconnected,mediate_deleted) { + #include + +# allow standard blockdevtypes. +# The concern here is in-kernel superblock parsers bringing down the +# host with bad data. However, we continue to disallow proc, sys, securityfs, +# etc to nonstandard locations. + mount fstype=ext* -> /**, + mount fstype=nbd* -> /**, + mount fstype=xfs -> /**, + mount fstype=btrfs -> /**, + mount fstype=vfat* -> /**, + mount fstype=fuseblk -> /**, + mount fstype=nbd* -> /**, + mount fstype=nfs* -> /**, + mount fstype=devpts, + +# allow System access. + mount fstype=cgroup -> /sys/fs/cgroup/**, + mount fstype=proc -> {{ lxc_container_cache_path }}/**, + mount fstype=sysfs -> {{ lxc_container_cache_path }}/**, + mount options=(rw,bind) {{ lxc_container_cache_path }}/**/dev/shm/ -> {{ lxc_container_cache_path }}/**/run/shm/, +} diff --git a/templates/lxc-openstack.conf.j2 b/templates/lxc-openstack.conf.j2 new file mode 100644 index 00000000..24b38da7 --- /dev/null +++ b/templates/lxc-openstack.conf.j2 @@ -0,0 +1,13 @@ +# {{ ansible_managed }} + +lxc.start.auto = 1 +lxc.start.delay = 15 +lxc.group = onboot +lxc.group = openstack + +# Default LXC network +lxc.network.type = {{ lxc_container_net_type }} +lxc.network.name = {{ lxc_container_net_name }} +lxc.network.link = {{ lxc_container_net_link }} +lxc.network.flags = up +lxc.network.hwaddr = 00:16:3e:xx:xx:xx diff --git a/templates/lxc-resolve-base.j2 b/templates/lxc-resolve-base.j2 new file mode 100644 index 00000000..a1556f88 --- /dev/null +++ b/templates/lxc-resolve-base.j2 @@ -0,0 +1,3 @@ +{% for item in lxc_cache_resolvers %} +{{ item }} +{% endfor %} diff --git a/templates/lxc-system-manage.j2 b/templates/lxc-system-manage.j2 new file mode 100644 index 00000000..ebbb2a5a --- /dev/null +++ b/templates/lxc-system-manage.j2 @@ -0,0 +1,371 @@ +#!/usr/bin/env bash +# 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. + +# This script was built for the express purpose of managing LXC on a +# host. The functions within this script provide for common operations +# that may be required when working with LXC in production. + +# {{ ansible_managed }} + +export USE_LXC_BRIDGE="true" +export LXC_BRIDGE="{{ lxc_net_bridge }}" +export LXC_ADDR="{{ lxc_net_address }}" +export LXC_NETMASK="{{ lxc_net_netmask }}" +export LXC_NETWORK="${LXC_ADDR}/${LXC_NETMASK}" +export LXC_DHCP_RANGE="{{ lxc_net_dhcp_range }}" +export LXC_DHCP_MAX="{{ lxc_net_dhcp_max }}" +export LXC_DHCP_CONFILE="{{ lxc_net_dhcp_config }}" +export LXC_DNSMASQ_USER="{{ lxc_net_dnsmasq_user }}" +export VARRUN="/run/lxc" +export LXC_DOMAIN="{{ lxc_net_domain }}" + +function warn { + echo -e "\e[0;35m${@}\e[0m" +} + +function info { + echo -e "\e[0;33m${@}\e[0m" +} + +function success { + echo -e "\e[0;32m${@}\e[0m" +} + +function remove_rules { + info "Removing LXC IPtables rules." + # Remove rules from the INPUT chain + iptables ${USE_IPTABLES_LOCK} -D INPUT -i "${LXC_BRIDGE}" -p udp --dport 67 -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -D INPUT -i "${LXC_BRIDGE}" -p tcp --dport 67 -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -D INPUT -i "${LXC_BRIDGE}" -p udp --dport 53 -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -D INPUT -i "${LXC_BRIDGE}" -p tcp --dport 53 -j ACCEPT + + # Remove rules from the FORWARDING chain + iptables ${USE_IPTABLES_LOCK} -D FORWARD -i "${LXC_BRIDGE}" -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -D FORWARD -o "${LXC_BRIDGE}" -j ACCEPT + + # Remove rules from the nat POSTROUTING chain + iptables ${USE_IPTABLES_LOCK} -t nat \ + -D POSTROUTING \ + -s "${LXC_NETWORK}" ! \ + -d "${LXC_NETWORK}" \ + -j MASQUERADE || true + + # Remove rules from the mangle POSTROUTING chain + iptables ${USE_IPTABLES_LOCK} -t mangle \ + -D POSTROUTING \ + -s "${LXC_NETWORK}" \ + -o "${LXC_BRIDGE}" \ + -p udp \ + -m udp \ + --dport 68 \ + -j CHECKSUM \ + --checksum-fill + success "IPtables rules removed." +} + +function add_rules { + info "Creating LXC IPtables rules." + set -e + # Set ip_prwarding + sysctl -w net.ipv4.ip_forward=1 > /dev/null 2>&1 + + # Add rules from the INPUT chain + iptables ${USE_IPTABLES_LOCK} -I INPUT -i "${LXC_BRIDGE}" -p udp --dport 67 -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -I INPUT -i "${LXC_BRIDGE}" -p tcp --dport 67 -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -I INPUT -i "${LXC_BRIDGE}" -p udp --dport 53 -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -I INPUT -i "${LXC_BRIDGE}" -p tcp --dport 53 -j ACCEPT + + # Add rules from the FORWARDING chain + iptables ${USE_IPTABLES_LOCK} -I FORWARD -i "${LXC_BRIDGE}" -j ACCEPT + iptables ${USE_IPTABLES_LOCK} -I FORWARD -o "${LXC_BRIDGE}" -j ACCEPT + + # Add rules from the nat POSTROUTING chain + iptables ${USE_IPTABLES_LOCK} -t nat \ + -A POSTROUTING \ + -s "${LXC_NETWORK}" ! \ + -d "${LXC_NETWORK}" \ + -j MASQUERADE + + # Add rules from the mangle POSTROUTING chain + iptables ${USE_IPTABLES_LOCK} -t mangle \ + -A POSTROUTING \ + -s "${LXC_NETWORK}" \ + -o "${LXC_BRIDGE}" \ + -p udp \ + -m udp \ + --dport 68 \ + -j CHECKSUM \ + --checksum-fill + success "IPtables rules created." +} + +function cleanup { + # Clean up everything + remove_rules + + # Set the lxc bridge interface down + ip link set "${LXC_BRIDGE}" down || true + + # Remove the lxc bridge interface + brctl delbr "${LXC_BRIDGE}" || true +} + +function pre_up { + # Create the run directory if needed. + if [[ ! -d "${VARRUN}" ]];then + mkdir -p "${VARRUN}" + fi + + # Source the lxc defaults + if [[ -f "/etc/default/lxc" ]]; then + source "/etc/default/lxc" + fi + + # Set the lock type where applicable + use_iptables_lock="-w" + iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock="" +} + +function start_dnsmasq { + set -e + info "Starting LXC dnsmasq." + dnsmasq "${LXC_DOMAIN_ARG}" --user="${LXC_DNSMASQ_USER}" \ + --pid-file="${VARRUN}/dnsmasq.pid" \ + --conf-file="${LXC_DHCP_CONFILE}" \ + --listen-address="${LXC_ADDR}" \ + --dhcp-range="${LXC_DHCP_RANGE}" \ + --dhcp-lease-max="${LXC_DHCP_MAX}" \ + --except-interface="lo" \ + --interface="${LXC_BRIDGE}" \ + --dhcp-leasefile="${DHCP_LEASE_FILE}" \ + --dhcp-no-override \ + --strict-order \ + --bind-interfaces \ + --dhcp-authoritative + success "dnsmasq started." +} + +function start_containers_nicely { + set -e + # Stop all containers on a host + success "Starting all containers." + for container in $(lxc-ls); do + lxc-start -d -n "${container}" + done +} + +function stop_containers_nicely { + # Stop all containers on a host + warn "Stopping all containers." + for container in $(lxc-ls); do + lxc-stop -n "${container}" + done +} + +function stop_containers_with_fire { + # Stop all containers on a host + warn "Stopping all containers with fire." + for container in $(lxc-ls); do + lxc-stop -k -n "${container}" + done +} + +function start_networks { + set -e + if [ -f "/sys/class/net/${LXC_BRIDGE}/bridge/bridge_id" ];then + success "LXC container network is already online." + else + if [ ! "$(ifup ${LXC_BRIDGE})" ];then + info "Building the LXC container network." + + # Create lxc bridge + brctl addbr "${LXC_BRIDGE}" || true + + # Set the lxc bridge up + ip link set "${LXC_BRIDGE}" up || true + + # Assign an address to the lxc bridge + ip addr add "${LXC_ADDR}"/"${LXC_NETMASK}" dev "${LXC_BRIDGE}" + + add_rules + + LXC_DOMAIN_ARG="" + if [ -n "$LXC_DOMAIN" ]; then + LXC_DOMAIN_ARG="-s $LXC_DOMAIN -S /$LXC_DOMAIN/" + fi + + # Start DNS mask + DHCP_LEASE_FILE="/var/lib/misc/dnsmasq.${LXC_BRIDGE}.leases" + start_dnsmasq + success "LXC container network has been created." + fi + fi +} + +function stop_dnsmasq { + if [[ -f "${VARRUN}/dnsmasq.pid" ]];then + PID="$(cat ${VARRUN}/dnsmasq.pid)" + if [[ "${PID}" ]];then + warn "Stopping LXC dnsmasq." + kill -9 "${PID}" || true + fi + rm -f "${VARRUN}/dnsmasq.pid" + fi +} + +function stop_networks { + warn "Destroying the LXC container network." + cleanup + stop_dnsmasq +} + +function remove_down_veth { + info "Getting a list of all DOWN veth interfaces" + VETHPAIRS="$(ip link list | grep veth | grep "state DOWN" | awk '/veth/ {print $2}' | sed 's/\://g')" + if [[ "$VETHPAIRS" ]];then + warn "Removing all DOWN veth interfaces" + for veth in $VETHPAIRS; do + ip link delete dev "${veth}" + done + else + success "No DOWN veth interfaces to remove" + fi +} + +function flush_cache { + warn "Flushing network cache" + ip -s -s neigh flush all +} + +# Run through the base app setup +pre_up + +# Check function +case "$1" in + containers-start) + start_containers_nicely + ;; + containers-stop) + stop_containers_nicely + ;; + containers-force-stop) + stop_containers_with_fire + ;; + containers-restart) + stop_containers_nicely + start_containers_nicely + ;; + containers-force-restart) + stop_containers_with_fire + start_containers_nicely + ;; + system-tear-down) + stop_containers_nicely + remove_down_veth + stop_networks + flush_cache + ;; + system-force-tear-down) + stop_containers_with_fire + remove_down_veth + stop_networks + flush_cache + ;; + system-start-up) + start_networks + start_containers_nicely + ;; + system-rebuild) + stop_containers_nicely + remove_down_veth + stop_networks + flush_cache + start_networks + start_containers_nicely + ;; + system-force-rebuild) + stop_containers_with_fire + remove_down_veth + stop_networks + flush_cache + start_networks + start_containers_nicely + ;; + dnsmasq-start) + start_dnsmasq + ;; + dnsmasq-stop) + stop_dnsmasq + ;; + dnsmasq-restart) + stop_dnsmasq + start_dnsmasq + ;; + iptables-create) + add_rules + ;; + iptables-remove) + remove_rules + ;; + iptables-recreate) + remove_rules + add_rules + ;; + veth-cleanup) + remove_down_veth + ;; + flush-net-cache) + flush_cache + ;; + *) + info 'Management of internal LXC systems and processes:' + echo ' + containers-start Start all containers. + containers-stop Stop all containers. + containers-restart Stop all containers and then Start them. + containers-force-stop Force Stop all containers. + containers-force-restart Force Stop all containers and then Start them. + system-start-up Start up everything that LXC needs to + operate, including the containers, dnsmasq, + LXC bridge, and IPtables. + system-tear-down Tear down everything LXC on this system. + This will remove all all IPtables rules, kill + dnsmasq, remove the LXC bridge, stops all + containers, removes DOWN veth interfaces, + and flushes the net cache. + system-force-tear-down Force tear down everything LXC on this system. + This will remove all all IPtables rules, kill + dnsmasq, remove the LXC bridge, stops all + containers, removes DOWN veth interfaces, + and flushes the net cache. + system-rebuild Rebuild the LXC network, IPtables, dnsmasq, + removes DOWN veth interfaces, flushes the + net cache, and restarts all conatiners. + system-force-rebuild Force rebuild the LXC network, IPtables, dnsmasq, + removes DOWN veth interfaces, flushes the + net cache, and restarts all conatiners. + dnsmasq-start Start the LXC dnsmasq process. + dnsmasq-stop Stop the LXC dnsmasq process. + dnsmasq-restart Restart the LXC dnsmasq process. + iptables-create Create the LXC IPtables rules for NAT. + iptables-remove Remove the LXC IPtables rules for NAT. + iptables-recreate Recreate the LXC IPtables rules for NAT. + veth-cleanup Remove all DOWN veth interfaces from a system. + flush-net-cache Flush the hosts network cache. This is useful if + IP addresses are being recycled on to containers + from other hosts. + ' + ;; +esac diff --git a/templates/lxc.default.j2 b/templates/lxc.default.j2 new file mode 100644 index 00000000..3de81e02 --- /dev/null +++ b/templates/lxc.default.j2 @@ -0,0 +1,12 @@ +# {{ ansible_managed }} + +USE_LXC_BRIDGE="true" +LXC_BRIDGE="{{ lxc_net_bridge }}" +LXC_ADDR="{{ lxc_net_address }}" +LXC_NETMASK="{{ lxc_net_netmask }}" +LXC_NETWORK="${LXC_ADDR}/${LXC_NETMASK}" +LXC_DHCP_RANGE="{{ lxc_net_dhcp_range }}" +LXC_DHCP_MAX="{{ lxc_net_dhcp_max }}" +LXC_DNSMASQ_USER="{{ lxc_net_dnsmasq_user }}" +LXC_DHCP_CONFILE="{{ lxc_net_dhcp_config }}" +LXC_DOMAIN="{{ lxc_net_domain }}" diff --git a/templates/manual-init.override.j2 b/templates/manual-init.override.j2 new file mode 100644 index 00000000..306c937e --- /dev/null +++ b/templates/manual-init.override.j2 @@ -0,0 +1,9 @@ +# {{ ansible_managed }} + +pre-start script + echo "pass" +end script + +post-stop script + echo "pass" +end script diff --git a/templates/sources.list.j2 b/templates/sources.list.j2 new file mode 100644 index 00000000..3190b2b6 --- /dev/null +++ b/templates/sources.list.j2 @@ -0,0 +1,5 @@ +# Sources created by the ansible +deb {{ lxc_container_template_main_apt_repo }} {{ lxc_container_release }} main restricted universe multiverse +deb {{ lxc_container_template_main_apt_repo }} {{ lxc_container_release }}-updates main restricted universe multiverse +deb {{ lxc_container_template_main_apt_repo }} {{ lxc_container_release }}-backports main restricted universe multiverse +deb {{ lxc_container_template_security_apt_repo }} {{ lxc_container_release }}-security main restricted universe multiverse diff --git a/tests/ansible-role-requirements.yml b/tests/ansible-role-requirements.yml new file mode 100644 index 00000000..509e662f --- /dev/null +++ b/tests/ansible-role-requirements.yml @@ -0,0 +1,6 @@ +- name: apt_package_pinning + src: https://github.com/os-cloud/openstack-ansible-apt_package_pinning + version: master +- name: pip_install + src: https://github.com/os-cloud/openstack-ansible-pip_install + version: master diff --git a/tests/ansible.cfg b/tests/ansible.cfg new file mode 100644 index 00000000..cb234805 --- /dev/null +++ b/tests/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +roles_path = ../../ + diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 00000000..df8b5f69 --- /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 00000000..cd7c4e30 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,62 @@ +--- +# 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 + roles: + - role: "{{ rolename | basename }}" + lxc_net_bridge: lxcbr0 + lxc_kernel_options: + - { key: 'fs.inotify.max_user_instances', value: 1024 } + lxc_container_caches: + - url: "https://rpc-repo.rackspace.com/container_images/rpc-trusty-container.tgz" + name: "trusty.tgz" + sha256sum: "56c6a6e132ea7d10be2f3e8104f47136ccf408b30e362133f0dc4a0a9adb4d0c" + chroot_path: trusty/rootfs-amd64 + # The $HOME directory is mocked to work with tox + # by defining the 'ansible_env' hash. This should + # NEVER be done outside of testing. + ansible_env: ## NEVER DO THIS OUTSIDE OF TESTING + HOME: "/tmp" + post_tasks: + - name: Open sysctl file + slurp: + src: /etc/sysctl.conf + register: sysctl_file + - name: Read files + set_fact: + sysctl_content: "{{ sysctl_file.content | b64decode }}" + - name: Check for container tar + stat: + path: /var/cache/lxc_trusty.tgz + register: container_tar_file + - name: Check for container cache dir + stat: + path: /var/cache/lxc/trusty/rootfs-amd64/ + register: container_cache_dir + - name: Check for lxc bridge + stat: + path: /sys/class/net/lxcbr0/bridge/bridge_id + register: lxc_bridge_file + - name: Check dnsmasq is running + shell: ps auxfww | grep -w 'dnsmasq -u lxc-dnsmasq' + - name: Check role functions + assert: + that: + - "'fs.inotify.max_user_instances' in sysctl_content" + - "lxc_bridge_file.stat.exists" + - "container_cache_dir.stat.isdir" + - "container_tar_file.stat.exists" diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..6d3d2aa3 --- /dev/null +++ b/tox.ini @@ -0,0 +1,97 @@ +[tox] +minversion = 1.6 +skipsdist = True +envlist = docs,pep8,bashate,ansible-syntax,ansible-lint + +[testenv] +usedevelop = True +install_command = pip install -U {opts} {packages} +setenv = VIRTUAL_ENV={envdir} +deps = -r{toxinidir}/dev-requirements.txt +commands = + /usr/bin/find . -type f -name "*.pyc" -delete + ansible-galaxy install \ + --role-file=ansible-role-requirements.yml \ + --ignore-errors \ + --force + +[testenv:docs] +commands = python setup.py build_sphinx + +# environment used by the -infra templated docs job +[testenv:venv] +deps = -r{toxinidir}/dev-requirements.txt +commands = {posargs} + +# Run hacking/flake8 check for all python files +[testenv:pep8] +deps = flake8 +whitelist_externals = bash +commands = + bash -c "grep -Irl \ + -e '!/usr/bin/env python' \ + -e '!/bin/python' \ + -e '!/usr/bin/python' \ + --exclude-dir '.*' \ + --exclude-dir 'doc' \ + --exclude-dir '*.egg' \ + --exclude-dir '*.egg-info' \ + --exclude 'tox.ini' \ + --exclude '*.sh' \ + {toxinidir} | xargs flake8 --verbose" + +[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 +# H303 No wildcard (*) import. +ignore=F403,H303 + +# Run bashate check for all bash scripts +# Ignores the following rules: +# E003: Indent not multiple of 4 (we prefer to use multiples of 2) +[testenv:bashate] +deps = bashate +whitelist_externals = bash +commands = + bash -c "grep -Irl \ + -e '!/usr/bin/env bash' \ + -e '!/bin/bash' \ + -e '!/bin/sh' \ + --exclude-dir '.*' \ + --exclude-dir '*.egg' \ + --exclude-dir '*.egg-info' \ + --exclude 'tox.ini' \ + {toxinidir} | xargs bashate --verbose --ignore=E003" + +[testenv:ansible-syntax] +changedir = tests +commands = + ansible-galaxy install \ + --role-file=ansible-role-requirements.yml \ + --ignore-errors \ + --force + ansible-playbook -i inventory \ + --syntax-check \ + --list-tasks \ + -e "rolename={toxinidir}" \ + test.yml + +[testenv:ansible-lint] +changedir = tests +commands = + ansible-galaxy install \ + --role-file=ansible-role-requirements.yml \ + --ignore-errors \ + --force + ansible-lint test.yml + +[testenv:ansible-functional] +changedir = tests +commands = + ansible-galaxy install \ + --role-file=ansible-role-requirements.yml \ + --ignore-errors \ + --force + ansible-playbook -i inventory \ + -e "rolename={toxinidir}" \ + test.yml