openstack-ansible-lxc_conta.../tasks/lxc_container_config.yml

321 lines
11 KiB
YAML

---
# 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: Execute container commands
lxc_container:
name: "{{ inventory_hostname }}"
container_command: |
{{ lxc_container_commands }}
delegate_to: "{{ physical_host }}"
- name: Write default container config
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "{{ item | replace('=', ' = ', 1) | regex_replace('\\s+', ' ') }}"
backup: "true"
with_items: "{{ lxc_container_default_config_list | union(lxc_container_config_list) }}"
delegate_to: "{{ physical_host }}"
notify:
- Lxc container restart
- name: Ensure bind mount host directories exists
file:
path: "{{ item['host_directory'] }}"
state: "directory"
recurse: true
with_items: "{{ lxc_container_default_bind_mounts | union(lxc_container_bind_mounts) }}"
delegate_to: "{{ physical_host }}"
- name: Add bind mount configuration to container
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "lxc.mount.entry = {{ item['host_directory'] }} {{ item['container_directory'].lstrip('/') }} none bind,create=dir 0 0"
backup: "true"
with_items: "{{ lxc_container_default_bind_mounts | union(lxc_container_bind_mounts) }}"
delegate_to: "{{ physical_host }}"
notify:
- Lxc container restart
# NOTE(cloudnull): Should a container already be up and running with a defined container interface
# the shell command will use the MAC address already set within the container as
# it's value. This allows the tasks to remain idempotent while ensuring that a
# container restart isn't required to set a static mac.
# This task is being done to allow a container to have a static mac address.
# before this task a container had a dynamic mac address which would
# change when a container was restarted. This restart process causes terrible
# issues in several network intensive systems (RabbitMQ, Neutron, etc). To
# resolve the rotating mac address issue this task is setting the mac in a hwaddr
# file and a lookup is being used in the container-interface.ini template to render
# the static hardware address as expected.
- name: Set define static mac address from an existing interface
shell: |
C_PID="$(lxc-info --name {{ inventory_hostname }} --pid | awk '/PID:/ {print $2}')"
C_ADDR="/proc/${C_PID}/root/sys/class/net/{{ item.value.interface }}/address"
HARDWARE_ADDR="/var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr"
HEXCHARS="0123456789abcdef"
if ! cat "${C_ADDR}" > "${HARDWARE_ADDR}"; then
echo "00:16:3e$(
for i in {1..6}; do
echo -n "${HEXCHARS:$(( $RANDOM % 16 )):1}"
done | sed -e 's/\(..\)/:\1/g'
)" > "${HARDWARE_ADDR}"
fi
args:
executable: /bin/bash
creates: "/var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr"
with_dict: "{{ container_networks | default({}) }}"
delegate_to: "{{ physical_host }}"
tags:
- skip_ansible_lint
when:
- lxc_container_fixed_mac | bool
- name: Gather hardware addresses to be used as facts
slurp:
src: "/var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr"
changed_when: false
register: macs
with_dict: "{{ container_networks | default({}) }}"
delegate_to: "{{ physical_host }}"
when:
- lxc_container_fixed_mac | bool
# NOTE(cloudnull): To dynamically set the the mac address "facts" Ansible line format is being used
- name: Set fixed hardware address fact
set_fact: "{{item.item.value.interface }}_mac_address={{ item.content | b64decode }}"
with_items:
- "{{ macs.results }}"
when:
- lxc_container_fixed_mac | bool
- name: LXC host config for container networks
template:
src: "container-interface.ini.j2"
dest: "/var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.ini"
owner: "root"
group: "root"
mode: "0644"
with_dict: "{{ container_networks | default({}) }}"
delegate_to: "{{ physical_host }}"
- name: Create start
lxc_container:
name: "{{ inventory_hostname }}"
state: started
delegate_to: "{{ physical_host }}"
- name: Drop container network file (interfaces)
template:
src: "{{ lxc_container_interface }}"
dest: "{{ lxc_container_interface_target }}"
owner: "root"
group: "root"
mode: "0644"
with_dict: "{{ container_networks | default({}) }}"
- name: Drop container network file (routes)
template:
src: "{{ lxc_container_route_interface }}"
dest: "{{ lxc_container_default_route_interfaces }}"
owner: "root"
group: "root"
mode: "0644"
when:
- lxc_container_route_interface is defined
- lxc_container_default_route_interfaces is defined
- item.value.static_routes is defined or
(item.value.gateway is defined and ansible_pkg_mgr == "zypper")
with_dict: "{{ container_networks | default({}) }}"
- name: Drop container setup script
template:
src: "container-setup.sh.j2"
dest: "/opt/container-setup.sh"
owner: "root"
group: "root"
mode: "0755"
- name: Run container setup script
command: /opt/container-setup.sh
register: container_setup
changed_when: false
failed_when: container_setup.rc != 0
# NOTE(major): the lxc.network.veth.pair line must appear *immediately* after
# the lxc.network.name congfiguration line or it will be ignored. That's why
# you'll find a "insertafter" in this YAML block.
- name: Add veth pair name to match container name
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "lxc.network.veth.pair = {{ lxc_container_network_veth_pair_prefix }}_eth0"
insertafter: "^lxc.network.name"
backup: "true"
delegate_to: "{{ physical_host }}"
- name: Container network includes
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "lxc.include = /var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.ini"
backup: "true"
with_dict: "{{ container_networks | default({}) }}"
when: item.value.interface is defined
delegate_to: "{{ physical_host }}"
- name: Create wiring script
copy:
src: "lxc-veth-wiring.sh"
dest: "/usr/local/bin/lxc-veth-wiring"
owner: "root"
group: "root"
mode: "0755"
delegate_to: "{{ physical_host }}"
- name: Run container veth wiring script
command: >
/usr/local/bin/lxc-veth-wiring
"{{ inventory_hostname }}"
"{{ lxc_container_network_veth_pair[-15:] }}"
"{{ item.value.interface }}"
"{{ item.value.bridge }}"
register: wiring_script
with_dict: "{{ container_networks | default({}) }}"
when:
- item.value.interface is defined
- item.value.type is not defined or item.value.type == 'veth'
failed_when: wiring_script.rc not in [3, 0]
changed_when: wiring_script.rc == 3
delegate_to: "{{ physical_host }}"
# Adds post-down and pre-start hooks
- name: Drop veth cleanup script
template:
src: "veth-cleanup.sh.j2"
dest: "/var/lib/lxc/{{ inventory_hostname }}/veth-cleanup.sh"
owner: "root"
group: "root"
mode: "0755"
delegate_to: "{{ physical_host }}"
# This is being defined due to an issue with dangling veth pairs.
# TODO(someone) This should be removed once an upstream patch has
# been submitted to either the kernel or LXC to fix the veth issues.
# Container restart is not happening here because it's not needed.
- name: Defines a pre and post hook script
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "{{ item }}"
backup: "true"
with_items:
- "lxc.hook.pre-start = /var/lib/lxc/{{ inventory_hostname }}/veth-cleanup.sh"
- "lxc.hook.post-stop = /var/lib/lxc/{{ inventory_hostname }}/veth-cleanup.sh"
delegate_to: "{{ physical_host }}"
# Flush the handlers to ensure the container and networking is online.
- meta: flush_handlers
- name: Wait for container connectivity
wait_for_connection:
connect_timeout: "{{ lxc_container_wait_params.connect_timeout | default(omit) }}"
delay: "{{ lxc_container_wait_params.delay | default(omit) }}"
sleep: "{{ lxc_container_wait_params.sleep | default(omit) }}"
timeout: "{{ lxc_container_wait_params.timeout | default(omit) }}"
- name: Add global_environment_variables to environment file
blockinfile:
dest: "/etc/environment"
state: present
marker: "# {mark} Managed by OpenStack-Ansible"
insertbefore: EOF
block: "{{ lookup('template', 'environment.j2') }}"
remote_user: root
- name: Create localhost config
lineinfile:
dest: "/etc/hosts"
regexp: "^127.0.0.1"
line: "127.0.0.1 localhost"
owner: "root"
group: "root"
mode: "0644"
remote_user: root
- name: Create domain config
lineinfile:
dest: "/etc/hosts"
regexp: "^127.0.1.1"
line: "127.0.1.1 {{ inventory_hostname | replace('_', '-') }}.{{ lxc_container_domain }} {{ inventory_hostname | replace('_', '-') }}"
owner: "root"
group: "root"
mode: "0644"
remote_user: root
- name: Create hostname
copy:
dest: "/etc/hostname"
content: "{{ inventory_hostname | replace('_', '-') }}"
owner: "root"
group: "root"
mode: "0644"
remote_user: root
- name: Setup hostname
command: hostname -F /etc/hostname
changed_when: false
remote_user: root
- name: Ensure sysctl can be applied
template:
src: "sysctl-container.init.j2"
dest: "/etc/systemd/system/sysctl-container.service"
mode: "0644"
owner: "root"
group: "root"
remote_user: root
# NOTE(hwoarang) openSUSE randomly fails to start the service
# with an error like the following one
# sysctl-container.service: Failed at step CGROUP spawning /sbin/sysctl: No such device
# Until this is fixed, we workaround it by simply retrying a few more times
# before giving up
# https://bugzilla.suse.com/show_bug.cgi?id=1055426
# https://bugs.launchpad.net/openstack-ansible/+bug/1712741
- name: Enable container sysctl service
service:
name: "sysctl-container"
state: started
enabled: yes
daemon_reload: yes
remote_user: root
register: _sysctl_service_started
until: _sysctl_service_started|success
retries: 5
delay: 5
- name: Allow the usage of local facts
file:
path: /etc/ansible/facts.d/
state: directory
tags:
- always
- name: Record the container variant deployed
ini_file:
dest: "/etc/ansible/facts.d/openstack_ansible.fact"
section: lxc
option: variant
value: "{{ properties['lxc_container_variant'] | default(lxc_container_variant) }}"
tags:
- always