Commit dc868dc9 authored by Pietsch, Martin's avatar Pietsch, Martin

move commit

parents
Description
===========
This role configures and upgrades a FreeBSD system. Furthermore, it creates a mirror and installation media for this.
Requirement
===========
User defined variables
----------------------
- hostname: inventory hostname, needed for creation of answer file
- network
- keymap
- locale
Variables
---------
- freebsd_install_home_mirror:
- description:
- home URL of install packages of FreeBSD
- default: ftp://ftp.freebsd.org/pub/FreeBSD/releases
- freebsd_install_local_mirror:
- description:
- local URL of install packages of FreeBSD
- default: ""
Connection plugins
------------------
- sshjail
Filter plugins
--------------
- ip_in_range
- regex_filter_list
Module
------
- jail
Tools
-----
- git
- unarchive
Processes
=========
main
----
1. execute system configuration (see configure)
2. if container are used
2.1 create container root directory
2.2 install jail.conf, if not exists
2.3 enable jail support
2.4 install container functions
3. install native packages, if defined
configure
---------
1. execute basic system configuration
2. set network configuration for IPv4 and IPv6
3. restart network interfaces, if necessary
4. set DNS configuration
5. configure firewall (default: pf)
6. set keymap and locale
answerfile
----------
1. generate answerfile and store it to system_answerfile_path
createcontainer
---------------
1. check jail configuration
2. create jail container, if its are not suppressed
installer
---------
1. install build dependencies
2. build installer images for all given architectures and releases
2.1 create build directory
2.2 synchronise mfsBSD
2.3 set rc.conf entries
2.4 install unattended installer
2.5 copy ansible's public ssh key
2.6 install latest pkg-static
2.7 get installer files
2.8 create installer
2.9 register installer
2.10. cleanup installer image in build path
mirror
------
1. create mirror path, if not exists
2. download all FreeBSD release files of all given architectures and releases
3. download all package files of given architectures and releases
registercontainer
-----------------
1. if container are used and ansible_connection has the value ssh, register container with sshjail
2. if container are used and ansible_connection has the value local, register container with jail
3. set container_host variable
upgrade
-------
1. if system_upgrade_states is set
1.1 identify corresponded host of development environment
1.2 upgrade software of host system
1.3 migrate jails for corresponded host of development environment
2. if system_upgrade_states is not set
2.1 upgrade software of host system
2.2 upgrade software of container
3. reboot system if necessary
4. wait for system
---
system_home_mirror: "http://pkg.FreeBSD.org/"
freebsd_install_home_mirror: "ftp://ftp.freebsd.org/pub/FreeBSD/releases"
system_container_base_config: ""
system_container_root: "/var/jails"
package_packages: {
"freebsd" : ["gtar", "git"]
}
#!/bin/sh
echo "Installation complete, running in host system"
echo ${SSHAUTHKEY} > /etc/ssh/authorized_keys
echo "hostname=\"${HOST}\"" >> /etc/rc.conf
echo "autoboot_delay=\"5\"" >> /boot/loader.conf
echo "sshd_enable=\"YES\"" >> /etc/rc.conf
mkdir -p /usr/local/etc/pkg/repos/
echo 'localrepo: { url: "pkg+'${PKGREPO}'\${ABI}/latest", mirror_type: "srv", pkgenabled: yes }' > /usr/local/etc/pkg/repos/localrepo.conf
echo 'FreeBSD: { enabled: no }' > /usr/local/etc/pkg/repos/FreeBSD.conf
IFS="
"
for ifc in `env | grep "ifconfig"`
do
key=`echo ${ifc} | cut -f1 -d"="`
value=`echo ${ifc} | cut -f2 -d"="`
echo "${key}=\"${value}\"" >>/etc/rc.conf
done
for dom in `env | grep "defaultrouter"`
do
key=`echo ${dom} | cut -f1 -d"="`
value=`echo ${dom} | cut -f2 -d"="`
echo "${key}=\"${value}\"" >>/etc/rc.conf
done
for dom in `env | grep "domain"`
do
value=`echo ${dom} | cut -f2 -d"="`
echo "search ${value}" >>/etc/resolv.conf
done
for ns in `env | grep "nameserver"`
do
value=`echo ${ns} | cut -f2 -d"="`
echo "nameserver ${value}" >>/etc/resolv.conf
done
sed -i "" 's/"//g' /etc/resolv.conf
export ASSUME_ALWAYS_YES=yes
export PAGER=/bin/cat
pkg update
pkg install python27
sed -i -e 's/^#PermitRootLogin no/PermitRootLogin without-password/g' /etc/ssh/sshd_config
sed -i -e 's/^AuthorizedKeysFile.*/AuthorizedKeysFile \/etc\/ssh\/authorized_keys/g' /etc/ssh/sshd_config
sed -i -e 's/^#HostbasedAuthentication.*/HostbasedAuthentication yes/g' /etc/ssh/sshd_config
freebsd-update fetch
freebsd-update install
echo "Setup done" >> /tmp/log.txt
echo "Setup done."
reboot
/bin/sh
#!/bin/sh
echo "Installation complete, running in host system"
echo ${SSHAUTHKEY} > /etc/ssh/authorized_keys
echo "hostname=\"${HOST}\"" >> /etc/rc.conf
echo "autoboot_delay=\"5\"" >> /boot/loader.conf
echo "sshd_enable=YES" >> /etc/rc.conf
mkdir -p /usr/local/etc/pkg/repos/
echo 'localrepo: { url: "pkg+'${INSTREPO}'\${ABI}/latest", mirror_type: "srv", pkgenabled: yes }' > /usr/local/etc/pkg/repos/localrepo.conf
echo 'FreeBSD: { enabled: no }' > /usr/local/etc/pkg/repos/FreeBSD.conf
export ASSUME_ALWAYS_YES=yes
pkg update
pkg install python27
sed -i -e 's/^#PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config
sed -i -e 's/^#AuthorizedKeysFile.*/AuthorizedKeysFile \/etc\/ssh\/authorized_keys/g' /etc/ssh/sshd_config
sed -i -e 's/^#HostbasedAuthentication.*/HostbasedAuthentication yes/g' /etc/ssh/sshd_config
echo "Setup done" >> /tmp/log.txt
echo "Setup done."
reboot
/bin/sh
tftpserver=10.0.2.3
pxehostname=`/bin/hostname`
tftp tftp://${tftpserver}/${pxehostname}
/unattended.sh /${pxehostname}
tftpserver=`/bin/kenv -q net.pxe.tftpserver`
pxehostname=`/bin/kenv -q net.pxe.hostname`
tftp tftp://${tftpserver}/install/${pxehostname}
/unattended.sh /${pxehostname}
#!/bin/csh
#set installer settings to current environment
foreach line ("`cat $1`")
set key=`echo $line | cut -f1 -d"="`
set value=`echo $line | cut -f2 -d"="`
eval "setenv ${key} ${value}" #set for sub processes
if ( (${key} =~ ifconfig*) || (${key} =~ defaultrouter*) ) then
rm -rf /etc/rc.conf.d/network
echo ${line} >>/etc/rc.conf
endif
end
service netif restart
service routing restart
foreach line ("`cat $1`")
set key=`echo $line | cut -f1 -d"="`
set value=`echo $line | cut -f2 -d"="`
if ( (${key} =~ nameserver*) ) then
echo "nameserver ${value}" >>/etc/resolv.conf
endif
if ( (${key} =~ domain*) ) then
echo "search ${value}" >>/etc/resolv.conf
endif
end
if ( -f /etc/resolv.conf ) then
sed -i "" 's/"//g' /etc/resolv.conf
endif
set sak=`cat /root/.ssh/authorized_keys`
setenv SSHAUTHKEY "${sak}"
#prepare installerconfig
cat $1 installerconfig.tpl >/tmp/installerconfig
bsdinstall distfetch
bsdinstall script /tmp/installerconfig
from ansible import errors
def fbsdmfentry (entry, section, old = None):
try:
data = entry.split('\t')
if old == None or not type(old) is dict:
retval = dict()
else:
retval = old;
fpkg = data[0];
pkg = fpkg.replace(".txz", "")
if not pkg in retval:
retval[pkg] = {"new": "", "old": ""}
retval[pkg][section] = data[1]
return retval
except Exception, e:
raise errors.AnsibleFilterError(
'fbsdentry plugin error: {0}, entry={1}, section={2}'.format(str(e), str(entry), str(section)))
class FilterModule(object):
''' A filter to extract freebsd base package name with checksum and save it in a dict'''
def filters(self):
return {
'fbsdmfentry': fbsdmfentry
}
---
- name: set mfsbsd source root
set_fact:
mfsbsdroot: /var/src/mfsbsd
- name: create mfsbsd source root
file:
path: "{{ mfsbsdroot }}"
state: directory
recurse: yes
- name: get mfsbsd source
git:
repo: https://github.com/mmatuska/mfsbsd.git
dest: "{{ mfsbsdroot }}"
register: mfsbsdsrc
- name: set mfsbsd rc.conf
lineinfile:
dest: "{{ mfsbsdroot }}/conf/rc.conf"
line: "{{ rcline.line }}"
regexp: "{{ rcline.regexp }}"
create: yes
with_items:
- { line: 'sshd_enable="NO"', regexp: "^sshd_enable=" }
- { line: 'sendmail_enable="NONE"', regexp: "^sendmail_enable=" }
- { line: 'cron_enable="NO"', regexp: "^cron_enable=" }
- { line: 'local_enable="YES"', regexp: "^local_enable=" }
loop_control:
loop_var: rcline
- name: set mfsbsd rc.local which calls unattended installer
copy:
src: rc.local
dest: "{{ mfsbsdroot }}/conf/rc.local"
- name: set public ssh key to installer
copy:
src: "{{ '%s/sshkeys/ansible.pub' | format(ansible_keystore) }}"
dest: "{{ mfsbsdroot }}/conf/authorized_keys"
- name: create customfiles directory for mfsbsd
file:
path: "{{ mfsbsdroot }}/customfiles"
state: directory
- name: copy custom files
copy:
src: "{{ custfile.src }}"
dest: "{{ mfsbsdroot }}/customfiles/"
mode: "{{ custfile.mode }}"
with_items:
- { src: unattended.sh, mode: "0755" }
- { src: installerconfig.tpl, mode: "0755" }
loop_control:
loop_var: custfile
- name: create temporary directory for pkg package
tempfile:
state: directory
suffix: pkg
register: pkgtmpdir
- name: get pkg package from repository
get_url:
url: "{{ '%s/FreeBSD:%s:%s/latest/Latest/pkg.txz' | format(system_local_mirror | default(system_home_mirror), distdata[1] | regex_replace('\\.[0-9]*', ''), distdata[0]) }}"
dest: "{{ '%s/pkg.txz' | format(pkgtmpdir.path) }}"
- name: extract pkg package
unarchive:
src: "{{ '%s/pkg.txz' | format(pkgtmpdir.path) }}"
dest: "{{ pkgtmpdir.path }}"
remote_src: yes
- name: copy pkg-static to mfsbsd
copy:
src: "{{ '%s/usr/local/sbin/pkg-static' | format(pkgtmpdir.path) }}"
dest: "{{ '%s/tools/' | format(mfsbsdroot) }}"
remote_src: yes
- name: remove temporary pkg package directory
file:
path: "{{ pkgtmpdir.path }}"
state: absent
- name: create local install repository
file:
path: "{{ '%s/repo' | format(mfsbsdroot) }}"
state: directory
- name: get installer files from repository
get_url:
url: "{{ '%s/%s/%s-RELEASE/%s' | format(freebsd_install_local_mirror | default(freebsd_install_home_mirror), distdata[0], distdata[1], repofile) }}"
dest: "{{ '%s/repo/%s' | format(mfsbsdroot, repofile) }}"
with_items:
- "base.txz"
- "kernel.txz"
loop_control:
loop_var: repofile
- name: create installer image
make:
chdir: "{{ mfsbsdroot }}"
target: "image"
params:
BASE: "{{ '%s/repo' | format(mfsbsdroot) }}"
ARCH: "{{ distdata[0] }}"
MFSROOT_MAXSIZE: 2500m
- name: register installer
include_role:
name: package.pxelinux
tasks_from: registerimage
vars:
pxelinux_image_buildpath: "{{ '%s/mfsbsd-%s-RELEASE-%s.img' | format(mfsbsdroot, distdata[1], distdata[0]) }}"
pxelinux_image_distribution: "freebsd"
pxelinux_image_release: "{{ distdata[1] }}"
pxelinux_image_architecture: "{{ distdata[0] }}"
- name: cleanup installer image
make:
chdir: "{{ mfsbsdroot }}"
target: "clean"
- file:
path: "{{ '%s/mfsbsd-%s-RELEASE-%s.img' | format(mfsbsdroot, distdata[1], distdata[0]) }}"
state: absent
---
- set_fact:
fuprm: ""
- set_fact:
puprm: ""
- block:
- jail:
name: "{{ container.name }}"
state: state
register: cstate
- set_fact:
fuprm: "{{ '-b %s' | format(cstate.path) }}"
- set_fact:
puprm: "{{ '-j %s' | format(container.name) }}"
when: container is defined
- name: fetch system updates
command: "{{ '/usr/sbin/freebsd-update %s --not-running-from-cron fetch' | format(fuprm) }}"
environment:
PAGER: /bin/cat
register: fuout
- name: install updates
command: "{{ '/usr/sbin/freebsd-update %s install' | format(fuprm) }}"
when: (fuout.stdout_lines | regex_filter_list('^[/]') | length()) > 0
- name: update repository lists
command: "{{ '/usr/sbin/pkg %s update' | format(puprm) }}"
- name: upgrade packages
command: "{{ '/usr/sbin/pkg %s upgrade' | format(puprm) }}"
environment:
ASSUME_ALWAYS_YES: "yes"
register: puout
- name: cleanup caches
command: "{{ '/usr/sbin/pkg %s clean' | format(puprm) }}"
environment:
ASSUME_ALWAYS_YES: "yes"
- set_fact:
us: "{{ (puout.stdout_lines | regex_filter_list('->') | length()) > 0 or (fuout.stdout_lines | regex_filter_list('^[/]') | length()) > 0 }}"
- set_fact:
upgraded: "{{ upgraded | combine({ 'host': us }) }}"
when: container is not defined
- block:
- set_fact:
upgraded: "{{ upgraded | combine({ container.name: us}) }}"
- jail:
name: "{{ container.name }}"
state: restart
when: upgraded[container.name] == True and upgraded["host"] == False
when: container is defined
- name: gathering IP addresses for "{{ container.name }}"
set_fact:
container_options: {}
- set_fact:
container_options: >-
{% set opts = {} -%}
{% if item.service == container.name -%}
{% do opts.update({'ipv4': ((container_options | default({})).ipv4 | default([])) + [item.ipv4]}) if item.ipv4 is defined and not (item.ipv4 in ((container_options | default({})).ipv4 | default([]))) -%}
{% do opts.update({'ipv6': ((container_options | default({})).ipv6 | default([])) + [item.ipv6]}) if item.ipv6 is defined and not (item.ipv6 in ((container_options | default({})).ipv6 | default([]))) -%}
{% endif -%}
{{ (container_options | default({})) | combine(opts) }}
when: item.service is defined
with_items: "{{ network.nat | default([]) }}"
- set_fact:
container_options: >-
{% set opts = {} -%}
{% if item.value.service == container.name -%}
{% do opts.update({'ipv4': ((container_options | default({})).ipv4 | default([])) + [item.value.ipv4]}) if item.value.ipv4 is defined and not (item.ipv4 in ((container_options | default({})).ipv4 | default([]))) -%}
{% do opts.update({'ipv6': ((container_options | default({})).ipv6 | default([])) + [item.value.ipv6]}) if item.value.ipv6 is defined and not (item.ipv6 in ((container_options | default({})).ipv6 | default([]))) -%}
{% endif -%}
{{ (container_options | default({})) | combine(opts) }}
when: item.value.service is defined
with_dict: "{{ network.devices | default({}) }}"
- set_fact:
container: >-
{% do container.container_options.update({'ip4.addr': container_options.ipv4 | join(',')}) if container_options.ipv4 is defined -%}
{% do container.container_options.update({'ip6.addr': container_options.ipv6 | join(',')}) if container_options.ipv6 is defined -%}
{{ container }}
- name: install fstab for container
template:
src: "{{ '%s.j2' | format(container.container_options['mount.fstab'] | basename) }}"
dest: "{{ '/etc/%s' | format(container.container_options['mount.fstab'] | basename) }}"
mode: 0644
- name: create "{{ container.name }}" container
jail:
name: "{{ container.name }}"
mirror: "{{ freebsd_install_local_mirror | default(freebsd_install_home_mirror) }}"
rcconf:
sendmail_enable: "NONE"
packages:
- python27
usehostdns: yes
usehostrepo: yes
create_nullfs: yes
state: create
options: "{{ container.container_options }}"
- name: start "{{ container.name }}" container
jail:
name: "{{ container.name }}"
state: start
- import_tasks: registercontainer.yml
- name: install and configure container package
include_tasks: _pkginstall.yml
- name: set ABI variable
set_fact:
FBSD_ABI: "{{ 'FreeBSD:%s:%s' | format(distdata[1] | regex_replace('\\.[0-9]*', ''), distdata[0]) }}"
- name: set package path varible
set_fact:
pkg_path: "{{ '%s/FreeBSD/%s' | format(system_mirror_directory, FBSD_ABI) }}"
- name: create package directories
file:
path: "{{ pkg_path }}"
recurse: yes
state: directory
- name: fetch packages
shell: "{{ 'pkg fetch -q -y -d -o %s %s' | format(pkg_path, system_gathered_packages | join(' ')) }}"
environment:
ABI: "{{ FBSD_ABI }}"
- name: create reposity data
shell: "{{ 'pkg repo %s' | format(pkg_path) }}"
- import_role:
name: "{{ 'package.%s' | format(container.name) }}"
delegate_to: "{{ inventory_hostname }}_{{ container.name | upper() }}"
---
- name: set release path variable
set_fact:
release_path: "{{ '%s/FreeBSD/releases/%s/%s-RELEASE' | format(system_mirror_directory, distdata[0], distdata[1]) }}"
- name: reset chksums fact
set_fact:
chksums: "{{ {} }}"
- name: create release directories
file:
path: "{{ release_path }}"
recurse: yes
state: directory
- name: create MANIFEST, if not exists
file:
path: "{{ '%s/MANIFEST' | format(release_path) }}"
state: touch
- name: get remote package checksums
set_fact:
chksums: "{{ bspkg | fbsdmfentry('new', chksums | default({})) }}"
with_url:
- "{{ '%s/%s/%s-RELEASE/MANIFEST' | format(freebsd_install_home_mirror, distdata[0], distdata[1]) }}"
loop_control:
loop_var: bspkg
- name: get local MANIFEST
fetch:
src: "{{ '%s/MANIFEST' | format(release_path) }}"
dest: "/tmp/MANIFEST"
flat: yes
- name: get local package checksums
set_fact:
chksums: "{{ bspkg | fbsdmfentry('old', chksums | default({})) }}"
when: bspkg != ""
with_items:
- "{{ lookup('file', '/tmp/MANIFEST') | split('\n') }}"
loop_control:
loop_var: bspkg
- name: delete local MANIFEST
file:
path: "/tmp/MANIFEST"
state: absent
delegate_to: localhost
- name: download base packages
get_url:
url: "{{ '%s/%s/%s-RELEASE/%s.txz' | format(freebsd_install_home_mirror, distdata[0], distdata[1], bspkg.key) }}"
dest: "{{ '%s/%s.txz' | format(release_path, bspkg.key) }}"
force: yes
when: bspkg.value.new != (bspkg.value.old | default(""))
with_dict: "{{ chksums }}"
loop_control:
loop_var: bspkg
- name: download base packages
get_url:
url: "{{ '%s/%s/%s-RELEASE/MANIFEST' | format(freebsd_install_home_mirror, distdata[0], distdata[1]) }}"
dest: "{{ '%s/MANIFEST' | format(release_path) }}"
force: yes
- name: create answerfile for "{{ hostname }}"
template:
src: answerfile.j2
dest: "{{ system_answerfile_path }}"
- include_role:
name: system
tasks_from: configure
- set_fact:
dhcp_ranges: >-
{% set range = {} -%}
{% if item.value.dhcp is defined -%}
{% do range.update({item.key: {}}) -%}
{% if item.value.dhcp.ipv4 is defined -%}
{% do range[item.key].update({"ipv4": {"from": item.value.dhcp.ipv4.from, "to": item.value.dhcp.ipv4.to}}) -%}
{% else -%}
{% do range[item.key].update({"ipv4": {"from": "0.0.0.0", "to": "0.0.0.0"}}) -%}
{% endif -%}
{% if item.value.dhcp.ipv6 is defined -%}
{% do range[item.key].update({"ipv6": {"from": item.value.dhcp.ipv6.from, "to": item.value.dhcp.ipv6.to}}) -%}
{% else -%}
{% do range[item.key].update({"ipv6": {"from": "::0", "to": "::0"}}) -%}
{% endif -%}
{% else -%}
{% do range.update({item.key: {"ipv4": {"from": "0.0.0.0", "to": "0.0.0.0"}, "ipv6": {"from": "::0", "to": "::0"}}}) -%}
{% endif -%}
{{ dhcp_ranges | default({}) | combine(range) }}
with_dict: "{{ network.classes }}"
- stat:
path: "/etc/rc.conf"
register: bfnetstrc
- name: set static ipv4 network interfaces
lineinfile:
dest: "/etc/rc.conf"
line: "{{ 'ifconfig_%s=\"inet %s netmask %s\"' | format(item.key, item.value.ipv4, '%s/%s' | format(item.value.ipv4, network.classes[item.value.class].ipv4.prefix) | ipaddr('netmask')) }}"
regexp: "{{ '^ifconfig_%s=' | format(item.key) }}"
create: yes
when: not (item.value.ipv4 | default(False) | ip_in_range('%s-%s' | format(dhcp_ranges[item.value.class].ipv4.from, dhcp_ranges[item.value.class].ipv4.to))) and item.value.ipv4 is defined
with_dict: "{{ network.devices }}"
- name: set dynamic ipv4 network interfaces
lineinfile:
dest: "/etc/rc.conf"
line: "{{ 'ifconfig_%s=\"SYNCDHCP\"' | format(item.key) }}"
regexp: "{{ '^ifconfig_%s=' | format(item.key) }}"
create: yes
when: (item.value.ipv4 | default(False) | ip_in_range('%s-%s' | format(dhcp_ranges[item.value.class].ipv4.from, dhcp_ranges[item.value.class].ipv4.to))) and item.value.ipv4 is defined
with_dict: "{{ network.devices }}"
- name: set ipv4 default gateway
lineinfile:
dest: "/etc/rc.conf"
line: "{{ 'defaultgateway=\"%s\"' | format(item.value.ipv4.gateway) }}"
regexp: "^defaultgateway="
create: yes
when: (item.value.default | default(False)) == True and item.value.ipv6 is defined
with_dict: "{{ network.classes }}"
- name: set static ipv6 network interfaces
lineinfile: