openstack-ansible-lxc_conta.../tasks/container_create.yml
Kevin Carter b35928cf83 Change the container prep using more intelligent commands
When creating many containers on a single contended host, the execution
of many delegated tasks in parallel results in failure. This patch
consolidates the container prep and networking tasks leveraging the
lxc-rootfs pid path on the physical host instead of relying on delegation.

Change-Id: I0823e34286a0857b539a94604dbe9cdeb8a605f0
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
2016-09-15 02:34:10 +00:00

405 lines
13 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: Check for lxc volume group
shell: "(which vgs > /dev/null && vgs | grep -o '{{ lxc_container_vg_name }}') || false"
register: vg_result
failed_when: false
changed_when: vg_result.rc != 0
delegate_to: "{{ physical_host }}"
when: lxc_container_backing_store is not defined or lxc_container_backing_store == "lvm"
tags:
- lxc-container-vg-detect
- name: Set container backend to "dir" or "lvm" based on whether the lxc VG was found
set_fact:
lxc_container_backing_store: "{{ (vg_result.rc != 0) | ternary('dir', 'lvm') }}"
when: vg_result.rc is defined
tags:
- lxc-container-vg-detect
- name: Container service directories
file:
path: "{{ item }}"
state: "directory"
with_items:
- "/openstack/{{ inventory_hostname }}"
- "/openstack/backup/{{ inventory_hostname }}"
- "/openstack/log/{{ inventory_hostname }}"
- "{{ lxc_container_directory }}/{{ inventory_hostname }}"
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-directories
- name: LXC autodev setup
template:
src: "autodev.j2"
dest: "/var/lib/lxc/{{ inventory_hostname }}/autodev"
owner: "root"
group: "root"
mode: "0755"
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-autodev
- name: Create container
lxc_container:
name: "{{ inventory_hostname }}"
container_log: true
container_log_level: "{{ (debug | bool) | ternary('DEBUG', 'INFO') }}"
config: "{{ lxc_container_config }}"
template: "{{ lxc_container_template }}"
state: started
backing_store: "{{ lxc_container_backing_store }}"
directory: "{{ lxc_container_rootfs_directory }}"
fs_size: "{{ properties.container_fs_size | default(lxc_container_fs_size) }}"
fs_type: "{{ lxc_container_fs_type }}"
vg_name: "{{ lxc_container_vg_name }}"
template_options: "{{ lxc_container_download_template_options }}"
delegate_to: "{{ physical_host }}"
when: >
lxc_container_backing_store != "overlayfs" or
(lxc_container_backing_store == 'lvm' and not
(lxc_container_backing_method is defined
and lxc_container_backing_method == 'copy-on-write'))
tags:
- lxc-container-create
# Due to https://github.com/ansible/ansible-modules-extras/issues/2577 the
# next two tasks do not use the lxc_container module.
# TODO(odyssey4me): Revisit this once a fix has merged
- name: Check if container exists (copy-on-write backing store)
command: "lxc-info -n {{ inventory_hostname }}"
failed_when: false
delegate_to: "{{ physical_host }}"
register: lxc_container_info
when: >
lxc_container_backing_store == "overlayfs" or
(lxc_container_backing_store == 'lvm' and
lxc_container_backing_method is defined and
lxc_container_backing_method == 'copy-on-write')
# Due to https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/1591510
# the '-B' option is used, instead of the more understandable
# '--backingstore'.
# TODO(odyssey4me): Revisit this once a fix has merged
- name: Create container (copy-on-write backing store)
command: >
lxc-copy --snapshot -B {{ lxc_container_backing_store }}
--name {{ lxc_container_base_name }}
--newname {{ inventory_hostname }}
-L {{ properties.container_fs_size | default(lxc_container_fs_size) }}
--logfile {{ lxc_container_log_path }}/lxc-{{ inventory_hostname }}.log
--logpriority {{ (debug | bool) | ternary('DEBUG', 'INFO') }}
delegate_to: "{{ physical_host }}"
when: >
(lxc_container_backing_store == "overlayfs" or
(lxc_container_backing_store == 'lvm' and
lxc_container_backing_method is defined and
lxc_container_backing_method == 'copy-on-write')) and
lxc_container_info.rc != 0
tags:
- lxc-container-create
- name: Check container state
command: "lxc-info -n {{ inventory_hostname }} --state"
failed_when: false
changed_when: false
delegate_to: "{{ physical_host }}"
register: _lxc_container_state
# Due to https://github.com/ansible/ansible-modules-extras/issues/2691
# this uses the LXC CLI tools to ensure that we get logging.
# TODO(odyssey4me): revisit this once the bug is fixed and released
- name: Start the container if it is not already running
command: >
lxc-start --daemon --name {{ inventory_hostname }}
--logfile {{ lxc_container_log_path }}/lxc-{{ inventory_hostname }}.log
--logpriority {{ (debug | bool) | ternary('DEBUG', 'INFO') }}
delegate_to: "{{ physical_host }}"
when: _lxc_container_state.stdout.find('STOPPED') != -1
- name: Execute container commands
lxc_container:
name: "{{ inventory_hostname }}"
container_command: |
{{ lxc_container_commands }}
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-commands
- name: Write default container config
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "{{ item | replace('=', ' = ') | 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
tags:
- lxc-container-config
- 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 0 0"
backup: "true"
with_items: "{{ lxc_container_default_bind_mounts | union(lxc_container_bind_mounts) }}"
delegate_to: "{{ physical_host }}"
notify:
- Lxc container restart
tags:
- lxc-container-config
- 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 }}"
tags:
- lxc-container-networks
- name: Create start
lxc_container:
name: "{{ inventory_hostname }}"
state: started
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-create
- name: Get LXC container PID
command: >
lxc-info -pHn {{ inventory_hostname }}
register: container_pid
changed_when: false
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-setup
- name: Drop container network file (interfaces)
template:
src: "{{ lxc_container_interface }}"
dest: "/proc/{{ container_pid.stdout }}/root{{ lxc_container_interface_target }}"
owner: "root"
group: "root"
mode: "0644"
with_dict: "{{ container_networks | default({}) }}"
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-setup
- name: Drop container network file (routes)
template:
src: "{{ lxc_container_route_interface }}"
dest: "/proc/{{ container_pid.stdout }}/root{{ lxc_container_default_route_interfaces }}"
owner: "root"
group: "root"
mode: "0644"
when:
- lxc_container_route_interface | bool
- lxc_container_default_route_interfaces | bool
- item.value.static_routes is defined
with_dict: "{{ container_networks | default({}) }}"
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-setup
- name: Drop container setup script
template:
src: "container-setup.sh.j2"
dest: "/proc/{{ container_pid.stdout }}/root/opt/container-setup.sh"
owner: "root"
group: "root"
mode: "0755"
with_dict: "{{ container_networks | default({}) }}"
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-setup
- name: Run container setup script
command: |
lxc-attach --name "{{ inventory_hostname }}" \
--logfile {{ lxc_container_log_path }}/lxc-{{ inventory_hostname }}.log \
--logpriority {{ (debug | bool) | ternary('DEBUG', 'INFO') }} \
-- /opt/container-setup.sh
register: container_setup
changed_when: false
failed_when: container_setup.rc != 0
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-setup
# 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 = {{ inventory_hostname[-8:].replace('-', '').replace('_', '') }}_eth0"
insertafter: "^lxc.network.name"
backup: "true"
delegate_to: "{{ physical_host }}"
tags:
- lxc-container-networks
- 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 }}"
tags:
- lxc-container-networks
- 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 }}"
tags:
- lxc-container-networks
- name: Run container veth wiring script
shell: >
/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 }}"
tags:
- lxc-container-networks
# 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 }}"
tags:
- lxc-container-networks
# 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 }}"
tags:
- lxc-container-networks
# Flush the handlers to ensure the container and networking is online.
- meta: flush_handlers
- name: Wait for ssh to be available
local_action:
module: wait_for
port: "{{ ansible_port | default('22') }}"
host: "{{ ansible_host | default(inventory_hostname) }}"
search_regex: OpenSSH
delay: "{{ lxc_container_ssh_delay }}"
register: ssh_wait_check
until: ssh_wait_check | success
retries: 3
tags:
- lxc-container-networks
- name: Install container proxy settings
template:
dest: "/etc/environment"
src: "environment.j2"
mode: "0644"
remote_user: root
when:
- global_environment_variables is defined
tags:
- lxc-container-proxy
- 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
tags:
- lxc-container-hostname
- 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
tags:
- lxc-container-hostname
- name: Create hostname
copy:
dest: "/etc/hostname"
content: "{{ inventory_hostname | replace('_', '-') }}"
owner: "root"
group: "root"
mode: "0644"
remote_user: root
tags:
- lxc-container-hostname
- name: Setup hostname
command: hostname -F /etc/hostname
remote_user: root
tags:
- lxc-container-hostname