Add configure-swap role
This is a role to configure swap and /opt on an infra host. Originally we wrote this for devstack-gate with Icd4e6d8ab84471ad06e69c3e0f9bac92776efc78. It was ported into the native devstack job with Iffe54fbccbccd68db08f79a1b51dd7f76dbff408. This is really generic, and it's quite possible non-devstack jobs would like to setup swap for jobs too, so o-z-j is a better home for the role. Change-Id: I0e9c846ace7fac8a1340746c6818fba6ec963018
This commit is contained in:
parent
80237ba2dc
commit
1d01c6d3da
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# Backup files
|
||||||
|
*~
|
||||||
|
\#*\#
|
||||||
|
|
||||||
# Unit test / coverage reports
|
# Unit test / coverage reports
|
||||||
.coverage
|
.coverage
|
||||||
.tox
|
.tox
|
||||||
|
11
roles/configure-swap/README.rst
Normal file
11
roles/configure-swap/README.rst
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Configure a swap partition
|
||||||
|
|
||||||
|
Creates a swap partition on the ephemeral block device (the rest of which
|
||||||
|
will be mounted on /opt).
|
||||||
|
|
||||||
|
**Role Variables**
|
||||||
|
|
||||||
|
.. zuul:rolevar:: configure_swap_size
|
||||||
|
:default: 8192
|
||||||
|
|
||||||
|
The size of the swap partition, in MiB.
|
2
roles/configure-swap/defaults/main.yaml
Normal file
2
roles/configure-swap/defaults/main.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Default swap partition/file size, in MiB
|
||||||
|
configure_swap_size: 8192
|
118
roles/configure-swap/tasks/ephemeral.yaml
Normal file
118
roles/configure-swap/tasks/ephemeral.yaml
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
# Configure attached ephemeral devices for storage and swap
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "ephemeral_device is defined"
|
||||||
|
|
||||||
|
- name: Set partition names
|
||||||
|
set_fact:
|
||||||
|
swap_partition: "{{ ephemeral_device}}1"
|
||||||
|
opt_partition: "{{ ephemeral_device}}2"
|
||||||
|
|
||||||
|
- name: Ensure ephemeral device is unmounted
|
||||||
|
become: yes
|
||||||
|
mount:
|
||||||
|
name: "{{ ephemeral_device }}"
|
||||||
|
state: unmounted
|
||||||
|
|
||||||
|
- name: Get existing partitions
|
||||||
|
become: yes
|
||||||
|
parted:
|
||||||
|
device: "{{ ephemeral_device }}"
|
||||||
|
unit: MiB
|
||||||
|
register: ephemeral_partitions
|
||||||
|
|
||||||
|
- name: Remove any existing partitions
|
||||||
|
become: yes
|
||||||
|
parted:
|
||||||
|
device: "{{ ephemeral_device }}"
|
||||||
|
number: "{{ item.num }}"
|
||||||
|
state: absent
|
||||||
|
with_items:
|
||||||
|
- "{{ ephemeral_partitions.partitions }}"
|
||||||
|
|
||||||
|
- name: Create new disk label
|
||||||
|
become: yes
|
||||||
|
parted:
|
||||||
|
label: msdos
|
||||||
|
device: "{{ ephemeral_device }}"
|
||||||
|
|
||||||
|
- name: Create swap partition
|
||||||
|
become: yes
|
||||||
|
parted:
|
||||||
|
device: "{{ ephemeral_device }}"
|
||||||
|
number: 1
|
||||||
|
state: present
|
||||||
|
part_start: '0%'
|
||||||
|
part_end: "{{ configure_swap_size }}MiB"
|
||||||
|
|
||||||
|
- name: Create opt partition
|
||||||
|
become: yes
|
||||||
|
parted:
|
||||||
|
device: "{{ ephemeral_device }}"
|
||||||
|
number: 2
|
||||||
|
state: present
|
||||||
|
part_start: "{{ configure_swap_size }}MiB"
|
||||||
|
part_end: "100%"
|
||||||
|
|
||||||
|
- name: Make swap on partition
|
||||||
|
become: yes
|
||||||
|
command: "mkswap {{ swap_partition }}"
|
||||||
|
|
||||||
|
- name: Write swap to fstab
|
||||||
|
become: yes
|
||||||
|
mount:
|
||||||
|
path: none
|
||||||
|
src: "{{ swap_partition }}"
|
||||||
|
fstype: swap
|
||||||
|
opts: sw
|
||||||
|
passno: 0
|
||||||
|
dump: 0
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# XXX: does "parted" plugin ensure the partition is available
|
||||||
|
# before moving on? No udev settles here ...
|
||||||
|
|
||||||
|
- name: Add all swap
|
||||||
|
become: yes
|
||||||
|
command: swapon -a
|
||||||
|
|
||||||
|
- name: Create /opt filesystem
|
||||||
|
become: yes
|
||||||
|
filesystem:
|
||||||
|
fstype: ext4
|
||||||
|
# The default ratio is 16384 bytes per inode or so. Reduce that to 8192
|
||||||
|
# bytes per inode so that we get roughly twice the number of inodes as
|
||||||
|
# by default. This should still be well above the block size of 4096.
|
||||||
|
# We do this because we have found in at least a couple locations that
|
||||||
|
# more inodes is useful and is painful to fix after the fact.
|
||||||
|
opts: -i 8192
|
||||||
|
dev: "{{ opt_partition }}"
|
||||||
|
|
||||||
|
# Rackspace at least does not have enough room for two devstack
|
||||||
|
# installs on the primary partition. We copy in the existing /opt to
|
||||||
|
# the new partition on the ephemeral device, and then overmount /opt
|
||||||
|
# to there for the test runs.
|
||||||
|
#
|
||||||
|
# NOTE(ianw): the existing "mount" touches fstab. There is currently (Sep2017)
|
||||||
|
# work in [1] to split mount & fstab into separate parts, but for now we bundle
|
||||||
|
# it into an atomic shell command
|
||||||
|
# [1] https://github.com/ansible/ansible/pull/27174
|
||||||
|
- name: Copy old /opt
|
||||||
|
become: yes
|
||||||
|
shell: |
|
||||||
|
mount {{ opt_partition }} /mnt
|
||||||
|
find /opt/ -mindepth 1 -maxdepth 1 -exec mv {} /mnt/ \;
|
||||||
|
umount /mnt
|
||||||
|
|
||||||
|
# This overmounts any existing /opt
|
||||||
|
- name: Add opt to fstab and mount
|
||||||
|
become: yes
|
||||||
|
mount:
|
||||||
|
path: /opt
|
||||||
|
src: "{{ opt_partition }}"
|
||||||
|
fstype: ext4
|
||||||
|
opts: noatime
|
||||||
|
state: mounted
|
65
roles/configure-swap/tasks/main.yaml
Normal file
65
roles/configure-swap/tasks/main.yaml
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
# On RAX hosts, we have a small root partition and a large,
|
||||||
|
# unallocated ephemeral device attached at /dev/xvde
|
||||||
|
- name: Set ephemeral device if /dev/xvde exists
|
||||||
|
when: ansible_devices["xvde"] is defined
|
||||||
|
set_fact:
|
||||||
|
ephemeral_device: "/dev/xvde"
|
||||||
|
|
||||||
|
# On other providers, we have a device called "ephemeral0".
|
||||||
|
#
|
||||||
|
# NOTE(ianw): Once [1] is in our ansible (2.4 era?), we can figure
|
||||||
|
# this out more directly by walking the device labels in the facts
|
||||||
|
#
|
||||||
|
# [1] https://github.com/ansible/ansible/commit/d46dd99f47c0ee5081d15bc5b741e9096d8bfd3e
|
||||||
|
- name: Set ephemeral device by label
|
||||||
|
when: ephemeral_device is undefined
|
||||||
|
block:
|
||||||
|
- name: Get ephemeral0 device node
|
||||||
|
command: /sbin/blkid -L ephemeral0
|
||||||
|
register: ephemeral0
|
||||||
|
# If this doesn't exist, returns !0
|
||||||
|
ignore_errors: yes
|
||||||
|
changed_when: False
|
||||||
|
|
||||||
|
- name: Set ephemeral device if LABEL exists
|
||||||
|
when: "ephemeral0.rc == 0"
|
||||||
|
set_fact:
|
||||||
|
ephemeral_device: "{{ ephemeral0.stdout }}"
|
||||||
|
|
||||||
|
# If we have ephemeral storage and we don't appear to have setup swap,
|
||||||
|
# we will create a swap and move /opt to a large data partition there.
|
||||||
|
- include: ephemeral.yaml
|
||||||
|
static: no
|
||||||
|
when:
|
||||||
|
- ephemeral_device is defined
|
||||||
|
- ansible_memory_mb['swap']['total'] | int + 10 <= configure_swap_size
|
||||||
|
|
||||||
|
# If no ephemeral device and no swap, then we will setup some swap
|
||||||
|
# space on the root device to ensure all hosts a consistent memory
|
||||||
|
# environment.
|
||||||
|
- include: root.yaml
|
||||||
|
static: no
|
||||||
|
when:
|
||||||
|
- ephemeral_device is undefined
|
||||||
|
- ansible_memory_mb['swap']['total'] | int + 10 <= configure_swap_size
|
||||||
|
|
||||||
|
# ensure a standard level of swappiness. Some platforms
|
||||||
|
# (rax+centos7) come with swappiness of 0 (presumably because the
|
||||||
|
# vm doesn't come with swap setup ... but we just did that above),
|
||||||
|
# which depending on the kernel version can lead to the OOM killer
|
||||||
|
# kicking in on some processes despite swap being available;
|
||||||
|
# particularly things like mysql which have very high ratio of
|
||||||
|
# anonymous-memory to file-backed mappings.
|
||||||
|
#
|
||||||
|
# This sets swappiness low; we really don't want to be relying on
|
||||||
|
# cloud I/O based swap during our runs if we can help it
|
||||||
|
- name: Set swappiness
|
||||||
|
become: yes
|
||||||
|
sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 30
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- debug: var=ephemeral_device
|
65
roles/configure-swap/tasks/root.yaml
Normal file
65
roles/configure-swap/tasks/root.yaml
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
# If no ephemeral devices are available, use root filesystem
|
||||||
|
|
||||||
|
- name: Calculate required swap
|
||||||
|
set_fact:
|
||||||
|
swap_required: "{{ configure_swap_size - ansible_memory_mb['swap']['total'] | int }}"
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Get root filesystem
|
||||||
|
shell: df --output='fstype' /root | tail -1
|
||||||
|
register: root_fs
|
||||||
|
|
||||||
|
- name: Save root filesystem
|
||||||
|
set_fact:
|
||||||
|
root_filesystem: "{{ root_fs.stdout }}"
|
||||||
|
|
||||||
|
- debug: var=root_filesystem
|
||||||
|
|
||||||
|
# Note, we don't use a sparse device to avoid wedging when disk space
|
||||||
|
# and memory are both unavailable.
|
||||||
|
|
||||||
|
# Cannot fallocate on filesystems like XFS, so use slower dd
|
||||||
|
- name: Create swap backing file for non-EXT fs
|
||||||
|
when: '"ext" not in root_filesystem'
|
||||||
|
become: yes
|
||||||
|
command: dd if=/dev/zero of=/root/swapfile bs=1M count={{ swap_required }}
|
||||||
|
args:
|
||||||
|
creates: /root/swapfile
|
||||||
|
|
||||||
|
- name: Create sparse swap backing file for EXT fs
|
||||||
|
when: '"ext" in root_filesystem'
|
||||||
|
become: yes
|
||||||
|
command: fallocate -l {{ swap_required }}M /root/swapfile
|
||||||
|
args:
|
||||||
|
creates: /root/swapfile
|
||||||
|
|
||||||
|
- name: Ensure swapfile perms
|
||||||
|
become: yes
|
||||||
|
file:
|
||||||
|
path: /root/swapfile
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0600
|
||||||
|
|
||||||
|
- name: Make swapfile
|
||||||
|
become: yes
|
||||||
|
command: mkswap /root/swapfile
|
||||||
|
|
||||||
|
- name: Write swap to fstab
|
||||||
|
become: yes
|
||||||
|
mount:
|
||||||
|
path: none
|
||||||
|
src: /root/swapfile
|
||||||
|
fstype: swap
|
||||||
|
opts: sw
|
||||||
|
passno: 0
|
||||||
|
dump: 0
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add all swap
|
||||||
|
become: yes
|
||||||
|
command: swapon -a
|
||||||
|
|
||||||
|
- debug: var=swap_required
|
Loading…
Reference in New Issue
Block a user