Update role to gate using all supported distros
The changes here remove the boiler plate code we had in favor of using all of our common roles. This also updates the nspawn role using some of the learnings we've had from our recent LXC changes and ensures we're not breaking any compatibility we had with our various distros. Add option to run a full config update if required > As a deployer I need the ability to make a sweeping change to container configs if required. At present the nspawn container create role will attempt to preserve the configs and update only what's required, which is desirable when maintaining uptime. This change provides the option `nspawn_container_preserve_config` which, if set to "false" will template the container configs instead of trying to preserve it. Document everything in config Change-Id: Ie969c10578e1102767ad8991c9d6171b547aef87 Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
This commit is contained in:
parent
4cd14f883d
commit
32f3ffdcbc
@ -13,25 +13,13 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
container_domain: "openstack.local"
|
# === systemd-nspawn defaults ==================================================
|
||||||
|
# Default networks that will be applied ONLY to nspwan deployments.
|
||||||
container_default_bind_mounts: []
|
|
||||||
container_bind_mounts: []
|
|
||||||
|
|
||||||
container_config_overrides: {}
|
|
||||||
|
|
||||||
container_network_config_overrides: {}
|
|
||||||
|
|
||||||
container_image: "{{ nspawn_map['distro'] }}-{{ nspawn_map['release'] }}-{{ nspawn_map['arch'] }}"
|
|
||||||
|
|
||||||
nspawn_networks:
|
nspawn_networks:
|
||||||
nspawn_address:
|
nspawn_address:
|
||||||
# The name of the interface, by default this is a dummy device on a private
|
|
||||||
# network however it could be a bridge or any other interface.
|
|
||||||
bridge: "nspawn0"
|
bridge: "nspawn0"
|
||||||
# Optional | Set bool to enable a private device. This will create a bridge
|
interface: "mv-mv-nspawn0"
|
||||||
# not connecting to the underlying L2.
|
address: dhcp
|
||||||
private_device: true
|
|
||||||
|
|
||||||
# This is a list of items that will be passed into the container as READ-ONLY
|
# This is a list of items that will be passed into the container as READ-ONLY
|
||||||
# files or directories. If any of these items are passed into the container
|
# files or directories. If any of these items are passed into the container
|
||||||
@ -39,10 +27,86 @@ nspawn_networks:
|
|||||||
# contianer prior to writting the config.
|
# contianer prior to writting the config.
|
||||||
# nspawn_read_only_host_bindmount:
|
# nspawn_read_only_host_bindmount:
|
||||||
# - { source: /etc/resolv.conf, dest: /etc/resolv.conf }
|
# - { source: /etc/resolv.conf, dest: /etc/resolv.conf }
|
||||||
nspawn_read_only_host_bindmount: []
|
nspawn_read_only_host_bindmount: "{{ _nspawn_read_only_host_bindmount | default([]) }}"
|
||||||
|
|
||||||
# This is a list of items that will be passed into the container as a shared
|
# This is a list of items that will be passed into the container as a shared
|
||||||
# bind mount. If any of these items are passed into the container.
|
# bind mount. If any of these items are passed into the container.
|
||||||
# nspawn_shared_host_bindmount:
|
# nspawn_shared_host_bindmount:
|
||||||
# - /etc/apt
|
# - /etc/apt
|
||||||
nspawn_shared_host_bindmount: []
|
nspawn_shared_host_bindmount: "{{ _nspawn_shared_host_bindmount | default([]) }}"
|
||||||
|
|
||||||
|
# Defined CPU architecture map
|
||||||
|
nspawn_architecture_mapping:
|
||||||
|
x86_64: amd64
|
||||||
|
ppc64le: ppc64el
|
||||||
|
s390x: s390x
|
||||||
|
armv7l: armhf
|
||||||
|
|
||||||
|
# Set the cache map used when creating the container.
|
||||||
|
# nspawn_map:
|
||||||
|
# distro: "$DISTRO_NAME"
|
||||||
|
# arch: "{{ nspawn_architecture_mapping[container_architecture] }}"
|
||||||
|
# release: "{{ hostvars[physical_host]['ansible_distribution_version'] }}"
|
||||||
|
nspawn_map: "{{ _nspawn_map | default({}) }}"
|
||||||
|
|
||||||
|
# Enable or Disable the use of systemd-resolved. Option is Boolean.
|
||||||
|
nspawn_container_enable_resolved: "{{ _nspawn_container_enable_resolved | default(true) }}"
|
||||||
|
|
||||||
|
# Enable or Disable config preservation. If this is disabled a new configuration
|
||||||
|
# file for the systemd container will be created, even if the container already
|
||||||
|
# exists. When this is set to "false" the container will be restarted should the
|
||||||
|
# configuration task(s) result in change.
|
||||||
|
nspawn_container_preserve_config: true
|
||||||
|
|
||||||
|
# Enable or Disable the BTRFS quota system for the "/var/lib/machines" mount
|
||||||
|
# point. More information on the BTRFS quota system can be found here:
|
||||||
|
# * https://btrfs.wiki.kernel.org/index.php/Quota_support
|
||||||
|
nspawn_host_machine_quota_disabled: false
|
||||||
|
|
||||||
|
# Set the default qgroup limits used for file system quotas. The default is
|
||||||
|
# "none". See the following documentation for more information:
|
||||||
|
# * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-qgroup
|
||||||
|
nspawn_host_qgroup_space_limit: none
|
||||||
|
nspawn_host_qgroup_compression_limit: none
|
||||||
|
|
||||||
|
|
||||||
|
# === General container defaults ===============================================
|
||||||
|
# NOTE(cloudnull): These are host specific variables we capture up-front. These
|
||||||
|
# psuedo variables are used to capture the container host
|
||||||
|
# information but could be overriden to deploy whatever.
|
||||||
|
container_host: "{{ hostvars[inventory_hostname]['physical_host'] | default('localhost') }}"
|
||||||
|
container_architecture: "{{ hostvars[container_host]['ansible_architecture'] | lower }}"
|
||||||
|
|
||||||
|
# Name of the on-disk image to use for deployment.
|
||||||
|
container_image: "{{ nspawn_map['distro'] }}-{{ nspawn_map['release'] }}-{{ nspawn_map['arch'] }}"
|
||||||
|
|
||||||
|
# The domain the containers will exist within.
|
||||||
|
container_domain: "openstack.local"
|
||||||
|
|
||||||
|
# Container Default bind mounts. This option will be merged with the container
|
||||||
|
# bind mounts. This option takes a list of files on a host that will be mounted
|
||||||
|
# at the exact same path within the container.
|
||||||
|
container_default_bind_mounts: []
|
||||||
|
|
||||||
|
# Container bind mounts. This option takes a list of files on a host that will
|
||||||
|
# be mounted at the exact same path within the container.
|
||||||
|
container_bind_mounts: []
|
||||||
|
|
||||||
|
# option used to specific specific container config values which will be
|
||||||
|
# directly injected into the container service or nspawn config file. This
|
||||||
|
# option take Key=Value pairs and can be used to set any desired config options
|
||||||
|
# in any section. Review the following link for more details:
|
||||||
|
# * https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html
|
||||||
|
container_config_overrides: {}
|
||||||
|
|
||||||
|
# Default networks that will be applied ALL containerized deployments.
|
||||||
|
# container_networks:
|
||||||
|
# management_address:
|
||||||
|
# address: "{{ ansible_host | default('localhost') }}"
|
||||||
|
# netmask: "255.255.255.0"
|
||||||
|
# bridge: "br-mgmt"
|
||||||
|
# static_routes:
|
||||||
|
# - cidr: 172.29.100.0/24
|
||||||
|
# gateway: 172.29.100.100
|
||||||
|
|
||||||
|
container_networks: {}
|
||||||
|
@ -13,39 +13,19 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
- name: Wait for container connectivity
|
|
||||||
wait_for_connection:
|
|
||||||
delay: 3
|
|
||||||
timeout: 60
|
|
||||||
listen: check connection
|
|
||||||
|
|
||||||
- name: Gather facts for new container(s)
|
- name: Gather facts for new container(s)
|
||||||
setup:
|
setup:
|
||||||
gather_subset: "!all"
|
gather_subset: "!all"
|
||||||
listen: check connection
|
listen: check connection
|
||||||
|
|
||||||
- name: Ensure dbus is installed
|
|
||||||
package:
|
|
||||||
name: "{{ nspawn_dbus_package }}"
|
|
||||||
state: present
|
|
||||||
update_cache: "{{ ansible_pkg_mgr in ['apt', 'zypper'] }}"
|
|
||||||
register: dbus_install
|
|
||||||
retries: 5
|
|
||||||
delay: 3
|
|
||||||
until: dbus_install | success
|
|
||||||
listen: check connection
|
|
||||||
|
|
||||||
- name: Restart new container (first boot only)
|
- name: Restart new container (first boot only)
|
||||||
systemd:
|
systemd:
|
||||||
name: "systemd-nspawn@{{ systemd_escape.stdout }}"
|
name: "systemd-nspawn@{{ systemd_escape.stdout }}"
|
||||||
state: "restarted"
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
register: machinectl_first_boot
|
register: machinectl_first_boot
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 2
|
delay: 2
|
||||||
until: machinectl_first_boot | success
|
until: machinectl_first_boot | success
|
||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
when:
|
|
||||||
- machinectl_container_image_status.rc != 0
|
|
||||||
notify:
|
|
||||||
- check connection
|
|
||||||
listen: Container first boot
|
listen: Container first boot
|
||||||
|
@ -33,4 +33,5 @@ galaxy_info:
|
|||||||
- python
|
- python
|
||||||
- development
|
- development
|
||||||
- openstack
|
- openstack
|
||||||
dependencies: []
|
dependencies:
|
||||||
|
- plugins
|
||||||
|
283
tasks/main.yml
283
tasks/main.yml
@ -77,17 +77,57 @@
|
|||||||
when:
|
when:
|
||||||
- machinectl_image_status.rc != 0
|
- machinectl_image_status.rc != 0
|
||||||
|
|
||||||
|
- name: Locate nspawn config
|
||||||
|
stat:
|
||||||
|
path: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
||||||
|
register: nspawn_config_exists
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
when:
|
||||||
|
- nspawn_systemd_version | int > 219
|
||||||
|
|
||||||
|
- name: Slurp existing nspawn config
|
||||||
|
slurp:
|
||||||
|
src: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
||||||
|
register: nspawn_config
|
||||||
|
changed_when: false
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
when:
|
||||||
|
- nspawn_container_preserve_config | bool
|
||||||
|
- nspawn_systemd_version | int > 219
|
||||||
|
- nspawn_config_exists.stat.exists | bool
|
||||||
|
|
||||||
- name: Clone the base container image
|
- name: Clone the base container image
|
||||||
command: machinectl clone "{{ container_image }}" "{{ inventory_hostname }}"
|
command: machinectl clone "{{ container_image }}" "{{ inventory_hostname }}"
|
||||||
when:
|
when:
|
||||||
- machinectl_container_image_status.rc != 0
|
- machinectl_container_image_status.rc != 0
|
||||||
register: machinectl_container_clone
|
register: machinectl_container_clone
|
||||||
retries: 5
|
retries: 3
|
||||||
delay: 2
|
delay: 2
|
||||||
until: machinectl_container_clone | success
|
until: machinectl_container_clone is success
|
||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
notify:
|
notify:
|
||||||
- Container first boot
|
- Container first boot
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Set the qgroup limits
|
||||||
|
block:
|
||||||
|
- name: Set the qgroup size|compression limits on machines
|
||||||
|
command: "btrfs qgroup limit {{ item }} /var/lib/machines/{{ inventory_hostname }}"
|
||||||
|
changed_when: false
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
with_items:
|
||||||
|
- "-e {{ nspawn_host_qgroup_space_limit }}"
|
||||||
|
- "-c {{ nspawn_host_qgroup_compression_limit }}"
|
||||||
|
when:
|
||||||
|
- not nspawn_host_machine_quota_disabled
|
||||||
|
rescue:
|
||||||
|
- name: Notice regarding quota system
|
||||||
|
debug:
|
||||||
|
msg: >-
|
||||||
|
There was an error processing the setup of qgroups. Check the system
|
||||||
|
to ensure they're available otherwise disable the quota system by
|
||||||
|
setting `nspawn_host_machine_quota_disabled` to true.
|
||||||
|
|
||||||
- name: Container directories
|
- name: Container directories
|
||||||
file:
|
file:
|
||||||
@ -99,6 +139,7 @@
|
|||||||
- "/openstack/log/{{ inventory_hostname }}"
|
- "/openstack/log/{{ inventory_hostname }}"
|
||||||
- "/var/lib/machines/{{ inventory_hostname }}/etc/systemd/network"
|
- "/var/lib/machines/{{ inventory_hostname }}/etc/systemd/network"
|
||||||
- "/var/lib/machines/{{ inventory_hostname }}/etc/systemd/nspawn"
|
- "/var/lib/machines/{{ inventory_hostname }}/etc/systemd/nspawn"
|
||||||
|
- "/var/lib/machines/{{ inventory_hostname }}/var/lib/dbus"
|
||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
|
|
||||||
- name: Container RO bind path cleanup
|
- name: Container RO bind path cleanup
|
||||||
@ -127,56 +168,41 @@
|
|||||||
# Check for the existance of an nspawn configuration file. If found slurp it up
|
# Check for the existance of an nspawn configuration file. If found slurp it up
|
||||||
# and use it as the base nspawn config file with the option to config template
|
# and use it as the base nspawn config file with the option to config template
|
||||||
# override.
|
# override.
|
||||||
- name: Locate nspawn config
|
- name: modern systemd block
|
||||||
stat:
|
block:
|
||||||
path: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
- name: Copy container config (new)
|
||||||
register: nspawn_config_exists
|
config_template:
|
||||||
delegate_to: "{{ physical_host }}"
|
content: "{{ nspawn_config.content | b64decode }}"
|
||||||
when:
|
dest: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
||||||
- nspawn_systemd_version | int > 219
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
config_overrides: "{{ container_config_overrides | default({}) }}"
|
||||||
|
config_type: "ini"
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
when:
|
||||||
|
- nspawn_container_preserve_config | bool
|
||||||
|
- nspawn_config_exists.stat.exists | bool
|
||||||
|
|
||||||
- name: slurp existing nspawn config
|
# If no nspawn configuration file exists, create a new config file using the
|
||||||
slurp:
|
# default template.
|
||||||
src: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
- name: Copy container config (new)
|
||||||
register: nspawn_config
|
config_template:
|
||||||
changed_when: false
|
src: templates/container_config.nspawn.j2
|
||||||
delegate_to: "{{ physical_host }}"
|
dest: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
config_overrides: "{{ container_config_overrides | default({}) }}"
|
||||||
|
config_type: "ini"
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
when:
|
||||||
|
- not nspawn_container_preserve_config | bool or
|
||||||
|
not nspawn_config_exists.stat.exists | bool
|
||||||
|
notify:
|
||||||
|
- Container first boot
|
||||||
when:
|
when:
|
||||||
- nspawn_systemd_version | int > 219
|
- nspawn_systemd_version | int > 219
|
||||||
- nspawn_config_exists.stat is defined
|
|
||||||
- nspawn_config_exists.stat.exists | bool
|
|
||||||
|
|
||||||
- name: Copy container config (new)
|
|
||||||
config_template:
|
|
||||||
content: "{{ nspawn_config.content | b64decode }}"
|
|
||||||
dest: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
|
||||||
owner: "root"
|
|
||||||
group: "root"
|
|
||||||
mode: "0644"
|
|
||||||
config_overrides: "{{ container_config_overrides | default({}) }}"
|
|
||||||
config_type: "ini"
|
|
||||||
delegate_to: "{{ physical_host }}"
|
|
||||||
when:
|
|
||||||
- nspawn_systemd_version | int > 219
|
|
||||||
- nspawn_config_exists.stat is defined
|
|
||||||
- nspawn_config_exists.stat.exists | bool
|
|
||||||
|
|
||||||
# If no nspawn configuration file exists, create a new config file using the
|
|
||||||
# default template.
|
|
||||||
- name: Copy container config (new)
|
|
||||||
config_template:
|
|
||||||
src: templates/container_config.nspawn.j2
|
|
||||||
dest: "/etc/systemd/nspawn/{{ inventory_hostname }}.nspawn"
|
|
||||||
owner: "root"
|
|
||||||
group: "root"
|
|
||||||
mode: "0644"
|
|
||||||
config_overrides: "{{ container_config_overrides | default({}) }}"
|
|
||||||
config_type: "ini"
|
|
||||||
delegate_to: "{{ physical_host }}"
|
|
||||||
when:
|
|
||||||
- nspawn_systemd_version | int > 219
|
|
||||||
- nspawn_config_exists.stat is defined
|
|
||||||
- not nspawn_config_exists.stat.exists | bool
|
|
||||||
|
|
||||||
- name: Copy container config (old)
|
- name: Copy container config (old)
|
||||||
template:
|
template:
|
||||||
@ -189,59 +215,20 @@
|
|||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
when:
|
when:
|
||||||
- nspawn_systemd_version | int < 220
|
- nspawn_systemd_version | int < 220
|
||||||
|
notify:
|
||||||
- name: Copy container interface config
|
- Container first boot
|
||||||
config_template:
|
|
||||||
src: container_mv.network.j2
|
|
||||||
dest: "/var/lib/machines/{{ inventory_hostname }}/etc/systemd/network/mv-mv-{{ item.key }}.network"
|
|
||||||
owner: "root"
|
|
||||||
group: "root"
|
|
||||||
mode: "0644"
|
|
||||||
config_overrides: "{{ container_network_config_overrides | default({}) }}"
|
|
||||||
config_type: "ini"
|
|
||||||
with_dict: "{{ container_networks | combine(nspawn_networks) }}"
|
|
||||||
delegate_to: "{{ physical_host }}"
|
|
||||||
|
|
||||||
- name: Create localhost config
|
|
||||||
lineinfile:
|
|
||||||
dest: "/var/lib/machines/{{ inventory_hostname }}/etc/hosts"
|
|
||||||
regexp: "^127.0.0.1"
|
|
||||||
line: "127.0.0.1 localhost"
|
|
||||||
owner: "root"
|
|
||||||
group: "root"
|
|
||||||
mode: "0644"
|
|
||||||
remote_user: root
|
|
||||||
delegate_to: "{{ physical_host }}"
|
|
||||||
|
|
||||||
- name: Create domain config
|
|
||||||
lineinfile:
|
|
||||||
dest: "/var/lib/machines/{{ inventory_hostname }}/etc/hosts"
|
|
||||||
regexp: "^127.0.1.1"
|
|
||||||
line: "127.0.1.1 {{ inventory_hostname | replace('_', '-') }}.{{ container_domain }} {{ inventory_hostname | replace('_', '-') }}"
|
|
||||||
owner: "root"
|
|
||||||
group: "root"
|
|
||||||
mode: "0644"
|
|
||||||
remote_user: root
|
|
||||||
delegate_to: "{{ physical_host }}"
|
|
||||||
|
|
||||||
- name: Create hostname
|
|
||||||
copy:
|
|
||||||
dest: "/var/lib/machines/{{ inventory_hostname }}/etc/hostname"
|
|
||||||
content: |
|
|
||||||
{{ inventory_hostname | replace('_', '-') }}
|
|
||||||
owner: "root"
|
|
||||||
group: "root"
|
|
||||||
mode: "0644"
|
|
||||||
remote_user: root
|
|
||||||
delegate_to: "{{ physical_host }}"
|
|
||||||
|
|
||||||
- name: Generate machine-id
|
- name: Generate machine-id
|
||||||
command: "systemd-machine-id-setup --root=/var/lib/machines/{{ inventory_hostname }}"
|
command: "systemd-machine-id-setup --root=/var/lib/machines/{{ inventory_hostname }}"
|
||||||
args:
|
args:
|
||||||
creates: "/var/lib/machines/{{ inventory_hostname }}/etc/machine-id"
|
creates: "/var/lib/machines/{{ inventory_hostname }}/etc/machine-id"
|
||||||
|
register: machineid_set
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
until: machineid_set is success
|
||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
notify:
|
tags:
|
||||||
- Container first boot
|
- skip_ansible_lint
|
||||||
|
|
||||||
- name: Create dbus machine-id
|
- name: Create dbus machine-id
|
||||||
copy:
|
copy:
|
||||||
@ -252,7 +239,7 @@
|
|||||||
remote_user: root
|
remote_user: root
|
||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
|
|
||||||
- name: Start (enable) new container
|
- name: Start new container (enable)
|
||||||
systemd:
|
systemd:
|
||||||
daemon_reload: yes
|
daemon_reload: yes
|
||||||
name: "systemd-nspawn@{{ systemd_escape.stdout }}"
|
name: "systemd-nspawn@{{ systemd_escape.stdout }}"
|
||||||
@ -261,18 +248,108 @@
|
|||||||
register: machinectl_start
|
register: machinectl_start
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 2
|
delay: 2
|
||||||
until: machinectl_start | success
|
until: machinectl_start is success
|
||||||
delegate_to: "{{ physical_host }}"
|
delegate_to: "{{ physical_host }}"
|
||||||
notify:
|
notify:
|
||||||
- check connection
|
- check connection
|
||||||
|
|
||||||
- name: Restart networkd
|
- name: Generate hostname
|
||||||
service:
|
command: >-
|
||||||
name: systemd-networkd
|
hostnamectl --machine="{{ inventory_hostname }}" {{ item }} --pretty --static --transient
|
||||||
state: restarted
|
with_items:
|
||||||
enabled: true
|
- "set-hostname {{ inventory_hostname | replace('_', '-') }}.{{ container_domain }}"
|
||||||
|
- "set-location {{ physical_host }}"
|
||||||
|
- "set-chassis container"
|
||||||
|
- "set-deployment {{ container_domain }}"
|
||||||
|
- "set-icon-name container"
|
||||||
|
register: hostnamectl_set
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
until: hostnamectl_set is success
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
# This point the container is running. Delegation should no longer be required.
|
||||||
|
# ==============================================================================
|
||||||
- name: Create journal directory
|
- name: Create journal directory
|
||||||
file:
|
file:
|
||||||
path: "/var/log/journal"
|
path: "/var/log/journal"
|
||||||
state: "directory"
|
state: "directory"
|
||||||
|
|
||||||
|
- name: Run the systemd-networkd role
|
||||||
|
include_role:
|
||||||
|
name: systemd_networkd
|
||||||
|
private: true
|
||||||
|
vars:
|
||||||
|
systemd_interface_cleanup: false
|
||||||
|
systemd_run_networkd: true
|
||||||
|
systemd_resolved_available: "{{ nspawn_container_enable_resolved }}"
|
||||||
|
systemd_resolved:
|
||||||
|
DNS: "{{ hostvars[physical_host]['ansible_mv_' + nspawn_networks['nspawn_address']['bridge']]['ipv4']['address'] }}"
|
||||||
|
Domains: "{{ container_domain }}"
|
||||||
|
systemd_networks: |-
|
||||||
|
{% set _networks = [] %}
|
||||||
|
{% for _, value in (container_networks | combine(nspawn_networks)).items() %}
|
||||||
|
{% set _network = {'interface': value.interface | default('mv-mv-' + value.bridge.split('br-')[-1])} %}
|
||||||
|
{% if value.address is defined %}
|
||||||
|
{% set _ = _network.__setitem__('address', value.address) %}
|
||||||
|
{% if (value.netmask is defined) and (_network.address != 'dhcp') %}
|
||||||
|
{% set _ = _network.__setitem__('netmask', value.netmask) %}
|
||||||
|
{% set prefix = (value.address + '/' + value.netmask) | ipaddr('prefix') %}
|
||||||
|
{% set _ = _network.__setitem__('address', [value.address + '/' + prefix | string]) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% set _ = _network.__setitem__('usedns', (value.usedns | default(true) | bool) | ternary('yes', 'no')) %}
|
||||||
|
{% set _ = _network.__setitem__('static_routes', value.static_routes | default([])) %}
|
||||||
|
{% if value.gateway is defined %}
|
||||||
|
{% set _ = _network.__setitem__('gateway', value.gateway) %}
|
||||||
|
{% endif %}
|
||||||
|
{% set _ = _network.__setitem__('mtu', value.mtu | default(1500 | string)) %}
|
||||||
|
{% set _ = _networks.append(_network) %}
|
||||||
|
{% endfor %}
|
||||||
|
{{ _networks | sort(attribute='interface') }}
|
||||||
|
tags:
|
||||||
|
- network-config
|
||||||
|
|
||||||
|
- name: Create resolved link
|
||||||
|
file:
|
||||||
|
src: "/var/run/systemd/resolve/resolv.conf"
|
||||||
|
dest: "/etc/resolv.conf"
|
||||||
|
force: true
|
||||||
|
state: link
|
||||||
|
when:
|
||||||
|
- nspawn_container_enable_resolved | bool
|
||||||
|
|
||||||
|
# Some distros do not have access to systemd-resolved. If the option
|
||||||
|
# `nspawn_container_enable_resolved` is disabled this will ensure functionality
|
||||||
|
# in the absence of modern systemd.
|
||||||
|
- name: Legacy resolvers
|
||||||
|
block:
|
||||||
|
- name: Check resolv.conf
|
||||||
|
stat:
|
||||||
|
path: "/etc/resolv.conf"
|
||||||
|
register: nspawn_resolv_conf
|
||||||
|
|
||||||
|
- name: Remove resolv.conf link
|
||||||
|
file:
|
||||||
|
path: "/etc/resolv.conf"
|
||||||
|
state: absent
|
||||||
|
when:
|
||||||
|
- nspawn_resolv_conf.stat.islnk is defined and
|
||||||
|
nspawn_resolv_conf.stat.islnk
|
||||||
|
|
||||||
|
- name: Place resolv.conf
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
nameserver {{ hostvars[physical_host]['ansible_mv_' + nspawn_networks['nspawn_address']['bridge']]['ipv4']['address'] }}
|
||||||
|
search {{ container_domain }}
|
||||||
|
dest: "/etc/resolv.conf"
|
||||||
|
when:
|
||||||
|
- not nspawn_container_enable_resolved | bool
|
||||||
|
|
||||||
|
- name: Force all notified handlers now
|
||||||
|
meta: flush_handlers
|
||||||
|
|
||||||
|
- name: (RE)Gather facts post setup
|
||||||
|
setup: {}
|
||||||
|
@ -27,11 +27,8 @@ Bind={{ bind }}:{{ bind }}
|
|||||||
{% set _ = container_networks.update(nspawn_networks) %}
|
{% set _ = container_networks.update(nspawn_networks) %}
|
||||||
{% for key, value in container_networks.items() %}
|
{% for key, value in container_networks.items() %}
|
||||||
{% if value.bridge is defined %}
|
{% if value.bridge is defined %}
|
||||||
{% set macvlan = 'mv-' + value.bridge.split('br-')[-1] %}
|
{% set _ = macvlans.append('mv-' + value.bridge.split('br-')[-1]) %}
|
||||||
{% else %}
|
|
||||||
{% set macvlan = 'mv-' + key %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% set _ = macvlans.append(macvlan) %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if macvlans | length > 0 %}
|
{% if macvlans | length > 0 %}
|
||||||
Private=yes
|
Private=yes
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
# {{ ansible_managed }}
|
|
||||||
|
|
||||||
[Match]
|
|
||||||
{% if item.value.bridge is defined %}
|
|
||||||
Name=mv-mv-{{ item.value.bridge.split('br-')[-1] }}
|
|
||||||
{% else %}
|
|
||||||
Name=mv-mv-{{ item.key }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% 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 }}
|
|
||||||
{% else %}
|
|
||||||
[DHCP]
|
|
||||||
UseDNS=yes
|
|
||||||
UseNTP=yes
|
|
||||||
RouteMetric=20
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if item.value.static_routes is defined %}
|
|
||||||
[Route]
|
|
||||||
{% for route in item.value.static_routes %}
|
|
||||||
Source={{ route['cidr'] }}
|
|
||||||
Gateway={{ route['gateway'] }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
[Network]
|
|
||||||
{% if item.value.address is defined %}
|
|
||||||
{% set addr_cidr = (item.value.address | string + '/' + item.value.netmask | string) | ipaddr('prefix') %}
|
|
||||||
Address={{ item.value.address }}/{{ addr_cidr }}
|
|
||||||
{% else %}
|
|
||||||
DHCP=yes
|
|
||||||
{% endif %}
|
|
||||||
{% if item.value.gateway is defined %}
|
|
||||||
Gateway={{ item.value.gateway }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
[Link]
|
|
||||||
{% if item.value.mtu is defined %}
|
|
||||||
MTUBytes={{ item.value.mtu }}
|
|
||||||
{% endif %}
|
|
||||||
ARP=yes
|
|
@ -10,7 +10,11 @@
|
|||||||
src: https://git.openstack.org/openstack/openstack-ansible-openstack_hosts
|
src: https://git.openstack.org/openstack/openstack-ansible-openstack_hosts
|
||||||
scm: git
|
scm: git
|
||||||
version: master
|
version: master
|
||||||
- name: lxc_hosts
|
- name: nspawn_hosts
|
||||||
src: https://git.openstack.org/openstack/openstack-ansible-lxc_hosts
|
src: https://git.openstack.org/openstack/openstack-ansible-nspawn_hosts
|
||||||
|
scm: git
|
||||||
|
version: master
|
||||||
|
- name: plugins
|
||||||
|
src: https://git.openstack.org/openstack/openstack-ansible-plugins
|
||||||
scm: git
|
scm: git
|
||||||
version: master
|
version: master
|
||||||
|
@ -13,13 +13,16 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
- name: Gather nspawn container host facts
|
container_networks:
|
||||||
hosts: "localhost"
|
management_address:
|
||||||
gather_facts: true
|
address: "{{ ansible_host | default('localhost') }}"
|
||||||
|
netmask: "255.255.255.0"
|
||||||
|
bridge: "br-mgmt"
|
||||||
|
static_routes:
|
||||||
|
- cidr: 172.29.100.0/24
|
||||||
|
gateway: 172.29.100.100
|
||||||
|
|
||||||
- name: Create container(s)
|
bridges:
|
||||||
hosts: "{{ container_group|default('all_containers') }}"
|
- name: "br-mgmt"
|
||||||
gather_facts: false
|
ip_addr: "172.29.100.100"
|
||||||
user: root
|
netmask: "255.255.255.0"
|
||||||
roles:
|
|
||||||
- role: "nspawn_container_create"
|
|
@ -15,19 +15,8 @@
|
|||||||
|
|
||||||
container_name: "{{ inventory_hostname }}"
|
container_name: "{{ inventory_hostname }}"
|
||||||
|
|
||||||
container_networks:
|
|
||||||
management_address:
|
|
||||||
address: "{{ ansible_host }}"
|
|
||||||
bridge: "br-mgmt"
|
|
||||||
interface: "eth1"
|
|
||||||
netmask: "255.255.252.0"
|
|
||||||
type: "veth"
|
|
||||||
static_routes:
|
|
||||||
- cidr: 10.100.100.0/24
|
|
||||||
gateway: 10.100.100.1
|
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
service_name: "{{ inventory_hostname }}"
|
service_name: "{{ inventory_hostname }}"
|
||||||
|
|
||||||
global_environment_variables:
|
deployment_environment_variables:
|
||||||
foo: "bar"
|
foo: bar
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
---
|
---
|
||||||
ansible_host: 10.100.100.2
|
ansible_host: 172.29.100.101
|
||||||
ansible_become: True
|
ansible_become: True
|
||||||
ansible_user: root
|
ansible_user: root
|
||||||
|
|
||||||
physical_host: localhost
|
physical_host: localhost
|
||||||
|
|
||||||
|
container_tech: nspawn
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
---
|
---
|
||||||
ansible_host: 10.100.100.3
|
ansible_host: 172.29.100.102
|
||||||
ansible_become: True
|
ansible_become: True
|
||||||
ansible_user: root
|
ansible_user: root
|
||||||
|
|
||||||
physical_host: localhost
|
physical_host: localhost
|
||||||
|
|
||||||
|
container_tech: nspawn
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
---
|
---
|
||||||
ansible_host: 10.100.100.4
|
ansible_host: 172.29.100.103
|
||||||
ansible_become: True
|
ansible_become: True
|
||||||
ansible_user: root
|
ansible_user: root
|
||||||
|
|
||||||
physical_host: localhost
|
physical_host: localhost
|
||||||
|
|
||||||
|
container_tech: nspawn
|
||||||
|
@ -17,3 +17,5 @@ bridges:
|
|||||||
- "br-mgmt"
|
- "br-mgmt"
|
||||||
|
|
||||||
ansible_python_interpreter: "/usr/bin/python2"
|
ansible_python_interpreter: "/usr/bin/python2"
|
||||||
|
|
||||||
|
physical_host: localhost
|
||||||
|
15
tests/templates/dump-container-details.sh.j2
Normal file
15
tests/templates/dump-container-details.sh.j2
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# {{ ansible_managed }}
|
||||||
|
|
||||||
|
ip route list > /var/log/container-{{ inventory_hostname }}-routes.log
|
||||||
|
ip a list > /var/log/container-{{ inventory_hostname }}-links.log
|
||||||
|
ps auxfww > /var/log/container-{{ inventory_hostname }}-process.log
|
||||||
|
cat /etc/resolv.conf > /var/log/container-{{ inventory_hostname }}-resolvers.log
|
||||||
|
systemd-resolve --statistics > /var/log/container-{{ inventory_hostname }}-resolver-statistics.log
|
||||||
|
hostnamectl status > /var/log/container-{{ inventory_hostname }}-hostname-status.log
|
||||||
|
systemctl status nspawn* > /var/log/container-{{ inventory_hostname }}-nspawn-general-status.log
|
||||||
|
systemctl status systemd-nspawn* > /var/log/container-{{ inventory_hostname }}-nspawn-container-status.log
|
||||||
|
journalctl -u dnsmasq-mv-nspawn0 -n 1024 > /var/log/container-{{ inventory_hostname }}-nspawn-dnsmasq-mv-nspawn0.log
|
||||||
|
|
||||||
|
# This script collects details and exits. It will always return 0
|
||||||
|
true
|
41
tests/templates/test-networks.service.j2
Normal file
41
tests/templates/test-networks.service.j2
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# {{ ansible_managed }}
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=test networks service
|
||||||
|
After=syslog.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
User=root
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
{% set seen_start_interfaces = [] %}
|
||||||
|
{% for item in bridges %}
|
||||||
|
{% if item is not mapping %}
|
||||||
|
{% set item = {'name': item} %}
|
||||||
|
{% endif %}
|
||||||
|
{% if item.name not in seen_start_interfaces %}
|
||||||
|
{% set _ = seen_start_interfaces.append(item.name) %}
|
||||||
|
|
||||||
|
# Interface [{{ item.name }}]
|
||||||
|
ExecStart=-/sbin/ip link add dev "{{ item.name }}" type bridge
|
||||||
|
ExecStart=-/sbin/ip link set dev "{{ item.name }}" up
|
||||||
|
{% if item.address is defined and item.netmask is defined %}
|
||||||
|
ExecStart=-/sbin/ip address add "{{ item.address }}/{{ item.netmask }}" dev "{{ item.bridge }}"
|
||||||
|
{% endif %}
|
||||||
|
{% if item.veth_peer is defined %}
|
||||||
|
ExecStart=-/sbin/ip link add "{{ item.name }}-veth" type veth peer name "{{ item.veth_peer }}"
|
||||||
|
ExecStart=-/sbin/ip link set "{{ item.name }}-veth" up
|
||||||
|
ExecStart=-/sbin/ip link set "{{ item.veth_peer }}-veth" up
|
||||||
|
ExecStart=-/sbin/ip link set dev "{{ item.name }}-veth" master "{{ item.name }}"
|
||||||
|
ExecStop=-/sbin/ip link delete dev "{{ item.veth_peer }}-veth"
|
||||||
|
ExecStop=-/sbin/ip link delete dev "{{ item.name }}-veth"
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
ExecStop=-/sbin/ip link delete dev "{{ item.name }}"
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
87
tests/test-nspawn-containers-create.yml
Normal file
87
tests/test-nspawn-containers-create.yml
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
# 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: Gather host facts
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
|
||||||
|
- name: Create container(s)
|
||||||
|
hosts: all_containers
|
||||||
|
gather_facts: false
|
||||||
|
become: true
|
||||||
|
pre_tasks:
|
||||||
|
- name: Get container status
|
||||||
|
command: machinectl status "{{ inventory_hostname }}"
|
||||||
|
register: machinectl_container_status
|
||||||
|
failed_when: false
|
||||||
|
changed_when: false
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
|
||||||
|
- name: Get container image status
|
||||||
|
command: machinectl image-status "{{ inventory_hostname }}"
|
||||||
|
register: machinectl_container_image_status
|
||||||
|
failed_when: false
|
||||||
|
changed_when: false
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
|
||||||
|
- name: Poweroff container
|
||||||
|
command: "machinectl poweroff {{ inventory_hostname }}"
|
||||||
|
register: machinectl_poweroff
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
until: machinectl_remove is success
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
failed_when: false
|
||||||
|
when:
|
||||||
|
- machinectl_container_status.rc == 0
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Remove container
|
||||||
|
command: "machinectl remove {{ inventory_hostname }}"
|
||||||
|
register: machinectl_remove
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
until: machinectl_remove is success
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
failed_when: false
|
||||||
|
when:
|
||||||
|
- machinectl_container_image_status.rc == 0
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Container cleanup
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: "absent"
|
||||||
|
with_items:
|
||||||
|
- "/openstack/log/{{ inventory_hostname }}"
|
||||||
|
- "/openstack/{{ inventory_hostname }}"
|
||||||
|
delegate_to: "{{ physical_host }}"
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: "nspawn_container_create"
|
||||||
|
|
||||||
|
post_tasks:
|
||||||
|
- name: Create detail gathering script
|
||||||
|
template:
|
||||||
|
src: "dump-container-details.sh.j2"
|
||||||
|
dest: "/opt/dump-{{ inventory_hostname }}-details.sh"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Collect details
|
||||||
|
command: "/opt/dump-{{ inventory_hostname }}-details.sh"
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
143
tests/test-nspawn-containers.yml
Normal file
143
tests/test-nspawn-containers.yml
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
---
|
||||||
|
# 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: Test containers
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
# NOTE(cloudnull): This should be revised at a future date.
|
||||||
|
- name: Test intra cluster connectivity
|
||||||
|
command: ping -c 1 8.8.8.8
|
||||||
|
register: machinectl_ping
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
until: machinectl_ping is success
|
||||||
|
failed_when: false
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Stop container3
|
||||||
|
command: "machinectl poweroff container3"
|
||||||
|
register: container_stop
|
||||||
|
changed_when: container_stop.rc == 0
|
||||||
|
failed_when: not container_stop.rc in [0, 2]
|
||||||
|
until: container_stop.rc in [0, 2]
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Start container3
|
||||||
|
command: "machinectl start container3"
|
||||||
|
register: container_start
|
||||||
|
changed_when: container_start.rc == 0
|
||||||
|
until: container_start is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Status check container1
|
||||||
|
command: "machinectl status container1"
|
||||||
|
register: container_status
|
||||||
|
changed_when: container_status.rc == 0
|
||||||
|
until: container_status is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Clone container2
|
||||||
|
command: "machinectl clone container2 test1-container2"
|
||||||
|
register: container_clone
|
||||||
|
changed_when: container_clone.rc == 0
|
||||||
|
until: container_clone is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Show image test1-container2
|
||||||
|
command: "machinectl show-image test1-container2"
|
||||||
|
register: container_show
|
||||||
|
changed_when: container_show.rc == 0
|
||||||
|
until: container_show is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Rename image test1-container2
|
||||||
|
command: "machinectl rename test1-container2 test1"
|
||||||
|
register: container_rename
|
||||||
|
changed_when: container_rename.rc == 0
|
||||||
|
until: container_rename is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Check Status of test1 image
|
||||||
|
command: "machinectl image-status test1"
|
||||||
|
register: container_status
|
||||||
|
changed_when: container_status.rc == 0
|
||||||
|
until: container_status is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Start test1 container
|
||||||
|
command: "machinectl start test1"
|
||||||
|
register: container_start
|
||||||
|
changed_when: container_start.rc == 0
|
||||||
|
until: container_start is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Status test1 container
|
||||||
|
command: "machinectl status test1"
|
||||||
|
register: container_status
|
||||||
|
changed_when: container_status.rc == 0
|
||||||
|
until: container_status is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Poweroff test1 container
|
||||||
|
command: "machinectl poweroff test1"
|
||||||
|
register: container_poweroff
|
||||||
|
changed_when: container_poweroff.rc == 0
|
||||||
|
until: container_poweroff is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
- name: Remove test container images
|
||||||
|
command: "machinectl remove {{ item }}"
|
||||||
|
with_items:
|
||||||
|
- test1
|
||||||
|
register: container_poweroff
|
||||||
|
changed_when: container_poweroff.rc == 0
|
||||||
|
until: container_poweroff is success
|
||||||
|
retries: 3
|
||||||
|
delay: 2
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
104
tests/test-nspawn-host-setup.yml
Normal file
104
tests/test-nspawn-host-setup.yml
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
---
|
||||||
|
# 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: Setup nspawn host
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
become: true
|
||||||
|
pre_tasks:
|
||||||
|
- name: Gather facts
|
||||||
|
setup:
|
||||||
|
gather_subset: "!all"
|
||||||
|
|
||||||
|
- name: Show host facts
|
||||||
|
debug:
|
||||||
|
var: hostvars
|
||||||
|
|
||||||
|
- name: Create test network service
|
||||||
|
template:
|
||||||
|
src: "templates/test-networks.service.j2"
|
||||||
|
dest: "/etc/systemd/system/00-test-networks.service"
|
||||||
|
|
||||||
|
- name: Enable test network service
|
||||||
|
systemd:
|
||||||
|
name: "00-test-networks.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: Ensure root ssh key
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user_id | 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 }}"
|
||||||
|
|
||||||
|
- name: Ensure public ssh key is in authorized_keys
|
||||||
|
authorized_key:
|
||||||
|
user: "{{ ansible_env.USER | default('root') }}"
|
||||||
|
key: "{{ nspawn_container_ssh_key }}"
|
||||||
|
manage_dir: no
|
||||||
|
|
||||||
|
- name: Clear iptables rules
|
||||||
|
command: "{{ item }}"
|
||||||
|
with_items:
|
||||||
|
- "iptables -F"
|
||||||
|
- "iptables -X"
|
||||||
|
- "iptables -t nat -F"
|
||||||
|
- "iptables -t nat -X"
|
||||||
|
- "iptables -t mangle -F"
|
||||||
|
- "iptables -t mangle -X"
|
||||||
|
- "iptables -P INPUT ACCEPT"
|
||||||
|
- "iptables -P FORWARD ACCEPT"
|
||||||
|
- "iptables -P OUTPUT ACCEPT"
|
||||||
|
- "iptables -A POSTROUTING -t mangle -p tcp -j CHECKSUM --checksum-fill"
|
||||||
|
- "iptables -t nat -A POSTROUTING -o {{ ansible_default_ipv4.interface }} -j MASQUERADE"
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: "nspawn_hosts"
|
||||||
|
|
||||||
|
post_tasks:
|
||||||
|
- name: Create detail gathering script
|
||||||
|
template:
|
||||||
|
src: "dump-container-details.sh.j2"
|
||||||
|
dest: "/opt/dump-{{ inventory_hostname }}-details.sh"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Collect details
|
||||||
|
command: "/opt/dump-{{ inventory_hostname }}-details.sh"
|
||||||
|
tags:
|
||||||
|
- skip_ansible_lint
|
50
tests/test-user-setup.yml
Normal file
50
tests/test-user-setup.yml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
# 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: Setup user environment
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Gather facts
|
||||||
|
setup:
|
||||||
|
gather_subset: "!all"
|
||||||
|
|
||||||
|
- name: Show host facts
|
||||||
|
debug:
|
||||||
|
var: hostvars
|
||||||
|
|
||||||
|
- name: Ensure user ssh key
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user_id | 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:
|
||||||
|
user_ssh_key: "{{ _root_ssh_key['content'] | b64decode }}"
|
||||||
|
|
||||||
|
- name: Ensure public ssh key is in authorized_keys
|
||||||
|
authorized_key:
|
||||||
|
user: "root"
|
||||||
|
key: "{{ user_ssh_key }}"
|
||||||
|
manage_dir: no
|
||||||
|
become: true
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
# Copyright 2015, Rackspace US, Inc.
|
# Copyright 2018, Rackspace US, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -13,11 +13,10 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Prepare the user ssh keys
|
- import_playbook: test-user-setup.yml
|
||||||
- include: common/test-prepare-keys.yml
|
|
||||||
|
|
||||||
# Prepare the host
|
- import_playbook: test-nspawn-host-setup.yml
|
||||||
- include: common/test-prepare-host.yml
|
|
||||||
|
|
||||||
# Test container creation
|
- import_playbook: test-nspawn-containers-create.yml
|
||||||
- include: test-containers-create.yml
|
|
||||||
|
- import_playbook: test-nspawn-containers.yml
|
||||||
|
@ -13,25 +13,23 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
nspawn_map:
|
_nspawn_map:
|
||||||
distro: centos
|
distro: centos
|
||||||
arch: "{{ nspawn_architecture_mapping[ansible_container_architecture] }}"
|
arch: "{{ nspawn_architecture_mapping[container_architecture] }}"
|
||||||
release: 7
|
release: 7
|
||||||
|
|
||||||
# This is a list of items that will be passed into the container as READ-ONLY
|
# This is a list of items that will be passed into the container as READ-ONLY
|
||||||
# files or directories. If any of these items are passed into the container
|
# files or directories. If any of these items are passed into the container
|
||||||
# the container create process will ensure the file is not present within the
|
# the container create process will ensure the file is not present within the
|
||||||
# contianer prior to writting the config.
|
# contianer prior to writting the config.
|
||||||
nspawn_read_only_host_bindmount:
|
_nspawn_read_only_host_bindmount:
|
||||||
- { source: /etc/environment, dest: /etc/environment }
|
- { source: /etc/environment, dest: /etc/environment }
|
||||||
- { source: /etc/localtime, dest: /etc/localtime }
|
|
||||||
|
|
||||||
# This is a list of items that will be passed into the container as a shared
|
# This is a list of items that will be passed into the container as a shared
|
||||||
# bind mount. If any of these items are passed into the container.
|
# bind mount. If any of these items are passed into the container.
|
||||||
nspawn_shared_host_bindmount:
|
_nspawn_shared_host_bindmount:
|
||||||
- /etc/yum
|
- /etc/localtime
|
||||||
- /root
|
- /root
|
||||||
- /opt
|
- /opt
|
||||||
|
|
||||||
nspawn_dbus_package:
|
_nspawn_container_enable_resolved: true
|
||||||
- dbus
|
|
||||||
|
37
vars/suse-42.yml
Normal file
37
vars/suse-42.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
# 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_map:
|
||||||
|
distro: opensuse
|
||||||
|
arch: "{{ nspawn_architecture_mapping[container_architecture] }}"
|
||||||
|
release: "{{ hostvars[physical_host]['ansible_distribution_version'] }}"
|
||||||
|
|
||||||
|
# This is a list of items that will be passed into the container as READ-ONLY
|
||||||
|
# files or directories. If any of these items are passed into the container
|
||||||
|
# the container create process will ensure the file is not present within the
|
||||||
|
# contianer prior to writting the config.
|
||||||
|
_nspawn_read_only_host_bindmount:
|
||||||
|
- { source: /etc/environment, dest: /etc/environment }
|
||||||
|
|
||||||
|
# This is a list of items that will be passed into the container as a shared
|
||||||
|
# bind mount. If any of these items are passed into the container.
|
||||||
|
_nspawn_shared_host_bindmount:
|
||||||
|
- /etc/localtime
|
||||||
|
- /root
|
||||||
|
- /opt
|
||||||
|
|
||||||
|
# This version of SUSE does not have access to systemd-resolved. This will need
|
||||||
|
# to remained disabled until it does.
|
||||||
|
_nspawn_container_enable_resolved: false
|
@ -13,25 +13,23 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
nspawn_map:
|
_nspawn_map:
|
||||||
distro: ubuntu
|
distro: ubuntu
|
||||||
arch: "{{ nspawn_architecture_mapping[ansible_container_architecture] }}"
|
arch: "{{ nspawn_architecture_mapping[container_architecture] }}"
|
||||||
release: xenial
|
release: xenial
|
||||||
|
|
||||||
# This is a list of items that will be passed into the container as READ-ONLY
|
# This is a list of items that will be passed into the container as READ-ONLY
|
||||||
# files or directories. If any of these items are passed into the container
|
# files or directories. If any of these items are passed into the container
|
||||||
# the container create process will ensure the file is not present within the
|
# the container create process will ensure the file is not present within the
|
||||||
# contianer prior to writting the config.
|
# contianer prior to writting the config.
|
||||||
nspawn_read_only_host_bindmount:
|
_nspawn_read_only_host_bindmount:
|
||||||
- { source: /etc/environment, dest: /etc/environment }
|
- { source: /etc/environment, dest: /etc/environment }
|
||||||
- { source: /etc/localtime, dest: /etc/localtime }
|
|
||||||
|
|
||||||
# This is a list of items that will be passed into the container as a shared
|
# This is a list of items that will be passed into the container as a shared
|
||||||
# bind mount. If any of these items are passed into the container.
|
# bind mount. If any of these items are passed into the container.
|
||||||
nspawn_shared_host_bindmount:
|
_nspawn_shared_host_bindmount:
|
||||||
- /etc/apt
|
- /etc/localtime
|
||||||
- /root
|
- /root
|
||||||
- /opt
|
- /opt
|
||||||
|
|
||||||
nspawn_dbus_package:
|
_nspawn_container_enable_resolved: true
|
||||||
- dbus
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
# Copyright 2018, Rackspace US, Inc.
|
# Copyright 2017, Rackspace US, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -13,14 +13,17 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# NOTE(cloudnull): These are host specific variables we capture up-front. This
|
- job:
|
||||||
# These psuedo variables are used to capture the container host
|
name: openstack-ansible-nspawn-ubuntu-xenial
|
||||||
# information.
|
parent: openstack-ansible-functional
|
||||||
ansible_container_host: "{{ hostvars[inventory_hostname]['physical_host'] }}"
|
nodeset: ubuntu-xenial
|
||||||
ansible_container_architecture: "{{ hostvars[ansible_container_host]['ansible_architecture'] | lower }}"
|
|
||||||
|
|
||||||
nspawn_architecture_mapping:
|
- job:
|
||||||
x86_64: amd64
|
name: openstack-ansible-nspawn-centos-7
|
||||||
ppc64le: ppc64el
|
parent: openstack-ansible-functional
|
||||||
s390x: s390x
|
nodeset: centos-7
|
||||||
armv7l: armhf
|
|
||||||
|
- job:
|
||||||
|
name: openstack-ansible-nspawn-opensuse-423
|
||||||
|
parent: openstack-ansible-functional
|
||||||
|
nodeset: opensuse-423
|
30
zuul.d/project.yaml
Normal file
30
zuul.d/project.yaml
Normal file
@ -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:
|
||||||
|
check:
|
||||||
|
jobs:
|
||||||
|
- openstack-ansible-linters
|
||||||
|
- openstack-ansible-nspawn-ubuntu-xenial
|
||||||
|
- openstack-ansible-nspawn-centos-7
|
||||||
|
- openstack-ansible-nspawn-opensuse-423
|
||||||
|
experimental:
|
||||||
|
jobs:
|
||||||
|
- openstack-ansible-integrated-deploy-aio
|
||||||
|
gate:
|
||||||
|
jobs:
|
||||||
|
- openstack-ansible-linters
|
||||||
|
- openstack-ansible-nspawn-ubuntu-xenial
|
||||||
|
- openstack-ansible-nspawn-centos-7
|
||||||
|
- openstack-ansible-nspawn-opensuse-423
|
Loading…
Reference in New Issue
Block a user