
When switching from LVM to a file backing store, the existing pool cannot be undefined until any existing VM's and LV's are removed. This ensures that if this is the case, it will be cleaned up so that the switch is effortless. Change-Id: Ie1460b37593306044f0a63f445c3da1987362d34
439 lines
14 KiB
YAML
439 lines
14 KiB
YAML
---
|
|
# 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 witing, 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 facts
|
|
hosts: mnaio_hosts
|
|
gather_facts: "{{ gather_facts | default(true) }}"
|
|
environment: "{{ deployment_environment_variables | default({}) }}"
|
|
tags:
|
|
- setup-host
|
|
tasks:
|
|
- name: Gather variables for each operating system
|
|
include_vars: "{{ item }}"
|
|
with_first_found:
|
|
- "{{ playbook_dir }}/vars/{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml"
|
|
- "{{ playbook_dir }}/vars/{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
|
|
- "{{ playbook_dir }}/vars/{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
|
|
- "{{ playbook_dir }}/vars/{{ ansible_distribution | lower }}.yml"
|
|
- "{{ playbook_dir }}/vars/{{ ansible_os_family | lower }}.yml"
|
|
tags:
|
|
- always
|
|
|
|
- name: Install pre-requisite host distro packages
|
|
package:
|
|
name: "{{ mnaio_host_required_distro_packages }}"
|
|
state: "latest"
|
|
update_cache: yes
|
|
cache_valid_time: 600
|
|
register: _install_required_host_packages
|
|
until: _install_required_host_packages is success
|
|
retries: 3
|
|
delay: 15
|
|
when:
|
|
- "mnaio_host_required_distro_packages | length > 0"
|
|
|
|
- name: Add/Remove/Update apt repositories
|
|
apt_repository:
|
|
repo: "{{ repo.repo }}"
|
|
state: "{{ repo.state | default('present') }}"
|
|
filename: "{{ repo.filename | default(omit) }}"
|
|
update_cache: no
|
|
with_items: "{{ mnaio_host_package_repos }}"
|
|
loop_control:
|
|
loop_var: repo
|
|
register: _add_apt_repo
|
|
when:
|
|
- "ansible_os_family == 'Debian'"
|
|
- "mnaio_host_package_repos | length > 0"
|
|
- "(repo.condition | default(True)) | bool"
|
|
|
|
- name: Update apt cache
|
|
apt:
|
|
update_cache: yes
|
|
register: _update_apt_cache
|
|
until: _update_apt_cache is success
|
|
retries: 3
|
|
delay: 15
|
|
when:
|
|
- "ansible_os_family == 'Debian'"
|
|
- "_add_apt_repo is changed"
|
|
|
|
- name: Install host distro packages
|
|
package:
|
|
name: "{{ mnaio_host_distro_packages }}"
|
|
state: "latest"
|
|
update_cache: yes
|
|
cache_valid_time: 600
|
|
register: _install_host_packages
|
|
until: _install_host_packages is success
|
|
retries: 3
|
|
delay: 15
|
|
|
|
- name: Ensure root has a .ssh directory
|
|
file:
|
|
path: /root/.ssh
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: 0700
|
|
|
|
- name: Create ssh key pair for root
|
|
user:
|
|
name: root
|
|
generate_ssh_key: yes
|
|
ssh_key_bits: 2048
|
|
ssh_key_file: /root/.ssh/id_rsa
|
|
|
|
- name: Get root public key
|
|
command: cat /root/.ssh/id_rsa.pub
|
|
register: public_key_get
|
|
changed_when: false
|
|
|
|
- name: Set key facts
|
|
set_fact:
|
|
root_public_key: "{{ public_key_get.stdout }}"
|
|
|
|
- name: Ensure root can ssh to localhost
|
|
authorized_key:
|
|
user: "root"
|
|
key: "{{ root_public_key }}"
|
|
|
|
- name: Setup SSH client to disable strict host key checks
|
|
lineinfile:
|
|
path: /etc/ssh/ssh_config
|
|
regexp: "^.*StrictHostKeyChecking.*$"
|
|
line: " StrictHostKeyChecking no"
|
|
insertafter: "^Host \\*$"
|
|
state: present
|
|
|
|
- name: Setup SSH client to have a non-persistant known hosts file
|
|
lineinfile:
|
|
path: /etc/ssh/ssh_config
|
|
regexp: "^.*UserKnownHostsFile.*$"
|
|
line: " UserKnownHostsFile=/dev/null"
|
|
insertafter: "^Host \\*$"
|
|
state: present
|
|
|
|
- name: Setup SSH client to disable DNS host key checks
|
|
lineinfile:
|
|
path: /etc/ssh/ssh_config
|
|
regexp: "^.*VerifyHostKeyDNS.*$"
|
|
line: " VerifyHostKeyDNS no"
|
|
insertafter: "^Host \\*$"
|
|
state: present
|
|
|
|
- name: Add sysctl options
|
|
sysctl:
|
|
name: net.ipv4.ip_forward
|
|
value: 1
|
|
sysctl_set: yes
|
|
state: present
|
|
reload: yes
|
|
sysctl_file: /etc/sysctl.conf
|
|
|
|
- name: Get gateway interface
|
|
shell: "/sbin/ip r g 1 | awk '{print $5}'"
|
|
register: gw_iface
|
|
|
|
- set_fact:
|
|
masquerade_interface: "{{ gw_iface.stdout.strip() }}"
|
|
|
|
- name: Add IPtables rules
|
|
iptables:
|
|
table: "{{ item.table | default(omit) }}"
|
|
chain: "{{ item.chain | default(omit) }}"
|
|
in_interface: "{{ item.in_interface | default(omit) }}"
|
|
out_interface: "{{ item.out_interface | default(omit) }}"
|
|
source: "{{ item.source | default(omit) }}"
|
|
destination: "{{ item.destination | default(omit) }}"
|
|
protocol: "{{ item.protocol | default(omit) }}"
|
|
match: "{{ item.match | default(omit) }}"
|
|
destination_port: "{{ item.destination_port | default(omit) }}"
|
|
jump: "{{ item.jump | default(omit) }}"
|
|
to_ports: "{{ item.to_ports | default(omit) }}"
|
|
with_items: "{{ mnaio_host_iptables_rules }}"
|
|
|
|
# These rules are added manually due to bugs in the iptables module.
|
|
- name: Add IPtables rules
|
|
shell: |
|
|
if ! iptables -w -t {{ item.table }} -C {{ item.rule }};then
|
|
iptables -w -t {{ item.table }} -I {{ item.rule }}
|
|
fi
|
|
with_items:
|
|
- table: 'nat'
|
|
rule: 'POSTROUTING -s 10.0.2.0/22 ! -d 10.0.2.0/22 -j MASQUERADE'
|
|
- table: 'mangle'
|
|
rule: 'POSTROUTING -s 10.0.2.0/22 -o vm-br-dhcp -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill'
|
|
- table: 'mangle'
|
|
rule: 'POSTROUTING -s 10.0.2.0/22 -o vm-br-dhcp -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill'
|
|
|
|
- name: Add IPtables pre-routing rules to allow external access to VMs
|
|
shell: |
|
|
if ! iptables -w -t nat -C PREROUTING -p tcp -d {{ ansible_default_ipv4.address }} --dport {{ item.host_port }} -j DNAT --to {{ item.vm_ip }}:{{ item.vm_port }};then
|
|
iptables -w -t nat -I PREROUTING -p tcp -d {{ ansible_default_ipv4.address }} --dport {{ item.host_port }} -j DNAT --to {{ item.vm_ip }}:{{ item.vm_port }}
|
|
fi
|
|
with_items: "{{ mnaio_host_iptables_prerouting_ports }}"
|
|
when: config_prerouting | default(false) | bool
|
|
|
|
- name: Start netfilter persistent
|
|
service:
|
|
name: "{{ mnaio_host_iptables_service }}"
|
|
state: started
|
|
enabled: yes
|
|
when:
|
|
- ansible_distribution | lower == 'ubuntu'
|
|
|
|
- name: Drop host network interfaces
|
|
template:
|
|
src: "pxe/configs/{{ ansible_os_family | lower }}/mnaio-bridges.cfg.j2"
|
|
dest: /etc/network/interfaces.d/mnaio-bridges.cfg
|
|
mode: "0644"
|
|
owner: root
|
|
group: root
|
|
register: mnaio_bridges
|
|
|
|
- name: Ensure extra interfaces are sourced
|
|
lineinfile:
|
|
line: "source /etc/network/interfaces.d/*.cfg"
|
|
dest: "/etc/network/interfaces"
|
|
regexp: "^source /etc/network/interfaces.d/.*"
|
|
|
|
- name: Set the host interfaces up
|
|
command: "/sbin/ifup {{ item.value.iface }}"
|
|
with_dict: "{{ mnaio_host_networks }}"
|
|
when: mnaio_bridges is changed
|
|
|
|
- name: Disable default virt network
|
|
virt_net:
|
|
name: "default"
|
|
state: inactive
|
|
autostart: no
|
|
|
|
- name: List virt network(s)
|
|
virt_net:
|
|
command: list_nets
|
|
register: vm_networks
|
|
|
|
- name: Define virt network(s)
|
|
virt_net:
|
|
command: define
|
|
name: "{{ item.value.iface }}"
|
|
xml: "{{ lookup('template', 'kvm/libvirt-network-template.xml.j2') }}"
|
|
with_dict: "{{ mnaio_host_networks }}"
|
|
when: "item.value.iface not in vm_networks.list_nets"
|
|
|
|
- name: Create virt network(s)
|
|
virt_net:
|
|
command: create
|
|
name: "{{ item.value.iface }}"
|
|
autostart: true
|
|
with_dict: "{{ mnaio_host_networks }}"
|
|
when: "item.value.iface not in vm_networks.list_nets"
|
|
|
|
- name: Locate the largest writable data disk if mnaio_data_disk is not set
|
|
shell: >
|
|
lsblk -brndo NAME,TYPE,FSTYPE,RO,SIZE | awk '/d[b-z]+ disk +0/{ if ($4>m){m=$4; d=$1}}; END{print d}'
|
|
register: lsblk
|
|
changed_when: false
|
|
when:
|
|
- mnaio_data_disk is undefined
|
|
|
|
- name: Get info about existing virt storage pools
|
|
virt_pool:
|
|
command: info
|
|
register: _virt_pools
|
|
|
|
- name: If an existing virt pool does not match default_vm_disk_mode, remove it
|
|
when:
|
|
- _virt_pools.pools.default is defined
|
|
- (default_vm_disk_mode == "file" and _virt_pools.pools.default.format is defined) or
|
|
(default_vm_disk_mode == "lvm" and _virt_pools.pools.default.format is not defined)
|
|
block:
|
|
- name: Stop running VMs
|
|
virt:
|
|
name: "{{ item }}"
|
|
command: destroy
|
|
failed_when: false
|
|
with_items: "{{ _virt_pools.pools.default.volumes }}"
|
|
|
|
- name: Delete VM LVs
|
|
lvol:
|
|
vg: "{{ default_vm_disk_vg }}"
|
|
lv: "{{ item }}"
|
|
state: absent
|
|
force: yes
|
|
failed_when: false
|
|
with_items: "{{ _virt_pools.pools.default.volumes }}"
|
|
|
|
- name: Delete VM Disk Images
|
|
file:
|
|
path: "{{ _virt_pools.pools.default.path | default('/data/images') }}/{{ item }}.img"
|
|
state: absent
|
|
with_items: "{{ _virt_pools.pools.default.volumes }}"
|
|
|
|
- name: Undefine the VMs
|
|
virt:
|
|
name: "{{ item }}"
|
|
command: undefine
|
|
failed_when: false
|
|
with_items: "{{ _virt_pools.pools.default.volumes }}"
|
|
|
|
- name: Dismount the mount point if default_vm_disk_mode is 'lvm'
|
|
mount:
|
|
path: /data
|
|
state: unmounted
|
|
when:
|
|
- default_vm_disk_mode == "lvm"
|
|
|
|
- name: Stop the pool
|
|
virt_pool:
|
|
command: destroy
|
|
name: default
|
|
|
|
- name: Delete the pool, destroying its contents
|
|
virt_pool:
|
|
command: delete
|
|
name: default
|
|
|
|
- name: Undefine the pool
|
|
virt_pool:
|
|
command: undefine
|
|
name: default
|
|
|
|
- name: Remove the mount point if default_vm_disk_mode is 'lvm'
|
|
mount:
|
|
path: /data
|
|
state: absent
|
|
when:
|
|
- default_vm_disk_mode == "lvm"
|
|
|
|
- name: Reload systemd to remove generated unit files for mount
|
|
systemd:
|
|
daemon_reload: yes
|
|
when:
|
|
- default_vm_disk_mode == "lvm"
|
|
|
|
- name: Remove the volume group if default_vm_disk_mode is 'file'
|
|
lvg:
|
|
vg: vg01
|
|
state: absent
|
|
register: _remove_vg
|
|
when:
|
|
- default_vm_disk_mode == "file"
|
|
|
|
- name: Remove the existing disk partition
|
|
parted:
|
|
device: "/dev/{{ mnaio_data_disk | default(lsblk.stdout) }}"
|
|
number: 1
|
|
state: absent
|
|
|
|
- name: Setup the data disk partition
|
|
parted:
|
|
device: "/dev/{{ mnaio_data_disk | default(lsblk.stdout) }}"
|
|
label: gpt
|
|
number: 1
|
|
name: data1
|
|
state: present
|
|
register: _add_partition
|
|
|
|
- name: Prepare the data disk for 'lvm' default_vm_disk_mode
|
|
when:
|
|
- default_vm_disk_mode == "lvm"
|
|
block:
|
|
- name: Create the volume group
|
|
lvg:
|
|
vg: vg01
|
|
pvs: "/dev/{{ mnaio_data_disk | default(lsblk.stdout) }}1"
|
|
|
|
- name: Define the default virt storage pool
|
|
virt_pool:
|
|
name: default
|
|
state: present
|
|
xml: |
|
|
<pool type='logical'>
|
|
<name>default</name>
|
|
<source>
|
|
<name>vg01</name>
|
|
<format type='lvm2'/>
|
|
</source>
|
|
<target>
|
|
<path>/dev/vg01</path>
|
|
</target>
|
|
</pool>
|
|
|
|
- name: Prepare the data disk for 'file' default_vm_disk_mode
|
|
when:
|
|
- default_vm_disk_mode == "file"
|
|
block:
|
|
- name: Prepare the data disk file system
|
|
filesystem:
|
|
fstype: ext4
|
|
dev: "/dev/{{ mnaio_data_disk | default(lsblk.stdout) }}1"
|
|
force: yes
|
|
when:
|
|
- _add_partition is changed
|
|
|
|
- name: Mount the data disk
|
|
mount:
|
|
src: "/dev/{{ mnaio_data_disk | default(lsblk.stdout) }}1"
|
|
path: /data
|
|
state: mounted
|
|
fstype: ext4
|
|
|
|
- name: Create the images directory
|
|
file:
|
|
path: /data/images
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
state: directory
|
|
|
|
- name: Define the default virt storage pool
|
|
virt_pool:
|
|
name: default
|
|
state: present
|
|
xml: |
|
|
<pool type='dir'>
|
|
<name>default</name>
|
|
<target>
|
|
<path>/data/images</path>
|
|
<permissions>
|
|
<mode>0755</mode>
|
|
<owner>0</owner>
|
|
<group>0</group>
|
|
</permissions>
|
|
</target>
|
|
</pool>
|
|
|
|
- name: Set default virt storage pool to active
|
|
virt_pool:
|
|
name: default
|
|
state: active
|
|
|
|
- name: Set default virt storage pool to autostart
|
|
virt_pool:
|
|
name: default
|
|
autostart: yes
|
|
|
|
- name: Load virtio kernel modules
|
|
shell: |
|
|
for mod in $(find /lib/modules/$(uname -r) -type f -name 'virtio*.ko'); do
|
|
module=$(echo $(basename $mod) | sed 's/\.ko//g')
|
|
modprobe ${module}
|
|
if ! grep ${module} /etc/modules; then
|
|
echo ${module} | tee -a /etc/modules
|
|
fi
|
|
done
|