--- # 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 == '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 == '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_map.distro }}-{{ lxc_container_map.release }}-{{ lxc_container_map.arch }} --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 == '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 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" with_items: "{{ lxc_container_default_bind_mounts | union(lxc_container_bind_mounts) }}" delegate_to: "{{ physical_host }}" - name: Ensure container directories exist lxc_container: name: "{{ inventory_hostname }}" container_command: | [[ ! -d "{{ item['container_directory'] }}" ]] && mkdir -p "{{ item['container_directory'] }}" 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: Container network interfaces lxc_container: name: "{{ inventory_hostname }}" container_command: | echo -e '{{ lxc_container_interface }}' | tee {{ lxc_container_interface_target }} with_dict: "{{ container_networks | default({}) }}" delegate_to: "{{ physical_host }}" tags: - lxc-container-networks - name: Container network route interfaces lxc_container: name: "{{ inventory_hostname }}" container_command: | echo -e '{{ lxc_container_default_route_interfaces.route_setup }}' | tee {{ lxc_container_default_route_interfaces.route_file }} when: item.value.static_routes is defined with_dict: "{{ container_networks | default({}) }}" delegate_to: "{{ physical_host }}" tags: - lxc-container-networks - 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 # 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 }}" "{{ inventory_hostname[-8:].replace('-', '').replace('_', '') }}_{{ item.value.interface }}" "{{ 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_ssh_port | default('22') }}" host: "{{ ansible_ssh_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