hosts: testvm
roles:
- role: base
- - role: vm/grub
- - role: vm/network
- - role: vm/guest
host_domain=realraum.at
ansible_host={{ inventory_hostname }}.{{ host_domain }}
ansible_user=root
+ansible_port=22000
+
[net-zone-mgmt]
torwaechter
+++ /dev/null
-#!/bin/bash
-
-if [ -z "$1" ]; then
- echo "$0 <host>"
- exit 1
-fi
-
-SHORT="r3-${1%%.*}"
-SSH_HOST=$(ssh -G "$SHORT" | grep "^hostname " | awk '{ print($2) }' )
-
-for name in $SHORT $SSH_HOST; do
- ssh-keygen -f "$HOME/.ssh/known_hosts" -R "[$name]:22000"
-done
-
-exit 0
--- /dev/null
+#!/bin/sh
+set -eu
+
+if [ $# -eq 0 ]; then
+ echo "Usage: $0 vmname [vmname ...]" >&2
+ exit 1
+fi
+
+cd "$(dirname "$0")"
+
+for vmname in "$@"; do
+ ansible-playbook -e vmname="${vmname}" remove_known_hosts.yml
+done
--- /dev/null
+- name: Purge host from known hosts
+ hosts: localhost
+ gather_facts: no
+ tasks:
+ - command: ssh-keygen -f ~/.ssh/known_hosts -R [{{ item }}]:{{ hostvars[vmname].ansible_port }}
+ with_items:
+ - "{{ hostvars[vmname].ansible_host }}"
+ - r3-{{ vmname }}
+ - r3g-{{ vmname }}
+ - r3e-{{ vmname }}
+ - "{{ hostvars[vmname].vm_network_cooked.primary.ip }}"
shell: /bin/zsh
- name: set default shell for adduser
- with_items:
- - regexp: "^DSHELL"
- line: "DSHELL=/bin/zsh"
+ with_dict:
+ DSHELL: /bin/zsh
lineinfile:
dest: /etc/adduser.conf
- regexp: "{{ item.regexp }}"
- line: "{{ item.line }}"
+ regexp: "^#?{{ item.key }}="
+ line: "{{ item.key }}={{ item.value }}"
### to be set inhost_vars and group_vars
# localconfig_ssh_config_proxycommand:
# localconfig_ssh_config_user:
-# localconfig_ssh_config_port:
+# ansible_port
{% if 'localconfig_ssh_config_user' in hostvars[host] %}
User {{ hostvars[host].localconfig_ssh_config_user }}
{% endif %}
-{% if 'localconfig_ssh_config_port' in hostvars[host] %}
- Port {{ hostvars[host].localconfig_ssh_config_port }}
+{% if hostvars[host].ansible_port != 22000 %}
+ Port {{ hostvars[host].ansible_port }}
{% endif %}
{% endfor %}
---
- name: enable serial console in grub and for kernel
- with_items:
- - regexp: '^GRUB_TIMEOUT='
- line: 'GRUB_TIMEOUT=2'
- - regexp: '^GRUB_CMDLINE_LINUX='
- line: 'GRUB_CMDLINE_LINUX="console=ttyS0,115200n8"'
- - regexp: '^GRUB_TERMINAL='
- line: 'GRUB_TERMINAL=serial'
- - regexp: '^GRUB_SERIAL_COMMAND='
- line: 'GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"'
+ with_dict:
+ GRUB_TIMEOUT: 2
+ GRUB_CMDLINE_LINUX: '"console=ttyS0,115200n8"'
+ GRUB_TERMINAL: serial
+ GRUB_SERIAL_COMMAND: >-
+ "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"
lineinfile:
dest: /etc/default/grub
- regexp: "{{ item.regexp }}"
- line: "{{ item.line }}"
+ regexp: "^{{ item.key }}="
+ line: "{{ item.key }}={{ item.value }}"
notify: update grub
+ loop_control:
+ label: "{{ item.key }}"
loop_control:
label: "{{ item.key }}"
notify: restart rngd
+
+- name: Provide a root shell on the VM console [1/2]
+ file:
+ path: /etc/systemd/system/serial-getty@ttyS0.service.d/
+ state: directory
+
+- name: Provide a root shell on the VM console [2/2]
+ copy:
+ dest: /etc/systemd/system/serial-getty@ttyS0.service.d/autologon.conf
+ content: |
+ [Service]
+ ExecStart=
+ ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 --noclear --autologin root --login-pause --host {{ vm_install_host }} %I $TERM
---
-- name: restart inetd
- service:
- name: openbsd-inetd
- state: restarted
-
- name: restart haveged
service:
name: haveged
- name: install dependencies
apt:
name:
- - atftpd
- - openbsd-inetd
- qemu-kvm
- libvirt-bin
- python-libvirt
path: /etc/default/haveged
notify: restart haveged
-- name: configure tftpd via inetd
- lineinfile:
- regexp: "^#?({{ vm_host.network.ip }}:)?tftp"
- line: "{{ vm_host.network.ip }}:tftp dgram udp4 wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd --tftpd-timeout 300 --retry-timeout 5 --maxthread 10 --verbose=5 {{ vm_host.installer.preseed_path }}"
- path: /etc/inetd.conf
- notify: restart inetd
-
- name: make sure installer directories exists
with_items:
- "{{ vm_host.installer.path }}"
---
-- name: generate preseed file
- template:
- src: "preseed_{{ vmdistro }}-{{ vmdistcodename }}.cfg.j2"
- dest: "{{ vm_host.installer.preseed_path }}/vm-{{ vmname }}-{{ vmdistro }}-{{ vmdistcodename }}.cfg"
+- block:
+ - name: Make a temporary directory
+ command: mktemp -d
+ register: tmpdir
+
+ - set_fact:
+ tmpdir: "{{ tmpdir.stdout }}"
+ initramfs: "{{ vm_host.installer.preseed_path }}/vm-{{ vmname }}-{{ vmdistro }}-{{ vmdistcodename }}.initrd.gz"
+
+ - name: Copy initramfs into position
+ copy:
+ remote_src: yes
+ src: "{{ vm_host.installer.path }}/{{ vmdistro }}-{{ vmdistcodename }}/{{ hostvars[vmname].vm_install_cooked.arch | default('amd64') }}/initrd.gz"
+ dest: "{{ initramfs }}"
+
+ - name: generate preseed file
+ template:
+ src: "preseed_{{ vmdistro }}-{{ vmdistcodename }}.cfg.j2"
+ dest: "{{ tmpdir }}/preseed.cfg"
+
+ - name: generate authorized_keys file
+ authorized_key:
+ user: root
+ path: "{{ tmpdir }}/authorized_keys"
+ key: "{{ hostvars[vmname].ssh_keys | default(noc_ssh_keys) | join('\n') }}"
+
+ - name: Inject files into initramfs
+ shell: cpio -H newc -o | gzip -9 >> {{ initramfs }}
+ args:
+ chdir: "{{ tmpdir }}"
+ stdin: |
+ preseed.cfg
+ authorized_keys
+
+ always:
+ - name: Delete temporary directory
+ file:
+ path: "{{ tmpdir }}"
+ state: absent
- name: create disks for vm
with_dict: "{{ hostvars[vmname].vm_install_cooked.disks.virtio | default({}) | combine(hostvars[vmname].vm_install_cooked.disks.scsi | default({})) }}"
command: info
register: vmhost_info
-- name: destroy exisiting vm
- virt:
- name: "{{ vmname }}"
- state: destroyed
- when: vmname in vmhost_info
+- block:
+ - name: destroy exisiting vm
+ virt:
+ name: "{{ vmname }}"
+ state: destroyed
-- name: wait for vm to be destroyed
- wait_for_virt:
- name: "{{ vmname }}"
- states: shutdown,crashed
- timeout: 5
- when: vmname in vmhost_info
+ - name: wait for vm to be destroyed
+ wait_for_virt:
+ name: "{{ vmname }}"
+ states: shutdown,crashed
+ timeout: 5
+
+ - name: undefining exisiting vm
+ virt:
+ name: "{{ vmname }}"
+ command: undefine
-- name: undefining exisiting vm
- virt:
- name: "{{ vmname }}"
- command: undefine
when: vmname in vmhost_info
- name: enable installer in VM config
<type arch='x86_64' machine='pc-0.12'>hvm</type>
{% if run_installer %}
<kernel>{{ vm_host.installer.path }}/{{ vmdistro }}-{{ vmdistcodename }}/{{ hostvars[vmname].vm_install_cooked.arch | default('amd64') }}/linux</kernel>
- <initrd>{{ vm_host.installer.path }}/{{ vmdistro }}-{{ vmdistcodename }}/{{ hostvars[vmname].vm_install_cooked.arch | default('amd64') }}/initrd.gz</initrd>
- <cmdline>console=ttyS0,115200n8 auto=true interface=auto url=tftp://{{ hostvars[inventory_hostname]['ansible_' + (vm_host.installer.net_if | replace('-', '_'))].ipv4.address }}/vm-{{ vmname }}-{{ vmdistro }}-{{ vmdistcodename }}.cfg netcfg/choose_interface=enp1s1 netcfg/disable_autoconfig=true netcfg/get_ipaddress={{ hostvars[vmname].vm_network_cooked.primary.ip }} netcfg/get_netmask={{ hostvars[vmname].vm_network_cooked.primary.mask }} netcfg/get_gateway={{ hostvars[vmname].vm_network_cooked.primary.gateway }} netcfg/get_nameservers="{{ hostvars[vmname].vm_network_cooked.nameservers | join(' ') }}" netcfg/confirm_static=true netcfg/get_hostname={{ vmname }} netcfg/get_domain={{ hostvars[vmname].vm_network_cooked.domain }}</cmdline>
+ <initrd>{{ vm_host.installer.preseed_path }}/vm-{{ vmname }}-{{ vmdistro }}-{{ vmdistcodename }}.initrd.gz</initrd>
+ <cmdline>console=ttyS0,115200n8</cmdline>
{% endif %}
<boot dev='hd'/>
</os>
d-i debian-installer/locale string en_US.UTF-8
d-i keyboard-configuration/xkb-keymap select us
-
-#d-i netcfg/choose_interface select enp1s1
-#d-i netcfg/disable_autoconfig boolean false
-#d-i netcfg/get_ipaddress string {{ hostvars[vmname].vm_network_cooked.primary.ip }}
-#d-i netcfg/get_netmask string {{ hostvars[vmname].vm_network_cooked.primary.mask }}
-#d-i netcfg/get_gateway string {{ hostvars[vmname].vm_network_cooked.primary.gateway }}
-#d-i netcfg/get_nameservers string {{ hostvars[vmname].vm_network_cooked.nameservers | join(' ') }}
-#d-i netcfg/confirm_static boolean true
+d-i netcfg/disable_dhcp boolean true
+d-i netcfg/choose_interface select enp1s1
+d-i netcfg/disable_autoconfig boolean false
+d-i netcfg/get_ipaddress string {{ hostvars[vmname].vm_network_cooked.primary.ip }}
+d-i netcfg/get_netmask string {{ hostvars[vmname].vm_network_cooked.primary.mask }}
+d-i netcfg/get_gateway string {{ hostvars[vmname].vm_network_cooked.primary.gateway }}
+d-i netcfg/get_nameservers string {{ hostvars[vmname].vm_network_cooked.nameservers | join(' ') }}
+d-i netcfg/confirm_static boolean true
d-i netcfg/get_hostname string {{ vmname }}
d-i netcfg/get_domain string {{ hostvars[vmname].vm_network_cooked.domain }}
d-i preseed/late_command string \
lvremove -f {{ vmname }}/dummy; \
in-target bash -c "apt-get update -q && apt-get full-upgrade -y -q"; \
- in-target bash -c "passwd -d root; passwd -l root; umask 077; mkdir -p /root/.ssh/; echo -e '{{ noc_ssh_keys | join('\\n') }}' > /root/.ssh/authorized_keys"; \
- in-target bash -c "sed -e 's/^\(\s*#*\s*Port.*\)/Port 22000/' -i /etc/ssh/sshd_config"
+ in-target bash -c "passwd -d root && passwd -l root"; \
+ mkdir -p -m 0700 /target/root/.ssh; \
+ cp /authorized_keys /target/root/.ssh/; \
+{% if hostvars[vmname].ansible_port is defined %}
+ in-target bash -c "sed -e 's/^\(\s*#*\s*Port.*\)/Port {{ hostvars[vmname].ansible_port }}/' -i /etc/ssh/sshd_config"
+{% endif %}
echo "installing vm: $name with $distro/$codename"
echo ""
-echo "########## clearing old ssh host keys #########"
-./remove-known-host.sh "$name"
-echo ""
-
echo "######## running the install playbook ########"
exec ansible-playbook -e "vmname=$name" -e "vmdistro=$distro" -e "vmdistcodename=$codename" $@ vm-install.yml
group: _vmhost_
# TODO: add some sanity checks
+- import_playbook: remove_known_hosts.yml
+
- name: basic installation
hosts: _vmhost_
roles:
set_fact:
ansible_ssh_extra_args: ""
+- name: Apply VM configuration roles
+ hosts: "{{ vmname }}"
+ roles:
+ - role: vm/grub
+ - role: vm/network
+ - role: vm/guest
+
- import_playbook: "host_playbooks/{{ vmname }}.yml"
- name: reboot and wait for VM come back