Browse Source

Erste FFDO Version (basierend auf FFMS)

Stefan Heinrichsen 5 years ago
commit
79a43af306
100 changed files with 4560 additions and 0 deletions
  1. 4 0
      .gitignore
  2. 0 0
      README.md
  3. 9 0
      all.yml
  4. 10 0
      ansible.cfg
  5. 3 0
      roles/backbone_gre_ffms/handlers/main.yml
  6. 12 0
      roles/backbone_gre_ffms/tasks/main.yml
  7. 28 0
      roles/backbone_gre_ffms/templates/gre_interbackbone.j2
  8. 3 0
      roles/backbone_gre_ffrl/handlers/main.yml
  9. 47 0
      roles/backbone_gre_ffrl/tasks/main.yml
  10. 20 0
      roles/backbone_gre_ffrl/templates/gre_ffrl.j2
  11. 9 0
      roles/backports-kernel/handlers/main.yml
  12. 27 0
      roles/backports-kernel/tasks/main.yml
  13. 84 0
      roles/batman_build/tasks/main.yml
  14. 10 0
      roles/batman_build/templates/dkms.conf
  15. 14 0
      roles/bird/files/bird.service
  16. 14 0
      roles/bird/files/bird6.service
  17. 7 0
      roles/bird/handlers/main.yml
  18. 128 0
      roles/bird/tasks/main.yml
  19. 9 0
      roles/bird/templates/batman.conf.j2
  20. 9 0
      roles/bird/templates/batman6.conf.j2
  21. 26 0
      roles/bird/templates/bird.conf.j2
  22. 22 0
      roles/bird/templates/bird6.conf.j2
  23. 194 0
      roles/bird/templates/bird6_ms.conf.j2
  24. 194 0
      roles/bird/templates/bird_ms.conf.j2
  25. 41 0
      roles/bird/templates/ospf.conf.j2
  26. 37 0
      roles/bird/templates/ospf6.conf.j2
  27. 5 0
      roles/bird/templates/temp/batman.conf
  28. 290 0
      roles/bird/templates/temp/ff6.conf_dis
  29. 290 0
      roles/bird/templates/temp/ffms.conf_dis
  30. 4 0
      roles/calculate_missing_inventory_variables/tasks/find_partner.yml
  31. 7 0
      roles/calculate_missing_inventory_variables/tasks/main.yml
  32. 3 0
      roles/calculate_missing_inventory_variables/tasks/per_host.yml
  33. 37 0
      roles/calculate_missing_inventory_variables/tasks/set_calculation_needed.yml
  34. 24 0
      roles/collectd/README.md
  35. 4 0
      roles/collectd/handlers/main.yml
  36. 103 0
      roles/collectd/tasks/main.yml
  37. 999 0
      roles/collectd/templates/collectd.conf.j2
  38. 4 0
      roles/collectd/templates/collection.conf.j2
  39. 123 0
      roles/collectd/templates/dhcp.py.j2
  40. 106 0
      roles/collectd/templates/fastd.py.j2
  41. 35 0
      roles/collectd/templates/filters.conf.j2
  42. 45 0
      roles/collectd/templates/ipv4ipv6.py.j2
  43. 66 0
      roles/collectd/templates/kea.py.j2
  44. 32 0
      roles/collectd/templates/l2tp.py.j2
  45. 23 0
      roles/collectd/templates/sysctl.py.j2
  46. 52 0
      roles/collectd/templates/thresholds.conf.j2
  47. 5 0
      roles/common/handlers/main.yml
  48. 135 0
      roles/common/tasks/main.yml
  49. 4 0
      roles/common/templates/authorized_keys.j2
  50. 35 0
      roles/common/templates/bash_profile.j2
  51. 52 0
      roles/common/templates/logrotate.conf.j2
  52. 6 0
      roles/dhcp/handlers/main.yml
  53. 22 0
      roles/dhcp/tasks/main.yml
  54. 26 0
      roles/dhcp/templates/dhcpd.conf.j2
  55. 8 0
      roles/dhcp/templates/dhcpd6.conf.j2
  56. 3 0
      roles/dhcp/templates/isc-dhcp-server.j2
  57. 115 0
      roles/dhcp/templates/isc-dhcp6-server.init.j2
  58. 21 0
      roles/dhcp/templates/isc-dhcp6-server.j2
  59. 3 0
      roles/dienste_lamp/handlers/main.yml
  60. 151 0
      roles/dienste_lamp/tasks/main.yml
  61. 3 0
      roles/dienste_lamp/templates/my.cnf.j2
  62. 13 0
      roles/dienste_lamp/templates/virthost.conf.j2
  63. 104 0
      roles/dienste_osticket/tasks/main.yml
  64. 8 0
      roles/fastd/files/status.pl
  65. 4 0
      roles/fastd/handlers/main.yml
  66. 68 0
      roles/fastd/tasks/main.yml
  67. 3 0
      roles/fastd/templates/dummy.j2
  68. 56 0
      roles/fastd/templates/fastd.conf.j2
  69. 2 0
      roles/fastd/templates/public.key.j2
  70. 2 0
      roles/fastd/templates/secret.key.j2
  71. 13 0
      roles/fastd/templates/verify.sh.j2
  72. 1 0
      roles/gateways_2nd_vnic/handlers/main.yml
  73. 6 0
      roles/gateways_2nd_vnic/tasks/2nd_vnic_interface.yml
  74. 3 0
      roles/gateways_2nd_vnic/tasks/main.yml
  75. 14 0
      roles/gateways_2nd_vnic/templates/2nd_vnic_interface.cfg.j2
  76. 6 0
      roles/gateways_batman/handlers/main.yml
  77. 21 0
      roles/gateways_batman/tasks/main.yml
  78. 47 0
      roles/gateways_batman/templates/batman.j2
  79. 3 0
      roles/gateways_dhcp/handlers/main.yml
  80. 45 0
      roles/gateways_dhcp/tasks/main.yml
  81. 2 0
      roles/gateways_dhcp/templates/closeramdisk.j2
  82. 14 0
      roles/gateways_dhcp/templates/dhcpd-tmpfs.service.j2
  83. 28 0
      roles/gateways_dhcp/templates/dhcpd.conf.j2
  84. 3 0
      roles/gateways_dhcp/templates/isc-dhcp-server.j2
  85. 2 0
      roles/gateways_dhcp/templates/openramdisk.j2
  86. 3 0
      roles/gateways_gre_upstream/handlers/main.yml
  87. 23 0
      roles/gateways_gre_upstream/tasks/main.yml
  88. 39 0
      roles/gateways_gre_upstream/templates/gre_upstream.j2
  89. 20 0
      roles/gateways_gre_upstream/templates/lo.j2
  90. 3 0
      roles/gateways_gretap/handlers/main.yml
  91. 16 0
      roles/gateways_gretap/tasks/main.yml
  92. 39 0
      roles/gateways_gretap/templates/gretap.j2
  93. 3 0
      roles/gateways_kea_build/handlers/main.yml
  94. 52 0
      roles/gateways_kea_build/tasks/main.yml
  95. 14 0
      roles/gateways_kea_build/templates/kea-dhcp-ddns.service.j2
  96. 14 0
      roles/gateways_kea_build/templates/kea-dhcp4.service.j2
  97. 14 0
      roles/gateways_kea_build/templates/kea-dhcp6.service.j2
  98. 2 0
      roles/gateways_kea_configure/handlers/main.yml
  99. 48 0
      roles/gateways_kea_configure/tasks/main.yml
  100. 0 0
      roles/gateways_kea_configure/templates/keav4.conf.j2

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+*.retry
+**/*.repokey
+*.tmp.json
+passwords.yml

+ 0 - 0
README.md


+ 9 - 0
all.yml

@@ -0,0 +1,9 @@
+---
+# Playbook zur Basis-Konfiguration von allen Servern 
+
+- hosts: all 
+  remote_user: root
+  roles:
+    - { role: hostname, tags: "hostname"}
+    - { role: common, tags: "common"}
+    - { role: motd, tags: "motd"}

+ 10 - 0
ansible.cfg

@@ -0,0 +1,10 @@
+[defaults]
+inventory=inventory/hosts
+#vault_password_file=.vault-password
+
+[privilege_escalation]
+become=True
+
+[ssh_connection]
+pipelining=True
+

+ 3 - 0
roles/backbone_gre_ffms/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: restart networking
+  shell: systemctl restart networking; if systemctl -q is-active isc-dhcp-server; then systemctl restart isc-dhcp-server; fi; if systemctl -q is-active kea-dhcp4.service; then systemctl restart kea-dhcp4.service; fi; if systemctl -q is-active tunneldigger; then systemctl restart tunneldigger; fi

+ 12 - 0
roles/backbone_gre_ffms/tasks/main.yml

@@ -0,0 +1,12 @@
+---
+- name: Tunnels between backbones
+  template: src="gre_interbackbone.j2" dest="/etc/network/interfaces.d/42_gre_interbackbone.cfg"
+  notify: restart networking
+
+- name: Routingtabelle 42 auch ffnet nennen
+  lineinfile: dest="/etc/iproute2/rt_tables" line="42   ffnet"
+
+#append line in interfaces file for reading additional config files
+- name: let read interfaces.d from interfaces
+  lineinfile: dest="/etc/network/interfaces" line="source /etc/network/interfaces.d/*"
+  notify: restart networking

+ 28 - 0
roles/backbone_gre_ffms/templates/gre_interbackbone.j2

@@ -0,0 +1,28 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+{% for host in groups['gateways']+groups['domaene-06'] %}
+{% if host != inventory_hostname %}
+auto bck-{{host}}
+iface bck-{{host}} inet static
+{% if hostvars[host].vm_id < vm_id %}
+        address 192.168.{{ hostvars[host].vm_id-1 }}.{{vm_id*2+1}}
+{% else %}
+        address 192.168.{{ vm_id-1 }}.{{hostvars[host].vm_id*2}}
+{% endif %}
+        netmask 31
+        pre-up ip link add $IFACE type gre local {{ansible_default_ipv4.address}} remote {{hostvars[host].ansible_ssh_host}} ttl 255
+        pre-up ip link set $IFACE up multicast on
+        post-up ip rule add iif $IFACE table ffnet
+        pre-down ip rule del iif $IFACE table ffnet ||:
+iface bck-{{host}} inet6 static
+{% if hostvars[host].vm_id < vm_id %}
+        address 2a03:2260:115:ffa1::{{hostvars[host].vm_id}}:{{vm_id}}:0
+{% else %}
+        address 2a03:2260:115:ffa1::{{vm_id}}:{{hostvars[host].vm_id}}:1
+{% endif %}
+        netmask 127
+        post-up ip -6 rule add iif $IFACE table ffnet
+        pre-down ip -6 rule del iif $IFACE table ffnet ||:
+        post-down ip link delete $IFACE
+
+{% endif %}
+{% endfor %}

+ 3 - 0
roles/backbone_gre_ffrl/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: restart networking
+  shell: systemctl restart networking; if systemctl -q is-active isc-dhcp-server; then systemctl restart isc-dhcp-server; fi; if systemctl -q is-active kea-dhcp4.service; then systemctl restart kea-dhcp4.service; fi; if systemctl -q is-active tunneldigger; then systemctl restart tunneldigger; fi

+ 47 - 0
roles/backbone_gre_ffrl/tasks/main.yml

@@ -0,0 +1,47 @@
+---
+# Tasks for network interfaces
+
+# adding ffrl natv4 address to loopback adapter
+- name: Create interfaces - add ffrl to loopback
+  lineinfile: 
+     dest='/etc/network/interfaces'
+     regexp='^[ \t]+up ip address add.*$'
+     insertafter='^iface lo inet loopback.*$'
+     line='        up ip address add {{ffrl_nat_ip}} dev lo'
+  when: ffrl_tun is defined
+
+- name: Create interfaces - add ffrl-rule to loopback
+  lineinfile: 
+     dest='/etc/network/interfaces'
+     regexp='^[ \t]+up ip rule add from.*$'
+     insertafter='^[ \t]+up ip address add.*$'
+     line='        up ip rule add from {{ffrl_nat_ip}} table ffnet'
+  when: ffrl_tun is defined
+
+- name: Create interfaces - add suppress_prefixlength-rule
+  lineinfile: 
+     dest='/etc/network/interfaces'
+     insertafter='^[ \t]+up ip rule add from.*$'
+     line='        up ip rule add iif lo table ffnet suppress_prefixlength 0'
+  when: ffrl_tun is defined
+
+- name: Create interfaces - add v6 suppress_prefixlength-rule
+  lineinfile: 
+     dest='/etc/network/interfaces'
+     insertafter='^[ \t]+up ip rule add iif lo table ffnet suppress_prefixlength 0.*$'
+     line='        up ip -6 rule add iif lo table ffnet suppress_prefixlength 0'
+  when: ffrl_tun is defined
+
+# creating gretap tunnels to ffrl
+- name: Create interfaces - gretap to ffrl
+  template: src="gre_ffrl.j2" dest="/etc/network/interfaces.d/40_gre_ffrl.cfg"
+  notify:
+    - restart networking
+  when: ffrl_tun is defined
+
+#append line in interfaces file for reading additional config files
+- name: let read interfaces from interfaces
+  lineinfile: dest="/etc/network/interfaces" line="source /etc/network/interfaces.d/*"
+  notify:
+    - restart networking
+  when: ffrl_tun is defined

+ 20 - 0
roles/backbone_gre_ffrl/templates/gre_ffrl.j2

@@ -0,0 +1,20 @@
+# GRE Tunnel zum Rheinland Backbone
+# Die Konfigurationsdaten werden vom Rheinland Backbone vergeben und zugewiesen
+{% for tun in ffrl_tun %}
+
+auto tun-ffrl-{{tun.name}}
+iface tun-ffrl-{{tun.name}} inet static
+        address {{tun.v4_remote | ipaddr( tun.v4_remote.split('.')[3] | int + 1) | ipaddr('address') }}
+        netmask {{tun.v4_remote | ipaddr('netmask')}}
+        pre-up ip tunnel add $IFACE mode gre local {{ansible_default_ipv4.address}} remote {{tun.gre_target | ipaddr('address') }} ttl 255
+        post-up ip link set $IFACE mtu 1400
+        post-down ip tunnel del $IFACE
+        post-up ip rule add iif $IFACE lookup ffnet
+        pre-down ip rule del iif $IFACE lookup ffnet ||:
+
+iface tun-ffrl-{{tun.name}} inet6 static
+        address {{tun.v6_remote | ipaddr('2') | ipaddr('address') }}
+        netmask {{tun.v6_remote | ipaddr('prefix')}}
+        post-up ip -6 rule add iif $IFACE lookup ffnet
+        pre-down ip -6 rule del iif $IFACE lookup ffnet ||:
+{% endfor %}

+ 9 - 0
roles/backports-kernel/handlers/main.yml

@@ -0,0 +1,9 @@
+---
+- name: Neustarten
+  shell: sleep 2 && shutdown -r now "Ansible updates triggered"
+  async: 1
+  poll: 0
+  ignore_errors: true
+
+- name: Neustart abwarten
+  local_action: wait_for port={{ ansible_ssh_port }} host={{ ansible_host }} state=started delay=60 timeout=900 connect_timeout=15

+ 27 - 0
roles/backports-kernel/tasks/main.yml

@@ -0,0 +1,27 @@
+- name: add backports repo
+  apt_repository:
+    repo: "{{ item }}"
+    state: present
+  with_items:
+    - "deb http://ftp.de.debian.org/debian {{ ansible_distribution_release }}-backports main"
+  when: ansible_distribution == "Debian"
+  register: apt
+
+- name: update apt cache
+  apt:
+    update_cache: yes
+  when: apt.changed
+
+- name: install backports-kernel
+  apt: 
+    name: "{{item}}"
+    default_release: jessie-backports
+    state: latest
+  when: ansible_distribution == "Debian"
+  with_items:
+    - linux-headers-amd64
+    - linux-image-amd64
+  notify: 
+    - Neustarten
+    - Neustart abwarten
+

+ 84 - 0
roles/batman_build/tasks/main.yml

@@ -0,0 +1,84 @@
+- name: Abhängigkeiten installieren
+  apt:
+    pkg: "{{ item }}"
+    state: present
+  with_items:
+    - dkms
+    - build-essential
+    - linux-headers-{{ansible_kernel}}
+    - checkinstall
+    - pkg-config
+    - libnl-3-dev
+    - libnl-genl-3-dev
+
+- name: create directory for batman-adv
+  file:
+    name: /opt/batman-adv
+    state: directory
+
+- name: Download Batman 
+  get_url:
+    url: "https://downloads.open-mesh.org/batman/releases/batman-adv-{{batman_version}}/batman-adv-{{batman_version}}.tar.gz"
+    dest: /opt/batman-adv/batman-adv-{{batman_version}}.tar.gz
+  register: getbatman
+
+- name: batman-Quellen entpacken
+  unarchive:
+    src: /opt/batman-adv/batman-adv-{{batman_version}}.tar.gz
+    dest: /usr/src
+    remote_src: True
+  when: 
+    - getbatman.changed
+
+- name: configure dkms
+  template: 
+    src: dkms.conf
+    dest: /usr/src/batman-adv-{{batman_version}}/dkms.conf
+
+- stat: 
+    path: /lib/modules/{{ansible_kernel}}/updates/dkms/batman-adv.ko
+  register: batman_adv_file
+
+- name: Batman bauen
+  shell: "dkms add -m batman-adv -v {{batman_version}} && dkms build -m batman-adv -v {{batman_version}} && dkms install -m batman-adv -v {{batman_version}}"
+  when:
+    - batman_adv_file.stat.exists == False or getbatman.changed
+
+# batctl
+- name: create directory for batctl
+  file:
+    name: /opt/batctl
+    state: directory
+
+- name: get batctl
+  get_url:
+    url: "https://downloads.open-mesh.org/batman/releases/batman-adv-{{batman_version}}/batctl-{{batman_version}}.tar.gz"
+    dest: /opt/batctl/batctl-{{batman_version}}.tar.gz
+  register: getbatctl
+
+- name: batctl-Quellen und entpacken
+  unarchive:
+    src: /opt/batctl/batctl-{{batman_version}}.tar.gz
+    dest: /usr/src
+    remote_src: True
+  when:
+    - getbatctl.changed
+
+- stat: path=/usr/local/sbin/batctl
+  register: batctl
+
+- name: batctl Version prüfen
+  shell: '{{batctl.stat.path}} -v | grep -oE "batctl [0-9]+\.[0-9]+"'
+  when: 
+    - batctl.stat.exists == True
+  changed_when: False
+  register: batctl_version
+  check_mode: no
+
+- name: batctl bauen
+  shell: "make && checkinstall -y make install"
+  args:
+    chdir: /usr/src/batctl-{{batman_version}}
+  when:
+    - batctl.stat.exists == False or batctl_version.stdout_lines[0] != "batctl {{batman_version}}"
+#    - batctl.stat.exists == False or batctl_version.stdout_lines[0] != "batctl batman_version"

+ 10 - 0
roles/batman_build/templates/dkms.conf

@@ -0,0 +1,10 @@
+PACKAGE_NAME='batman-adv'
+PACKAGE_VERSION="{{ batman_version }}"
+
+BUILT_MODULE_NAME[0]="batman-adv"
+BUILT_MODULE_LOCATION[0]="build/net/batman-adv/"
+DEST_MODULE_LOCATION[0]="/kernel/net/batman-adv/"
+AUTOINSTALL=yes
+
+MAKE[0]="make KERNELPATH=${kernel_source_dir}"
+CLEAN="make KERNELPATH=${kernel_source_dir} clean"

+ 14 - 0
roles/bird/files/bird.service

@@ -0,0 +1,14 @@
+[Unit]
+Description=BIRD Internet Routing Daemon (IPv4)
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/bird/envvars
+ExecStartPre=/usr/lib/bird/prepare-environment
+ExecStartPre=/usr/sbin/bird -p
+ExecReload=/usr/sbin/birdc configure
+ExecStart=/usr/sbin/bird -f -u $BIRD_RUN_USER -g $BIRD_RUN_GROUP $BIRD_ARGS
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target

+ 14 - 0
roles/bird/files/bird6.service

@@ -0,0 +1,14 @@
+[Unit]
+Description=BIRD Internet Routing Daemon (IPv6)
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/bird/envvars
+ExecStartPre=/usr/lib/bird/prepare-environment
+ExecStartPre=/usr/sbin/bird6 -p
+ExecReload=/usr/sbin/birdc6 configure
+ExecStart=/usr/sbin/bird6 -f -u $BIRD_RUN_USER -g $BIRD_RUN_GROUP $BIRD_ARGS
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target

+ 7 - 0
roles/bird/handlers/main.yml

@@ -0,0 +1,7 @@
+---
+- name: configure bird
+  shell: birdc configure || systemctl restart bird
+
+- name: configure bird6
+  shell: birdc6 configure || systemctl restart bird6
+

+ 128 - 0
roles/bird/tasks/main.yml

@@ -0,0 +1,128 @@
+---
+# Role for configure bird and bird6 for our gateway servers.
+- name: add key for bird repo
+  apt_key:
+    keyserver: keyserver.ubuntu.com 
+    id: AC0E47584A7A714D
+  when: ansible_distribution == "Debian"
+
+- name: add bird repo
+  apt_repository:
+    repo: "deb http://bird.network.cz/debian/ {{ ansible_distribution_release }} main"
+    state: present
+  when: ansible_distribution == "Debian" and ansible_distribution_major_version == "8"
+
+- name: install bird and other required packets
+  apt:
+    pkg: "{{item}}"
+    update_cache: yes
+    cache_valid_time: 1800
+    state: present
+  with_items:
+    - bird
+    - bird6
+    - ipcalc
+  when: ansible_distribution == "Debian" and ansible_distribution_major_version == "8"
+
+- name: install bird and other required packets
+  apt:
+    pkg: "{{item}}"
+    update_cache: yes
+    cache_valid_time: 1800
+    state: present
+  with_items:
+    - bird
+    - ipcalc
+  when: (ansible_distribution == "Ubuntu") or
+        (ansible_distribution == "Debian" and ansible_distribution_major_version == "9")
+
+- name: calculate more specific routes for DHCP pools
+  shell: ipcalc {{ domaenenliste[item].dhcp_start }} - {{ domaenenliste[item].dhcp_ende}} | grep -v "deaggregate" | sed -e 's/\(^.*$\)/route \1 via "bat{{item}}";/g'
+  check_mode: no
+  changed_when: false
+  register: more_specific_routes
+  with_items: "{{domaenenliste | default([])}}"
+  when: domaenenliste is defined
+
+- name: configure bird.conf
+  template: 
+    src: bird.conf.j2
+    dest: /etc/bird/bird.conf
+  notify:
+    - configure bird
+
+- name: general (disabled) bird.conf from MS setup
+  template: 
+    src: bird_ms.conf.j2
+    dest: /etc/bird/conf.d/ffms.conf_dis
+  notify:
+    - configure bird
+
+
+- name: configure batman.conf
+  template: 
+    src: batman.conf.j2
+    dest: /etc/bird/conf.d/batman.conf
+  notify:
+    - configure bird
+
+- name: configure ospf.conf (temporary nat-routing over old supernodes)
+  template: 
+    src: ospf.conf.j2
+    dest: /etc/bird/conf.d/ospf.conf
+  notify:
+    - configure bird
+
+- name: configure bird6.conf
+  template:
+    src: bird6.conf.j2
+    dest: /etc/bird/bird6.conf
+  notify:
+    - configure bird6
+
+- name: general (disabled) bird6.conf from MS setup
+  template: 
+    src: bird_ms.conf.j2
+    dest: /etc/bird/conf6.d/ffms6.conf_dis
+  notify:
+    - configure bird
+
+- name: configure batman6.conf
+  template: 
+    src: batman6.conf.j2
+    dest: /etc/bird/conf6.d/batman6.conf
+  notify:
+    - configure bird
+
+- name: configure ospf6.conf (temporary routing over old supernodes)
+  template: 
+    src: ospf6.conf.j2
+    dest: /etc/bird/conf6.d/ospf6.conf
+  notify:
+    - configure bird
+
+- name: bird.service kopieren
+  copy: 
+    src: bird.service
+    dest: /lib/systemd/system/bird.service
+  notify:
+    - configure bird
+
+- name: bird6.service kopieren
+  copy: 
+    src: bird6.service
+    dest: /lib/systemd/system/bird6.service
+  notify:
+    - configure bird6
+
+- name: activate and start bird
+  service:
+    name: bird
+    state: started 
+    enabled: yes
+
+- name: activate and start bird6
+  service: 
+    name: bird6
+    state: started
+    enabled: yes

+ 9 - 0
roles/bird/templates/batman.conf.j2

@@ -0,0 +1,9 @@
+{% if domaenenliste is defined %}
+{% for domaene in domaenenliste|dictsort %}
+
+protocol direct bat{{domaene[0]}} {
+        interface "bat{{domaene[0]}}";
+};
+
+{% endfor %}
+{% endif %}

+ 9 - 0
roles/bird/templates/batman6.conf.j2

@@ -0,0 +1,9 @@
+{% if domaenenliste is defined %}
+{% for domaene in domaenenliste|dictsort %}
+
+protocol direct bat{{domaene[0]}} {
+        interface "bat{{domaene[0]}}";
+};
+
+{% endfor %}
+{% endif %}

+ 26 - 0
roles/bird/templates/bird.conf.j2

@@ -0,0 +1,26 @@
+# Managed by Ansible... do not update manually as changes will be overwritten
+
+router id {{ secondary_vnic_ip4 }};
+log syslog all;
+
+protocol kernel { 
+   persist;
+   scan time 10;
+   device routes;
+   import all;
+   export all;   
+   kernel table 42;
+};
+
+protocol device {
+   scan time 10;
+};
+
+/*
+protocol static unr_def {
+   preference 1;
+   route 0.0.0.0/0 unreachable;
+};
+*/
+
+include "/etc/bird/conf.d/*.conf"; 

+ 22 - 0
roles/bird/templates/bird6.conf.j2

@@ -0,0 +1,22 @@
+router id {{ secondary_vnic_ip4 }};
+log syslog all;
+
+protocol kernel {
+    persist;
+    scan time 10;
+    device routes;
+    import all;
+    export all;
+    kernel table 42;
+};
+
+protocol device {
+    scan time 10;
+};
+
+protocol static unr_def {
+    preference 1;
+    route ::/0 unreachable;
+};
+
+include "/etc/bird/conf6.d/*.conf";

+ 194 - 0
roles/bird/templates/bird6_ms.conf.j2

@@ -0,0 +1,194 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
+router id {{ vm_id }};
+
+table ffnet;
+
+filter freifunk {
+	if net ~ {{ff_network.v6_network}} then accept;
+{% if not ffrl_tun is defined %}
+	if net ~ [::/0] then accept;
+{% endif %}
+	reject;
+}
+
+protocol kernel {
+	scan time 20;
+	import all;
+	export all;
+	table ffnet;
+	kernel table 42;
+	device routes;
+	persist;
+};
+
+{% if domaenenliste is defined %}
+protocol radv {
+{% for domaene in domaenenliste|dictsort %}
+	interface "bat{{domaene[0]}}" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix {{domaenen[domaene[0]].ffv6_network}} {
+		};
+		rdnss {
+			ns {{domaenen[domaene[0]].ffv6_network | ipaddr(domaene[1].server_id) | ipaddr('address') }};
+		};
+		dnssl "{{freifunk.search_domain}}";
+	};
+{% endfor %}
+};
+{% endif %}
+
+
+protocol bfd {
+	table ffnet;
+	interface "gre*";
+	interface "bck*";
+	multihop {
+		passive;
+	};
+};
+
+protocol device {
+	scan time 10;
+};
+
+protocol ospf {
+	table ffnet;
+	import filter freifunk;
+	export all;
+	area 0.0.0.0 {
+		interface "bat*" {
+			stub;
+		};
+{% for host in groups['supernodes'] %}
+{% if hostvars[host].hoster|default('unknown') != hoster|default('unknown') %}
+		interface "bck-{{host}}" {
+			cost 1000;
+		};
+{% endif %}
+{% endfor %}
+		interface "bck-*";
+{% if ffrl_tun is defined %}
+		interface "lo" {
+			stub;
+		};
+{% endif %}
+	};
+};
+
+function is_default() {
+	return (net ~ [::/0]);
+};
+
+{% if ffrl_tun is defined %}
+filter export_to_upstream_filter {
+	if source = RTS_STATIC then accept;
+	reject;
+};
+{% endif %}
+
+protocol static static_Gesamtnetzwerk {
+	table ffnet;
+	route {{ff_network.v6_network}} reject;
+};
+
+{% if domaenenliste is defined %}
+{% for domaene in domaenenliste|dictsort %}
+protocol static static_domaene{{domaene[0]}} {
+	table ffnet;
+	route {{domaenen[domaene[0]].ffv6_network | regex_replace('..::/\d+$','00::/56')}} reject;
+};
+{% endfor %}
+{% endif %}
+{% if dhcp is defined %}
+protocol static 'static_{{inventory_hostname_short}}' {
+	table ffnet;
+	route {{ff_network.v6_network | regex_replace('..::/\d+$','00::/56')}} reject;
+};
+{% endif %}
+
+protocol kernel 'kernel_master' {
+	scan time 20;
+	table master;
+	kernel table 254;
+	import all;
+	export all;
+	persist;
+};
+
+protocol static {
+	table master;
+	import all;
+	export none;
+};
+
+protocol direct {
+	interface "lo";
+	interface "tun-ffrl*";
+	interface "gre-*";
+	interface "bck-*";
+	interface "bat*";
+	table ffnet;
+}
+
+template bgp internal {
+	table ffnet;
+	local as {{ff_network.as_number}};
+	import filter {
+		if is_default() then
+			preference = 99;
+		else
+			preference = 160;
+		accept;
+	};
+	export filter {
+		if source = RTS_BGP then accept;
+{% if ffrl_tun is not defined %}
+		if source = RTS_STATIC then accept;
+{% endif %}
+		else reject;
+	};
+	gateway direct;
+	direct;
+	next hop self;
+};
+
+{% for host in groups['supernodes'] %}
+{% if hostvars[host].vm_id != vm_id %}
+protocol bgp ibgp_{{host|regex_replace('-','_')}} from internal {
+{% if hostvars[host].vm_id < vm_id %}
+	neighbor 2a03:2260:115:ffa1::{{hostvars[host].vm_id}}:{{vm_id}}:1 as {{ff_network.as_number}};
+{% else %}
+	neighbor 2a03:2260:115:ffa1::{{vm_id}}:{{hostvars[host].vm_id}}:0 as {{ff_network.as_number}};
+{% endif %}
+{% if hostvars[host].hoster|default('unknown') != hoster|default('unknown') %}
+	import filter {
+		preference = 50;
+		accept;
+	};
+{% endif %}
+}
+
+{% endif %}
+{% endfor %}
+
+{% if ffrl_tun is defined %}
+template bgp uplink {
+	table ffnet;
+	local as {{ff_network.as_number}};
+	import where is_default();
+	export filter export_to_upstream_filter;
+	gateway recursive;
+}
+
+{% for tun in ffrl_tun %}
+protocol bgp ffrl_{{tun.name}} from uplink {
+	description "Rheinland Backbone";
+	source address {{ tun.v6_remote | ipaddr('2') | ipaddr('address') }};
+	neighbor {{tun.v6_remote | ipaddr('address')}} as 201701;
+};
+
+{% endfor %}
+{% endif %}
+

+ 194 - 0
roles/bird/templates/bird_ms.conf.j2

@@ -0,0 +1,194 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
+router id {{ vm_id }};
+
+table ffnet;
+
+filter freifunk {
+	if net ~ {{ff_network.v6_network}} then accept;
+{% if not ffrl_tun is defined %}
+	if net ~ [::/0] then accept;
+{% endif %}
+	reject;
+}
+
+protocol kernel {
+	scan time 20;
+	import all;
+	export all;
+	table ffnet;
+	kernel table 42;
+	device routes;
+	persist;
+};
+
+{% if domaenenliste is defined %}
+protocol radv {
+{% for domaene in domaenenliste|dictsort %}
+	interface "bat{{domaene[0]}}" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix {{domaenen[domaene[0]].ffv6_network}} {
+		};
+		rdnss {
+			ns {{domaenen[domaene[0]].ffv6_network | ipaddr(domaene[1].server_id) | ipaddr('address') }};
+		};
+		dnssl "{{freifunk.search_domain}}";
+	};
+{% endfor %}
+};
+{% endif %}
+
+
+protocol bfd {
+	table ffnet;
+	interface "gre*";
+	interface "bck*";
+	multihop {
+		passive;
+	};
+};
+
+protocol device {
+	scan time 10;
+};
+
+protocol ospf {
+	table ffnet;
+	import filter freifunk;
+	export all;
+	area 0.0.0.0 {
+		interface "bat*" {
+			stub;
+		};
+{% for host in groups['supernodes'] %}
+{% if hostvars[host].hoster|default('unknown') != hoster|default('unknown') %}
+		interface "bck-{{host}}" {
+			cost 1000;
+		};
+{% endif %}
+{% endfor %}
+		interface "bck-*";
+{% if ffrl_tun is defined %}
+		interface "lo" {
+			stub;
+		};
+{% endif %}
+	};
+};
+
+function is_default() {
+	return (net ~ [::/0]);
+};
+
+{% if ffrl_tun is defined %}
+filter export_to_upstream_filter {
+	if source = RTS_STATIC then accept;
+	reject;
+};
+{% endif %}
+
+protocol static static_Gesamtnetzwerk {
+	table ffnet;
+	route {{ff_network.v6_network}} reject;
+};
+
+{% if domaenenliste is defined %}
+{% for domaene in domaenenliste|dictsort %}
+protocol static static_domaene{{domaene[0]}} {
+	table ffnet;
+	route {{domaenen[domaene[0]].ffv6_network | regex_replace('..::/\d+$','00::/56')}} reject;
+};
+{% endfor %}
+{% endif %}
+{% if dhcp is defined %}
+protocol static 'static_{{inventory_hostname_short}}' {
+	table ffnet;
+	route {{ff_network.v6_network | regex_replace('..::/\d+$','00::/56')}} reject;
+};
+{% endif %}
+
+protocol kernel 'kernel_master' {
+	scan time 20;
+	table master;
+	kernel table 254;
+	import all;
+	export all;
+	persist;
+};
+
+protocol static {
+	table master;
+	import all;
+	export none;
+};
+
+protocol direct {
+	interface "lo";
+	interface "tun-ffrl*";
+	interface "gre-*";
+	interface "bck-*";
+	interface "bat*";
+	table ffnet;
+}
+
+template bgp internal {
+	table ffnet;
+	local as {{ff_network.as_number}};
+	import filter {
+		if is_default() then
+			preference = 99;
+		else
+			preference = 160;
+		accept;
+	};
+	export filter {
+		if source = RTS_BGP then accept;
+{% if ffrl_tun is not defined %}
+		if source = RTS_STATIC then accept;
+{% endif %}
+		else reject;
+	};
+	gateway direct;
+	direct;
+	next hop self;
+};
+
+{% for host in groups['supernodes'] %}
+{% if hostvars[host].vm_id != vm_id %}
+protocol bgp ibgp_{{host|regex_replace('-','_')}} from internal {
+{% if hostvars[host].vm_id < vm_id %}
+	neighbor 2a03:2260:115:ffa1::{{hostvars[host].vm_id}}:{{vm_id}}:1 as {{ff_network.as_number}};
+{% else %}
+	neighbor 2a03:2260:115:ffa1::{{vm_id}}:{{hostvars[host].vm_id}}:0 as {{ff_network.as_number}};
+{% endif %}
+{% if hostvars[host].hoster|default('unknown') != hoster|default('unknown') %}
+	import filter {
+		preference = 50;
+		accept;
+	};
+{% endif %}
+}
+
+{% endif %}
+{% endfor %}
+
+{% if ffrl_tun is defined %}
+template bgp uplink {
+	table ffnet;
+	local as {{ff_network.as_number}};
+	import where is_default();
+	export filter export_to_upstream_filter;
+	gateway recursive;
+}
+
+{% for tun in ffrl_tun %}
+protocol bgp ffrl_{{tun.name}} from uplink {
+	description "Rheinland Backbone";
+	source address {{ tun.v6_remote | ipaddr('2') | ipaddr('address') }};
+	neighbor {{tun.v6_remote | ipaddr('address')}} as 201701;
+};
+
+{% endfor %}
+{% endif %}
+

+ 41 - 0
roles/bird/templates/ospf.conf.j2

@@ -0,0 +1,41 @@
+define FFDO_subnet_new =
+[
+        10.233.128.0/17+
+];
+
+define FFDO_subnet_old =
+[
+        10.233.0.0/18+
+];
+
+define AS31371_nets =
+[
+        91.204.4.0/22{24,32},
+        195.160.168.0/23+,
+        193.43.221.0/24+
+];
+
+protocol ospf ospf5 {
+
+#        import where net ~ AS31371_nets || net ~ FFDO_subnet_old;
+        import where net ~ FFDO_subnet_old;
+        export filter {
+                if net ~ FFDO_subnet_new then {
+                        ospf_metric1 = 10;
+                        accept;
+                }
+                reject;
+        };
+
+        area 0.0.0.0 {
+                interface "{{secondary_vnic}}" {
+                        cost 10;
+                        type broadcast;
+                        hello 10;
+                        retransmit 5;
+                        dead 40;
+                        wait 10;
+                };
+        };
+};
+

+ 37 - 0
roles/bird/templates/ospf6.conf.j2

@@ -0,0 +1,37 @@
+define FFDO6_subnet_new =
+[
+	2a03:2260:300a:2000::/64+,
+	2a03:2260:300a:2100::/64+,
+	2a03:2260:300a:2200::/64+,
+	2a03:2260:300a:2300::/64+,
+	2a03:2260:300a:2400::/64+,
+	2a03:2260:300a:2500::/64+,
+	2a03:2260:300a:2600::/64+,
+	2a03:2260:300a:2700::/64+,
+	2a03:2260:300a:2800::/64+,
+	2a03:2260:300a:2900::/64+,
+	2a03:2260:300a:2a00::/64+
+];
+
+define FFDO6_subnet_old =
+[
+	2a03:2260:300a:1000::/64+
+];
+
+protocol ospf ospfffdo6 {
+
+#	import where net ~ FFDO6_subnet_old;
+	import all;
+	export where net ~ FFDO6_subnet_new;
+
+	area 0.0.0.0 {
+		interface "{{secondary_vnic}}" {
+			cost 10;
+			type broadcast;
+			hello 10; 
+			retransmit 5; 
+			dead 40;
+			wait 10;
+		};
+	};
+};

+ 5 - 0
roles/bird/templates/temp/batman.conf

@@ -0,0 +1,5 @@
+protocol direct bat01 {
+        interface "bat01";
+};
+
+#Todo: per Ansible erzeugen

+ 290 - 0
roles/bird/templates/temp/ff6.conf_dis

@@ -0,0 +1,290 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
+router id 1;
+
+table ffnet;
+
+filter freifunk {
+	if net ~ 2a03:2260:300a::/48 then accept;
+	reject;
+}
+
+protocol kernel {
+	scan time 20;
+	import all;
+	export all;
+	table ffnet;
+	kernel table 42;
+	device routes;
+	persist;
+};
+
+protocol radv {
+	interface "bat01" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2000::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2000::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat02" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2100::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2100::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat03" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2200::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2200::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat04" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2300::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2300::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat05" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2400::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2400::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat06" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2500::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2500::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat07" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2600::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2600::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat08" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2700::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2700::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat09" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2800::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2800::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat10" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2900::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2900::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat11" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2a00::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2a00::1;
+		};
+		dnssl "ffdo";
+	};
+};
+
+
+protocol bfd {
+	table ffnet;
+	interface "gre*";
+	interface "bck*";
+	multihop {
+		passive;
+	};
+};
+
+protocol device {
+	scan time 10;
+};
+
+protocol ospf {
+	table ffnet;
+	import filter freifunk;
+	export all;
+	area 0.0.0.0 {
+		interface "bat*" {
+			stub;
+		};
+		interface "bck-*";
+		interface "lo" {
+			stub;
+		};
+	};
+};
+
+function is_default() {
+	return (net ~ [::/0]);
+};
+
+filter export_to_upstream_filter {
+	if source = RTS_STATIC then accept;
+	reject;
+};
+
+protocol static static_Gesamtnetzwerk {
+	table ffnet;
+	route 2a03:2260:300a::/48 reject;
+};
+
+protocol static static_domaene01 {
+	table ffnet;
+	route 2a03:2260:300a:2000::/56 reject;
+};
+protocol static static_domaene02 {
+	table ffnet;
+	route 2a03:2260:300a:2100::/56 reject;
+};
+protocol static static_domaene03 {
+	table ffnet;
+	route 2a03:2260:300a:2200::/56 reject;
+};
+protocol static static_domaene04 {
+	table ffnet;
+	route 2a03:2260:300a:2300::/56 reject;
+};
+protocol static static_domaene05 {
+	table ffnet;
+	route 2a03:2260:300a:2400::/56 reject;
+};
+protocol static static_domaene06 {
+	table ffnet;
+	route 2a03:2260:300a:2500::/56 reject;
+};
+protocol static static_domaene07 {
+	table ffnet;
+	route 2a03:2260:300a:2600::/56 reject;
+};
+protocol static static_domaene08 {
+	table ffnet;
+	route 2a03:2260:300a:2700::/56 reject;
+};
+protocol static static_domaene09 {
+	table ffnet;
+	route 2a03:2260:300a:2800::/56 reject;
+};
+protocol static static_domaene10 {
+	table ffnet;
+	route 2a03:2260:300a:2900::/56 reject;
+};
+protocol static static_domaene11 {
+	table ffnet;
+	route 2a03:2260:300a:2a00::/56 reject;
+};
+
+protocol kernel 'kernel_master' {
+	scan time 20;
+	table master;
+	kernel table 254;
+	import all;
+	export all;
+	persist;
+};
+
+protocol static {
+	table master;
+	import all;
+	export none;
+};
+
+protocol direct {
+	interface "lo";
+	interface "tun-ffrl*";
+	interface "gre-*";
+	interface "bck-*";
+	interface "bat*";
+	table ffnet;
+}
+
+template bgp internal {
+	table ffnet;
+	local as 65403;
+	import filter {
+		if is_default() then
+			preference = 99;
+		else
+			preference = 160;
+		accept;
+	};
+	export filter {
+		if source = RTS_BGP then accept;
+		else reject;
+	};
+	gateway direct;
+	direct;
+	next hop self;
+};
+
+protocol bgp ibgp_sn_dev2 from internal {
+	neighbor 2a03:2260:115:ffa1::1:2:0 as 65403;
+}
+
+
+template bgp uplink {
+	table ffnet;
+	local as 65403;
+	import where is_default();
+	export filter export_to_upstream_filter;
+	gateway recursive;
+}
+
+protocol bgp ffrl_dus from uplink {
+	description "Rheinland Backbone";
+	source address 2a03:2260:0:3f::2;
+	neighbor 2a03:2260:0:3f::1 as 201701;
+};
+
+protocol bgp ffrl_fra from uplink {
+	description "Rheinland Backbone";
+	source address 2a03:2260:0:3e::2;
+	neighbor 2a03:2260:0:3e::1 as 201701;
+};
+

+ 290 - 0
roles/bird/templates/temp/ffms.conf_dis

@@ -0,0 +1,290 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
+router id 1;
+
+table ffnet;
+
+filter freifunk {
+	if net ~ 2a03:2260:300a::/48 then accept;
+	reject;
+}
+
+protocol kernel {
+	scan time 20;
+	import all;
+	export all;
+	table ffnet;
+	kernel table 42;
+	device routes;
+	persist;
+};
+
+protocol radv {
+	interface "bat01" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2000::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2000::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat02" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2100::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2100::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat03" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2200::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2200::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat04" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2300::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2300::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat05" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2400::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2400::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat06" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2500::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2500::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat07" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2600::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2600::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat08" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2700::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2700::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat09" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2800::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2800::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat10" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2900::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2900::1;
+		};
+		dnssl "ffdo";
+	};
+	interface "bat11" {
+		max ra interval 20;
+		link mtu 1280;
+		prefix 2a03:2260:300a:2a00::/64 {
+		};
+		rdnss {
+			ns 2a03:2260:300a:2a00::1;
+		};
+		dnssl "ffdo";
+	};
+};
+
+
+protocol bfd {
+	table ffnet;
+	interface "gre*";
+	interface "bck*";
+	multihop {
+		passive;
+	};
+};
+
+protocol device {
+	scan time 10;
+};
+
+protocol ospf {
+	table ffnet;
+	import filter freifunk;
+	export all;
+	area 0.0.0.0 {
+		interface "bat*" {
+			stub;
+		};
+		interface "bck-*";
+		interface "lo" {
+			stub;
+		};
+	};
+};
+
+function is_default() {
+	return (net ~ [::/0]);
+};
+
+filter export_to_upstream_filter {
+	if source = RTS_STATIC then accept;
+	reject;
+};
+
+protocol static static_Gesamtnetzwerk {
+	table ffnet;
+	route 2a03:2260:300a::/48 reject;
+};
+
+protocol static static_domaene01 {
+	table ffnet;
+	route 2a03:2260:300a:2000::/56 reject;
+};
+protocol static static_domaene02 {
+	table ffnet;
+	route 2a03:2260:300a:2100::/56 reject;
+};
+protocol static static_domaene03 {
+	table ffnet;
+	route 2a03:2260:300a:2200::/56 reject;
+};
+protocol static static_domaene04 {
+	table ffnet;
+	route 2a03:2260:300a:2300::/56 reject;
+};
+protocol static static_domaene05 {
+	table ffnet;
+	route 2a03:2260:300a:2400::/56 reject;
+};
+protocol static static_domaene06 {
+	table ffnet;
+	route 2a03:2260:300a:2500::/56 reject;
+};
+protocol static static_domaene07 {
+	table ffnet;
+	route 2a03:2260:300a:2600::/56 reject;
+};
+protocol static static_domaene08 {
+	table ffnet;
+	route 2a03:2260:300a:2700::/56 reject;
+};
+protocol static static_domaene09 {
+	table ffnet;
+	route 2a03:2260:300a:2800::/56 reject;
+};
+protocol static static_domaene10 {
+	table ffnet;
+	route 2a03:2260:300a:2900::/56 reject;
+};
+protocol static static_domaene11 {
+	table ffnet;
+	route 2a03:2260:300a:2a00::/56 reject;
+};
+
+protocol kernel 'kernel_master' {
+	scan time 20;
+	table master;
+	kernel table 254;
+	import all;
+	export all;
+	persist;
+};
+
+protocol static {
+	table master;
+	import all;
+	export none;
+};
+
+protocol direct {
+	interface "lo";
+	interface "tun-ffrl*";
+	interface "gre-*";
+	interface "bck-*";
+	interface "bat*";
+	table ffnet;
+}
+
+template bgp internal {
+	table ffnet;
+	local as 65403;
+	import filter {
+		if is_default() then
+			preference = 99;
+		else
+			preference = 160;
+		accept;
+	};
+	export filter {
+		if source = RTS_BGP then accept;
+		else reject;
+	};
+	gateway direct;
+	direct;
+	next hop self;
+};
+
+protocol bgp ibgp_sn_dev2 from internal {
+	neighbor 2a03:2260:115:ffa1::1:2:0 as 65403;
+}
+
+
+template bgp uplink {
+	table ffnet;
+	local as 65403;
+	import where is_default();
+	export filter export_to_upstream_filter;
+	gateway recursive;
+}
+
+protocol bgp ffrl_dus from uplink {
+	description "Rheinland Backbone";
+	source address 2a03:2260:0:3f::2;
+	neighbor 2a03:2260:0:3f::1 as 201701;
+};
+
+protocol bgp ffrl_fra from uplink {
+	description "Rheinland Backbone";
+	source address 2a03:2260:0:3e::2;
+	neighbor 2a03:2260:0:3e::1 as 201701;
+};
+

+ 4 - 0
roles/calculate_missing_inventory_variables/tasks/find_partner.yml

@@ -0,0 +1,4 @@
+- name: Suche Partnergateway
+  when: "hostvars[gateway].domaenenliste[dom] is defined and gateway != inventory_hostname"
+  set_fact:
+    domaenenliste: "{{domaenenliste | combine( {dom: {'partner' : gateway}}, recursive=True)}}"

+ 7 - 0
roles/calculate_missing_inventory_variables/tasks/main.yml

@@ -0,0 +1,7 @@
+- name: Prüfen, wo Variablen nachberechnet werden müssen
+  include: set_calculation_needed.yml dom={{item}}
+  with_items: "{{domaenenliste}}"
+
+- name: Domaenenliste ausgeben
+  debug:
+    var: domaenenliste

+ 3 - 0
roles/calculate_missing_inventory_variables/tasks/per_host.yml

@@ -0,0 +1,3 @@
+- include: per_domain.yml domain={{ item }}
+  with_items: hostvars[host].domaenenliste
+  when: domain[1].server_id is undefined or domain[1].dhcp_start is undefined or domain[1].dhcp_ende is undefined

+ 37 - 0
roles/calculate_missing_inventory_variables/tasks/set_calculation_needed.yml

@@ -0,0 +1,37 @@
+- debug:
+    var: dom
+
+- name: Prüfen, wo Variablen nachberechnet werden müssen
+  set_fact:
+    domaenenliste: "{{domaenenliste | combine( {dom: {'calculation_needed' : 'true'}}, recursive=True)}}"
+  when: "(domaenenliste[dom].server_id is not defined) or (domaenenliste[dom].dhcp_start is not defined) or (domaenenliste[dom].dhcp_ende is not defined)"
+
+- name: Partner setzen
+  when: "domaenenliste[dom].calculation_needed is defined and domaenenliste[dom].calculation_needed == 'true'"
+  with_items: "{{ groups['gateways'] }}"
+  loop_control:
+    loop_var: gates
+  include: find_partner.yml gateway={{gates}}
+
+- name: server_id auf 2 setzen, falls andere vm_id größer
+  when: "domaenenliste[dom].calculation_needed is defined and domaenenliste[dom].calculation_needed == 'true' and hostvars[domaenenliste[dom].partner].vm_id > vm_id"
+  set_fact:
+    domaenenliste: "{{domaenenliste | combine( {dom: {'server_id' : 2}}, recursive=True)}}"
+
+- name: server_id auf 3 setzen, falls andere vm_id kleiner
+  when: "domaenenliste[dom].calculation_needed is defined and domaenenliste[dom].calculation_needed == 'true' and hostvars[domaenenliste[dom].partner].vm_id < vm_id"
+  set_fact:
+    domaenenliste: "{{domaenenliste | combine( {dom: {'server_id' : 3}}, recursive=True)}}"
+
+- name: Unterer DHCP-Bereich
+  when: "domaenenliste[dom].calculation_needed is defined and domaenenliste[dom].calculation_needed == 'true' and domaenenliste[dom].server_id == 2"
+  set_fact:
+          domaenenliste: "{{domaenenliste | combine( {dom: {'dhcp_start' : '10.' + dom | int | string + '.64.0', 'dhcp_ende' : '10.' + dom | int | string + '.127.255' }}, recursive=True)}}"
+
+- name: Oberer DHCP-Bereich
+  when: "domaenenliste[dom].calculation_needed is defined and domaenenliste[dom].calculation_needed == 'true' and domaenenliste[dom].server_id == 3"
+  set_fact:
+          domaenenliste: "{{domaenenliste | combine( {dom: {'dhcp_start' : '10.' + dom | int | string + '.128.0', 'dhcp_ende' : '10.' + dom | int | string + '.191.255' }}, recursive=True)}}"
+
+
+

+ 24 - 0
roles/collectd/README.md

@@ -0,0 +1,24 @@
+## Rolle für collectd client
+Diese Rolle kann sowohl für Backbone-Server, als auch für Gateway-Server, als auch für Supernodes verwendet werden. Da auf Backbone-only Servern kein DHCP und auch kein fastd läuft, können diese Monitoring-Ziele deaktiviert werden. Siehe dazu den Punkt *Variablen*.
+### Variablen
+Es gibt zwei Dictionaries, die für die collectd Rolle relevant sind. Diese werden üblicherweise in den ``group_vars`` konfiguriert. Das Dictionary ``graphite_data_target`` wird üblicherweise nur in der Gruppe ``all`` gesetzt.
+
+#### Beispiel
+```
+# Zielserver für Graphite Daten 
+graphite_data_target:
+  # IP Adresse
+  host: 5.9.86.154
+  # Port des Carbon-Dienstes 
+  port: 2003  
+  
+# Collectd Konfiguration 
+collectd:
+  # Prefix für Graphite-Daten
+  graphite_prefix: host.
+  # Sollen Daten über den DHCP Server erfasst werden?
+  collect_dhcp: true
+  # Sollen Daten über den fastd Server erfasst werden?
+  collect_fastd: true
+```
+

+ 4 - 0
roles/collectd/handlers/main.yml

@@ -0,0 +1,4 @@
+---
+- name: restart collectd
+  service: name=collectd state=restarted
+

+ 103 - 0
roles/collectd/tasks/main.yml

@@ -0,0 +1,103 @@
+---
+# Collectd-Daemon fuer Gateway Server
+
+- name: install required packages
+  apt:
+    pkg: "{{ item }}"
+    update_cache: yes
+    state: present
+  with_items:
+    - collectd
+    - python-pip
+
+- name: install pip packages
+  pip: 
+    name: "{{ item }}"
+    state: present 
+  with_items:
+    - ipaddress
+    - pybrctl
+
+- name: enable collectd
+  service: name=collectd enabled=yes    
+  notify:
+    - restart collectd 
+
+- name: create config directory
+  file: path=/etc/collectd state=directory
+  notify:
+    - restart collectd
+
+- name: deploy collectd.conf 
+  template: src=collectd.conf.j2 dest=/etc/collectd/collectd.conf 
+  notify:
+    - restart collectd
+
+- name: deploy collection.conf
+  template: src=collection.conf.j2 dest=/etc/collectd/collection.conf
+  notify:
+    - restart collectd
+
+- name: deploy filters.conf
+  template: src=filters.conf.j2 dest=/etc/collectd/filters.conf
+  notify:
+    - restart collectd
+
+- name: deploy thresholds.conf
+  template: src=thresholds.conf.j2 dest=/etc/collectd/thresholds.conf
+  notify:
+    - restart collectd
+
+- name: create plugins directory
+  file: path=/opt/collectd-python state=directory
+  notify:
+    - restart collectd
+
+- name: Add type for dhcp stats to types.db
+  lineinfile: dest=/usr/share/collectd/types.db regexp="^dhcp_leases" line="dhcp_leases             active:GAUGE:0:U, touched:GAUGE:0:U"
+  notify:
+    - restart collectd
+
+- name: Add type for kea dhcp stats to types.db
+  lineinfile: dest=/usr/share/collectd/types.db regexp="^kea_leases" line="kea_leases             total-addresses:GAUGE:0:U, assigned-addresses:GAUGE:0:U, declined-addresses:GAUGE:0:U, declined-reclaimed-addresses:GAUGE:0:U, reclaimed-leases:GAUGE:0:U, active-leases:GAUGE:0:U"
+  notify:
+    - restart collectd
+
+- name: Add type for l2tp stats to types.db
+  lineinfile: dest=/usr/share/collectd/types.db regexp="^if_count" line="if_count                value:GAUGE:0:U"
+  notify:
+    - restart collectd
+
+- name: deploy l2tp.py
+  template: src=l2tp.py.j2 dest=/opt/collectd-python/l2tp.py
+  notify:
+    - restart collectd
+  when: collectd.collect_l2tp and domaenenliste is defined
+
+- name: deploy fastd.py
+  template: src=fastd.py.j2 dest=/opt/collectd-python/fastd.py
+  notify:
+    - restart collectd
+  when: collectd.collect_fastd
+
+- name: deploy dhcp.py
+  template: src=dhcp.py.j2 dest=/opt/collectd-python/dhcp.py
+  notify:
+    - restart collectd
+  when: collectd.collect_dhcp and domaenenliste is defined
+
+- name: deploy kea.py
+  template: src=kea.py.j2 dest=/opt/collectd-python/kea.py
+  notify:
+    - restart collectd
+  when: collectd.collect_dhcp and domaenenliste is defined
+
+- name: deploy ipv4ipv6.py
+  template: src=ipv4ipv6.py.j2 dest=/opt/collectd-python/ipv4ipv6.py
+  notify:
+    - restart collectd
+
+- name: deploy sysctl.py
+  template: src=sysctl.py.j2 dest=/opt/collectd-python/sysctl.py
+  notify:
+    - restart collectd

File diff suppressed because it is too large
+ 999 - 0
roles/collectd/templates/collectd.conf.j2


+ 4 - 0
roles/collectd/templates/collection.conf.j2

@@ -0,0 +1,4 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+datadir: "/var/lib/collectd/rrd/"
+libdir: "/usr/lib/collectd/"
+

+ 123 - 0
roles/collectd/templates/dhcp.py.j2

@@ -0,0 +1,123 @@
+#!/usr/bin/python
+
+import datetime, collectd, os.path, ipaddress
+
+def parse_leases(lease_file):
+	validKeys = ['lease', 'starts', 'ends', '}']
+	leases = {}
+	lease = {}
+	for line in lease_file:
+		tokens = line.split()
+
+		if len(tokens) == 0 or tokens[0].startswith('#'):
+			continue
+
+		key = tokens[0].lower()
+
+		if key in validKeys:
+			if key == 'lease':
+				lease = {'id' : tokens[1]}
+
+			elif key == '}':
+				if lease['id'] in leases:
+					if leases[lease['id']]['ends'] < lease['ends']:
+						leases[lease['id']] = lease
+				else:
+					leases[lease['id']] = lease
+
+			else:
+				lease[key] = tokens[2]+' '+tokens[3].rstrip(';')
+
+	return leases
+
+def parse_dhcpd_conf(config_file):
+	subnet = {}
+	subnets = {}
+	for line in config_file:
+		line = line.strip().rstrip(';')
+		tokens = line.split()
+
+		if len(tokens) == 0 or tokens[0].startswith('#'):
+			continue
+		key = tokens[0].lower()
+
+		if key == 'subnet':
+			net = ipaddress.ip_network(unicode(tokens[1]+'/'+tokens[3]))
+			subnet = {'netaddr_str' : tokens[1], 'netaddr_int' : int(net.network_address), 'netmask_str' : tokens[3], 'netmask_int' : int(net.netmask)}
+		
+		elif key == 'interface':
+			subnet['interface'] = tokens[1]
+
+		elif key == '}':
+			subnet_add(subnets, subnet)
+			subnet = {}
+
+	return subnets
+
+def subnet_add(subnets, subnet):
+	if 'interface' not in subnet:
+		subnet['interface'] = 'global'
+	sub_name = subnet['interface']
+	if sub_name not in subnets:
+		subnets[sub_name] = subnet
+	else:
+		pass #needs to be implemented
+
+def count_active_leases(all_leases, now, subnets):
+	count_active = 0
+	count_all = 0
+	subnet_counter = {}
+	for interface in subnets.iterkeys():
+		subnet_counter[interface] = {'count_active': 0, 'count_all': 0, 'count_touch': 0}
+
+	for lease in all_leases.itervalues():
+		addr = int(ipaddress.ip_address(unicode(lease['id'])))
+		for subnet in subnets.itervalues():
+			if (addr & subnet['netmask_int']) == subnet['netaddr_int']:
+				subnc = subnet_counter[subnet['interface']]
+				subnc['count_all'] += 1
+				count_all += 1
+				if timestamp_inbetween(now, lease['starts'], lease['ends']):
+					subnc['count_active'] += 1
+					count_active += 1
+				break
+
+	for subnet in subnet_counter.itervalues():
+			subnet['count_touch'] = subnet['count_all'] - subnet['count_active']
+	count_touch = count_all - count_active
+
+	return count_active, count_touch, subnet_counter
+
+
+def timestamp_inbetween(now, start, end):
+	return start < now < end
+
+def read(data=None):
+	configfile = '/etc/dhcp/dhcpd.conf'
+	if os.path.isfile(configfile):
+		cfile = open(configfile, 'r')
+		config = parse_dhcpd_conf(cfile)
+		leasefile = '/var/lib/dhcp/dhcpd.leases'
+		if os.path.isfile(leasefile):
+			lfile = open(leasefile, 'r')
+			all_leases = parse_leases(lfile)
+			lfile.close()
+			count_active, count_touch, subnet_counter = count_active_leases(all_leases, datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S"), config)
+			vl = collectd.Values(type='dhcp_leases')
+			vl.plugin='dhcp'
+			vl.type_instance = 'all_interfaces'
+			vl.dispatch(values=[count_active, count_touch])
+			for k, v in subnet_counter.iteritems():
+				vl = collectd.Values(type='dhcp_leases')
+				vl.plugin='dhcp'
+				vl.type_instance = k
+				vl.dispatch(values=[v['count_active'], v['count_touch']])
+				vl = collectd.Values(type='dhcp_leases')
+
+
+def write(vl, data=None):
+	for i in vl.values:
+		print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+collectd.register_read(read)
+collectd.register_write(write);

+ 106 - 0
roles/collectd/templates/fastd.py.j2

@@ -0,0 +1,106 @@
+#!/usr/bin/python
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author:
+#   dray <dresen@itsecteam.ms>
+#
+# Script to count fastd connections adapted from
+# https://github.com/FreiFunkMuenster/gateway-ffms/blob/master/nrpe/check_fastd_connections.py
+#
+# About this plugin:
+#   This plugin collects the number of fastd connection for FFMS
+#
+# Configuration
+#
+# <Module fastd>
+#     server_address "/tmp/fastd-status"
+# </Module>
+# 
+# for multiple fastd instances, add each socket to server_address seperated by :
+# Example:
+# server_address "/tmp/fastd-a-status:/tmp/fastd-b-status"
+#
+#
+
+import collectd
+import socket
+import sys
+import json
+
+server_address = ''
+
+
+def read(data=None):
+	vl = collectd.Values(type='gauge')
+	vl.plugin='python.fastd'
+
+
+	try:
+		connections = 0	
+		servers = server_address.split(":")
+		for server in servers:
+			sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+			sock.connect(server)
+
+			received_count = 1
+			received_data = ""
+
+			while received_count > 0:
+				data = sock.recv(1024)
+				received_count = len(data)
+				received_data += data;
+
+			sock.close();
+		
+			received_json = json.loads(received_data);
+
+			for item in received_json.items()[2][1].items():
+				connection = item[1]
+				connections += 1
+		vl.dispatch(values=[connections])
+		
+	except socket.error, msg:
+		collectd.error("[FFMS Fastd] Socket read failed: %s" % (msg))
+	    # vl.dispatch(values=[-1])	
+	
+
+def write(vl, data=None):
+	for i in vl.values:
+		print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+def config (config):
+	global server_address
+	server_address = ''   #'/tmp/fastd-status'
+
+	for node in config.children:
+		key = node.key.lower()
+		val = node.values[0]
+
+		if key == 'server_address':
+			server_address = val
+
+		else:
+			collectd.warning("ffms_fastd plugin: Unknown configuration key: %s." % key )
+			continue
+
+	if server_address == '':
+		collectd.error('ffms_fastd plugin: No Serveradress configured.' )
+	else:
+		collectd.info("ffms_fastd plugin: Successful configured with server_address %s." % server_address)
+	
+collectd.register_read(read);
+collectd.register_write(write);
+collectd.register_config(config);

+ 35 - 0
roles/collectd/templates/filters.conf.j2

@@ -0,0 +1,35 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+# Filter configuration for collectd(1).
+#
+# See the section "FILTER CONFIGURATION" in collectd.conf(5) for details.
+
+#PreCacheChain "PreCache"
+#PostCacheChain "PostCache"
+
+#LoadPlugin match_empty_counter
+#LoadPlugin match_hashed
+#LoadPlugin match_regex
+#LoadPlugin match_timediff
+#LoadPlugin match_value
+
+#LoadPlugin target_notification
+#LoadPlugin target_replace
+#LoadPlugin target_scale
+#LoadPlugin target_set
+#LoadPlugin target_v5upgrade
+
+#<Chain "PreCache">
+#	<Rule "no_fqdn">
+#		<Match "regex">
+#			Host "^[^\.]*$"
+#			Invert false
+#		</Match>
+#		Target "stop"
+#	</Rule>
+#</Chain>
+
+# Default behavior:
+#<Chain "PostCache">
+#	Target "write"
+#</Chain>
+

+ 45 - 0
roles/collectd/templates/ipv4ipv6.py.j2

@@ -0,0 +1,45 @@
+#!/usr/bin/python
+
+import datetime, collectd, os.path
+
+def getStats():
+	stats = {
+		'v4' : {},
+		'v6' : {}
+	}
+	prc = open('/proc/net/netstat', 'r')
+	for line in prc.readlines():
+		if 'IpExt' in line and 'InOctets' not in line:
+			line = line.split()
+			stats['v4']['rx'] = line[7]
+			stats['v4']['tx'] = line[8]
+			break
+	prc.close()
+	prc = open('/proc/net/snmp6', 'r')
+	for line in prc.readlines():
+		if 'Ip6InOctets' in line:
+			stats['v6']['rx'] = line.split()[1]
+		elif 'Ip6OutOctets' in line:
+			stats['v6']['tx'] = line.split()[1]
+	prc.close()
+	return stats
+
+def read(data=None):
+	stats = getStats()
+	vl = collectd.Values(type='if_octets')
+	vl.plugin='ip_traffic'
+	vl.type_instance = 'v4'
+	vl.dispatch(values=[stats['v4']['rx'], stats['v4']['tx']])
+	vl = collectd.Values(type='if_octets')
+	vl.plugin='ip_traffic'
+	vl.type_instance = 'v6'
+	vl.dispatch(values=[stats['v6']['rx'], stats['v6']['tx']])
+
+
+def write(vl, data=None):
+	for i in vl.values:
+		print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+collectd.register_read(read)
+collectd.register_write(write);
+

+ 66 - 0
roles/collectd/templates/kea.py.j2

@@ -0,0 +1,66 @@
+#!/usr/bin/python
+
+import collectd,datetime,socket,os,json,collections{% if kea.database.type == "postgresql" %},psycopg2
+{% endif %}
+
+{% if kea.database.type == "postgresql" %}
+def performPSQL():
+	conn = psycopg2.connect("host='{{kea.database.db_host}}' dbname='{{kea.database.db_name}}' user='{{kea.database.db_user}}' password='{{kea.database.db_pass}}'")
+	cursor = conn.cursor()
+	cursor.execute("SELECT subnet_id, COUNT(*) FROM lease4 WHERE state=0 GROUP BY subnet_id")
+	return dict((int(x), int(y)) for x, y in cursor.fetchall())
+{% endif %}
+
+def read(data=None):
+	resDict = {}
+	resDict[u'all_interfaces'] = collections.defaultdict(int)
+
+{% if kea.database.type == "postgresql" %}
+	active_leases = performPSQL()
+
+	for k, v in active_leases.items():
+		if_name = 'bat' + str(k)
+		resDict[if_name] = collections.defaultdict(int)
+		resDict[if_name]['active-leases'] = v
+		resDict[u'all_interfaces']['active-leases'] += v
+
+{% endif %}
+	BUFF_SIZE = 1024
+	s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+	s.connect("/var/kea/control.sock")
+	s.send('{"command":"statistic-get-all","arguments":{}}')
+	result = ""
+	part = s.recv(BUFF_SIZE)
+	while len(part) == BUFF_SIZE:
+		result += part
+		part = s.recv(1024)
+	result += part
+	jsonData = json.loads(result)
+	for k,v in jsonData["arguments"].iteritems():
+		k = k.split('.') 
+		interface = k[0].replace('subnet[','bat').replace(']','')
+		if len(k) != 2:
+			continue
+		if interface not in resDict:
+			resDict[interface] = collections.defaultdict(int)
+		resDict[interface][k[1]] = v[0][0]
+		resDict['all_interfaces'][k[1]] += v[0][0]
+
+	s.close()
+
+	for k,v in resDict.iteritems():
+		vl = collectd.Values(type='kea_leases')
+		vl.plugin='kea_leases'
+		vl.type_instance = k
+{% if kea.database.type == "postgresql" %}
+		vl.dispatch(values=[v['total-addresses'], v['assigned-addresses'], v['declined-addresses'], v['declined-reclaimed-addresses'], v['reclaimed-leases'], v['active-leases']])
+{% else %}
+		vl.dispatch(values=[v['total-addresses'], v['assigned-addresses'], v['declined-addresses'], v['declined-reclaimed-addresses'], v['reclaimed-leases'], -1])
+{% endif %}
+
+def write(vl, data=None):
+	for i in vl.values:
+		print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+collectd.register_read(read)
+collectd.register_write(write);

+ 32 - 0
roles/collectd/templates/l2tp.py.j2

@@ -0,0 +1,32 @@
+#!/usr/bin/python
+import collectd
+from pybrctl import BridgeController
+
+def getBridgeInterfaceCount():
+	ifcount = {}
+	brctl = BridgeController()
+	for br in brctl.showall():
+		ifcount[br.name] = len(br.getifs())
+	return ifcount
+
+def read(data=None):
+	stats = getBridgeInterfaceCount()
+	globalCount = 0
+	for k,v in stats.iteritems():
+		globalCount += v
+		vl = collectd.Values(type='if_count')
+		vl.plugin='l2tp'
+		vl.type_instance = k
+		vl.dispatch(values=[v])
+	vl = collectd.Values(type='if_count')
+	vl.plugin='l2tp'
+	vl.type_instance = 'all'
+	vl.dispatch(values=[globalCount])
+
+
+def write(vl, data=None):
+	for i in vl.values:
+		print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+collectd.register_read(read)
+collectd.register_write(write);

+ 23 - 0
roles/collectd/templates/sysctl.py.j2

@@ -0,0 +1,23 @@
+#!/usr/bin/python
+import subprocess, collectd
+
+def getStats(entries):
+	sysctl = ['sysctl', '-n']
+	return dict(zip(entries, subprocess.check_output(sysctl + entries).split('\n')))
+
+
+def read(data=None):
+	stats = getStats(['net.netfilter.nf_conntrack_max', 'net.netfilter.nf_conntrack_count'])
+	for k,v in stats.iteritems():
+		vl = collectd.Values(type='gauge')
+		vl.plugin='sysctl'
+		vl.type_instance = k
+		vl.dispatch(values=[v])
+
+
+def write(vl, data=None):
+	for i in vl.values:
+		print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+collectd.register_read(read)
+collectd.register_write(write)

+ 52 - 0
roles/collectd/templates/thresholds.conf.j2

@@ -0,0 +1,52 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+# Threshold configuration for collectd(1).
+#
+# See the section "THRESHOLD CONFIGURATION" in collectd.conf(5) for details.
+
+#LoadPlugin "threshold"
+#<Plugin "threshold">
+#	<Type "counter">
+#		WarningMin 0.00
+#		WarningMax 1000.00
+#		FailureMin 0
+#		FailureMax 1200.00
+#		Invert false
+#		Persist false
+#		Instance "some_instance"
+#	</Type>
+#
+#	<Type "load">
+#		DataSource "midterm"
+#		WarningMax 1
+#		Hysteresis 0.3
+#	</Type>
+#
+#	<Type "cpu">
+#		Instance "user"
+#		WarningMax 85
+#		Hits 6
+#	</Type>
+#
+#	<Plugin "interface">
+#		Instance "eth0"
+#		<Type "if_octets">
+#			DataSource "rx"
+#			FailureMax 10000000
+#		</Type>
+#	</Plugin>
+#
+#	<Host "hostname">
+#		<Type "cpu">
+#			Instance "idle"
+#			FailureMin 10
+#		</Type>
+#
+#		<Plugin "memory">
+#			<Type "memory">
+#				Instance "cached"
+#				WarningMin 100000000
+#			</Type>
+#		</Plugin>
+#	</Host>
+#</Plugin>
+

+ 5 - 0
roles/common/handlers/main.yml

@@ -0,0 +1,5 @@
+- name: reload sshd
+  shell: systemctl reload ssh
+
+- name: reload resolv config
+  shell: resolvconf -u

+ 135 - 0
roles/common/tasks/main.yml

@@ -0,0 +1,135 @@
+---
+# Allgemeine Konfigurationen für alle Server
+
+- name: Enable syntax highlighting in vim by default
+  lineinfile:
+    dest: ~/.vimrc
+    regexp: '^syntax '
+    line: 'syntax on'
+    owner: root
+    group: root
+    mode: 0644
+    create: yes
+
+- name: Update .bash_profile file
+  template:
+    src: bash_profile.j2
+    dest: ~/.bash_profile
+
+- name: Flush all handlers
+  meta: flush_handlers
+
+- name: add default repo
+  #Freifunk- und Rollen-Repos erst in den jeweiligen Rollen
+  apt_repository:
+    repo: "{{ item }}"
+    state: present
+  with_items:
+    - "deb http://ftp.de.debian.org/debian/ {{ ansible_distribution_release }} main"
+    - "deb http://ftp.de.debian.org/debian/ {{ ansible_distribution_release }}-updates main"
+    - "deb http://security.debian.org/ {{ ansible_distribution_release }}/updates main"
+  when: ansible_distribution == "Debian"
+
+- name: Eventuelles CDROM-Repo von der Installation entfernen
+  lineinfile:
+    dest: /etc/apt/sources.list
+    state: absent
+    regexp: 'cdrom'
+
+- name: install common packages
+  apt:
+    pkg: "{{ item }}"
+    update_cache: yes
+    state: present
+  with_items:
+    - vim
+    - wget
+    - vnstat
+    - tmux
+    - pastebinit
+    - htop
+    - jnettop
+    - iotop
+    - tcpdump
+    - screen
+    - strace
+    - socat
+    - dnsutils
+    - host
+    - apt-transport-https
+    - tshark
+    - dwdiff
+    - molly-guard
+    - git
+    - iperf3
+    - mtr-tiny
+    - dhcpdump
+    - dhcping
+    - irqbalance
+    - build-essential
+    - ethtool
+    - mc
+
+- name: uninstall unneeded packages
+  apt:
+    pkg: "{{ item }}"
+    update_cache: yes
+    state: absent
+  with_items:
+    - rpcbind
+
+- name: SSH-Schlüsseldatei generieren
+  template:
+    src: authorized_keys.j2
+    dest: /root/.ssh/authorized_keys
+  when: administratorenteam is defined
+
+- name: SSH-Dämon Passwortanmeldung abschalten
+  lineinfile:
+    dest: /etc/ssh/sshd_config
+    regexp: "^[#]?PasswordAuthentication"
+    line: "PasswordAuthentication no"
+  notify: reload sshd
+
+- locale_gen: name=de_DE.UTF-8 state=present
+
+- name: "Get all files in /etc/logrotate.d/"
+  raw: find /etc/logrotate.d/ -type f
+  register: logrotate_files
+  check_mode: no
+  changed_when: False
+
+- name: "Update logrotate cycle in /etc/logrotate.d/"
+  replace:
+    dest: "{{item}}"
+    regexp: 'daily|weekly|monthly'
+    replace: '{{logrotate.cycle}}'
+  with_items: "{{logrotate_files.stdout_lines}}"
+
+- name: "Update logrotate count in /etc/logrotate.d/"
+  replace:
+    dest: "{{item}}"
+    regexp: 'rotate[ \t]+[0-9]+'
+    replace: 'rotate {{logrotate.count}}'
+  with_items: "{{logrotate_files.stdout_lines}}"
+
+- name: Logrotate Rotationszyklus und Anzahl anpassen
+  template:
+    src: logrotate.conf.j2
+    dest: /etc/logrotate.conf
+  when: logrotate is defined
+
+- name: Setze Timeout für das stopen von Interfaces
+  lineinfile:
+    dest: /lib/systemd/system/networking.service.d/network-pre.conf
+    line: "[Service]"
+    state: present
+  when: ansible_distribution == "Debian" and ansible_distribution_major_version == "8"
+
+- name: Setze Timeout für das stopen von Interfaces
+  lineinfile:
+    dest: /lib/systemd/system/networking.service.d/network-pre.conf
+    regexp: "^TimeoutStopSec="
+    line: "TimeoutStopSec=60"
+    state: present
+  when: ansible_distribution == "Debian" and ansible_distribution_major_version == "8"

+ 4 - 0
roles/common/templates/authorized_keys.j2

@@ -0,0 +1,4 @@
+{% for admin in administratorenteam %}
+{{ lookup('file', 'inventory/keyfiles/' + admin + '.pub') }}
+{% endfor %}
+

+ 35 - 0
roles/common/templates/bash_profile.j2

@@ -0,0 +1,35 @@
+
+
+#############################################################################
+
+export PS1='\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;36m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]'
+umask 022
+
+#############################################################################
+
+eval "`dircolors`"
+
+#############################################################################
+
+alias ls='ls $LS_OPTIONS'
+alias ll='ls $LS_OPTIONS -l'
+alias l='ls $LS_OPTIONS -lA'
+alias ..='cd ..'
+alias ...='cd ../..'
+alias ..2='cd ../..'
+alias ..3='cd ../../..'
+alias ..4='cd ../../../..'
+alias s='ssh -l root'
+
+#############################################################################
+
+export HISTFILESIZE=99999999
+export HISTSIZE=99999999
+export HISTCONTROL="ignoreboth"
+
+export LS_OPTIONS='--color=auto -h'
+
+#export GREP_OPTIONS="--color"
+
+#############################################################################
+

+ 52 - 0
roles/common/templates/logrotate.conf.j2

@@ -0,0 +1,52 @@
+# see "man logrotate" for details
+{{logrotate.cycle}}
+
+rotate {{logrotate.count}}
+
+# create new (empty) log files after rotating old ones
+create
+
+# uncomment this if you want your log files compressed
+#compress
+
+# packages drop log rotation information into this directory
+include /etc/logrotate.d
+
+# no packages own wtmp, or btmp -- we'll rotate them here
+/var/log/wtmp {
+    missingok
+    monthly
+    create 0664 root utmp
+    rotate 1
+}
+
+/var/log/btmp {
+    missingok
+    monthly
+    create 0660 root utmp
+    rotate 1
+}
+{% if 'gateways' in group_names or 'services' in group_names %}
+/var/log/named/bind.log {
+    {{logrotate.cycle}}
+    rotate {{logrotate.count}}
+    copytruncate
+}
+{% endif %}
+
+{% if 'gateways' in group_names %}
+/var/log/tunneldigger-broker.log {
+    {{logrotate.cycle}}
+    rotate {{logrotate.count}}
+    copytruncate
+}
+{% endif %}
+
+# system-specific logs may be configured here
+{% if 'dhcp_type' in hostvars[inventory_hostname] and dhcp_type == 'kea' %}
+/var/log/kea-dhcp4.log {
+    {{logrotate.cycle}}
+    rotate {{logrotate.count}}
+    copytruncate
+}
+{% endif %}

+ 6 - 0
roles/dhcp/handlers/main.yml

@@ -0,0 +1,6 @@
+---
+- name: restart isc-dhcp-server
+  service: name=isc-dhcp-server state=restarted
+
+- name: restart isc-dhcp6-server
+  service: name=isc-dhcp6-server state=restarted

+ 22 - 0
roles/dhcp/tasks/main.yml

@@ -0,0 +1,22 @@
+---
+- name: Ramdisk in fstab eintragen
+  mount: name=/var/lib/dhcp src=tmpfs fstype=tmpfs opts='defaults,size=100M' state=mounted
+  notify:
+    - restart isc-dhcp-server
+
+- name: install isc-dhcp-server
+  apt: pkg=isc-dhcp-server state=installed
+
+- name: create dhcp defaults 
+  template: src=isc-dhcp-server.j2 dest=/etc/default/isc-dhcp-server
+  notify:
+    - restart isc-dhcp-server
+  
+- name: create dhcp config
+  template: src=dhcpd.conf.j2 dest=/etc/dhcp/dhcpd.conf
+  notify:
+    - restart isc-dhcp-server
+
+- stat: path=/var/lib/dhcp/dhcpd.leases
+  register: leases4_file
+

+ 26 - 0
roles/dhcp/templates/dhcpd.conf.j2

@@ -0,0 +1,26 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+default-lease-time {{dhcp_global.lease_default}};
+max-lease-time {{dhcp_global.lease_max}};
+
+authoritative;
+
+log-facility local7;
+
+subnet {{ff_network.v4_network | ipaddr('network')}} netmask {{ff_network.v4_network | ipaddr('netmask')}} {
+    range {{dhcp.range_start}} {{dhcp.range_end}};
+
+    option routers {{ff_network.v4_network | ipaddr(server_id) | ipaddr('address') }};
+    option domain-name-servers {{ff_network.v4_network | ipaddr(server_id) | ipaddr('address') }};
+    option interface-mtu {{dhcp_global.mtu}};
+}
+{% if "static_hosts" in hostvars[inventory_hostname] %}
+
+{% for host in static_hosts %}
+
+host {{host.name}} {
+    hardware ethernet {{host.mac_address}};
+    fixed-address {{host.v4_address}};
+}
+{% endfor %}
+{% endif %}
+

+ 8 - 0
roles/dhcp/templates/dhcpd6.conf.j2

@@ -0,0 +1,8 @@
+# Enable RFC 5007 support (same than for DHCPv4)
+allow leasequery;
+
+# Global definitions for name server address(es)
+option dhcp6.name-servers {{ff_network.v6_network | ipaddr(server_id) | ipaddr('address')}};
+
+  subnet6 {{ff_network.v6_network}} {
+}

+ 3 - 0
roles/dhcp/templates/isc-dhcp-server.j2

@@ -0,0 +1,3 @@
+# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
+#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
+INTERFACES="bat0"

+ 115 - 0
roles/dhcp/templates/isc-dhcp6-server.init.j2

@@ -0,0 +1,115 @@
+#!/bin/sh
+#
+#
+
+### BEGIN INIT INFO
+# Provides:          isc-dhcp6-server
+# Required-Start:    $remote_fs $network $syslog
+# Required-Stop:     $remote_fs $network $syslog
+# Should-Start:      $local_fs slapd $named
+# Should-Stop:       $local_fs slapd
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: DHCP6 server
+# Description:       Dynamic Host Configuration Protocol Server V6
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+test -f /usr/sbin/dhcpd || exit 0
+
+DHCPD_DEFAULT="${DHCPD_DEFAULT:-/etc/default/isc-dhcp6-server}"
+
+# It is not safe to start if we don't have a default configuration...
+if [ ! -f "$DHCPD_DEFAULT" ]; then
+        echo "$DHCPD_DEFAULT does not exist! - Aborting..."
+        if [ "$DHCPD_DEFAULT" = "/etc/default/isc-dhcp6-server" ]; then
+                echo "Run 'dpkg-reconfigure isc-dhcp-server' to fix the problem."
+        fi
+        exit 0
+fi
+
+. /lib/lsb/init-functions
+
+# Read init script configuration
+[ -f "$DHCPD_DEFAULT" ] && . "$DHCPD_DEFAULT"
+
+NAME=dhcpd
+DESC="ISC DHCP6 server"
+# fallback to default config file
+DHCPD_CONF=${DHCPD_CONF:-/etc/dhcp/dhcpd6.conf}
+# try to read pid file name from config file, with fallback to /var/run/dhcpd.pid
+if [ -z "$DHCPD_PID" ]; then
+        DHCPD_PID=$(sed -n -e 's/^[ \t]*pid-file-name[ \t]*"(.*)"[ \t]*;.*$/\1/p' < "$DHCPD_CONF" 2>/dev/null | head -n 1)
+fi
+DHCPD_PID="${DHCPD_PID:-/var/run/dhcpd6.pid}"
+
+test_config()
+{
+        if ! /usr/sbin/dhcpd -6 -t $OPTIONS -q -cf "$DHCPD_CONF" > /dev/null 2>&1; then
+                echo "dhcpd self-test failed. Please fix $DHCPD_CONF."
+                echo "The error was: "
+                /usr/sbin/dhcpd -6 -t $OPTIONS -cf "$DHCPD_CONF"
+                exit 1
+        fi
+}
+
+# single arg is -v for messages, -q for none
+check_status()
+{
+    if [ ! -r "$DHCPD_PID" ]; then
+        test "$1" != -v || echo "$NAME is not running."
+        return 3
+    fi
+    if read pid < "$DHCPD_PID" && ps -p "$pid" > /dev/null 2>&1; then
+        test "$1" != -v || echo "$NAME is running."
+        return 0
+    else
+        test "$1" != -v || echo "$NAME is not running but $DHCPD_PID exists."
+        return 1
+    fi
+}
+
+case "$1" in
+        start)
+                test_config
+                log_daemon_msg "Starting $DESC" "$NAME"
+                start-stop-daemon --start --quiet --pidfile "$DHCPD_PID" \
+                        --exec /usr/sbin/dhcpd -- \
+                        -6 -q $OPTIONS -cf "$DHCPD_CONF" -pf "$DHCPD_PID" $INTERFACES
+                sleep 2
+
+                if check_status -q; then
+                        log_end_msg 0
+                else
+                        log_failure_msg "check syslog for diagnostics."
+                        log_end_msg 1
+                        exit 1
+                fi
+                ;;
+        stop)
+                log_daemon_msg "Stopping $DESC" "$NAME"
+                start-stop-daemon --stop --quiet --pidfile "$DHCPD_PID"
+                log_end_msg $?
+                rm -f "$DHCPD_PID"
+                ;;
+        restart | force-reload)
+                test_config
+                $0 stop
+                sleep 2
+                $0 start
+                if [ "$?" != "0" ]; then
+                        exit 1
+                fi
+                ;;
+        status)
+                echo -n "Status of $DESC: "
+                check_status -v
+                exit "$?"
+                ;;
+        *)
+                echo "Usage: $0 {start|stop|restart|force-reload|status}"
+                exit 1 
+esac
+
+exit 0

+ 21 - 0
roles/dhcp/templates/isc-dhcp6-server.j2

@@ -0,0 +1,21 @@
+# Defaults for isc-dhcp-server initscript
+# sourced by /etc/init.d/isc-dhcp-server
+# installed at /etc/default/isc-dhcp-server by the maintainer scripts
+ 
+#
+# This is a POSIX shell fragment
+#
+ 
+# Path to dhcpd's config file (default: /etc/dhcp/dhcpd6.conf).
+#DHCPD_CONF=/etc/dhcp/dhcpd6.conf
+ 
+# Path to dhcpd's PID file (default: /var/run/dhcpd6.pid).
+#DHCPD_PID=/var/run/dhcpd6.pid
+ 
+# Additional options to start dhcpd with.
+#       Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
+#OPTIONS=""
+ 
+# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
+#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
+INTERFACES="bat0"

+ 3 - 0
roles/dienste_lamp/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: restart apache
+  service: name=apache2 state=restarted

+ 151 - 0
roles/dienste_lamp/tasks/main.yml

@@ -0,0 +1,151 @@
+- include_vars: passwords.yml
+
+## MariaDB ##
+- name: Unattended package installation
+  shell: export DEBIAN_FRONTEND=noninteractive
+  changed_when: false
+
+- name: Install MariaDB
+  apt:
+    pkg: "{{ item }}"
+    update_cache: no
+    state: installed
+  with_items:
+    - mariadb-server
+    - mariadb-client
+    - python-mysqldb
+
+- name: Start and enable mysql
+  service: name=mysql state=started enabled=yes
+
+- name: Set root Password
+  mysql_user: name=root host={{ item }} password={{ mysql_root_password }} state=present
+  with_items:
+    - localhost
+    - 127.0.0.1
+    - ::1
+
+- name: Reload privilege tables
+  command: 'mysql -ne "{{ item }}"'
+  with_items:
+    - FLUSH PRIVILEGES
+  changed_when: False
+
+- name: Add .my.cnf
+  template: src=my.cnf.j2 dest=/root/.my.cnf owner=root group=root mode=0600
+
+- name: Remove anonymous users
+  command: 'mysql -ne "{{ item }}"'
+  with_items:
+    - DELETE FROM mysql.user WHERE User=''
+  changed_when: False
+
+- name: Disallow root login remotely
+  command: 'mysql -ne "{{ item }}"'
+  with_items:
+    - DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')
+  changed_when: False
+
+- name: Remove test database and access to it
+  command: 'mysql -ne "{{ item }}"'
+  with_items:
+    - DROP DATABASE IF EXISTS test
+    - DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'
+  changed_when: False
+
+- name: Reload privilege tables
+  command: 'mysql -ne "{{ item }}"'
+  with_items:
+    - FLUSH PRIVILEGES
+  changed_when: False
+
+## Apache ##
+- name: PHP | Install Ondrej PHP PPA
+  apt_repository:
+    repo: 'ppa:ondrej/php'
+    update_cache: yes
+
+- name: Install Apache and PHP 
+  apt:
+    pkg: "{{ item }}"
+    update_cache: no
+    state: installed
+  with_items:
+    - apache2
+    - php5.6
+    - php5.6-cli
+    - php5.6-mysql
+    - php-gettext
+    - php5.6-mbstring
+    - libapache2-mod-php5.6
+    - php5.6-gd
+    - php5.6-imap
+    - php5.6-xml
+    - php5.6-intl
+    - php5.6-apcu
+  notify:
+    - "restart apache"
+
+- name: purge php7.1
+  apt:
+    pkg: php7.1-common
+    update_cache: no
+    state: absent
+    purge: yes
+  notify:
+    - "restart apache"
+
+- name: activate cgi.fix_pathinfo in php.ini
+  lineinfile: dest=/etc/php/5.6/apache2/php.ini regexp=^[;]?cgi.fix_pathinfo line="cgi.fix_pathinfo=1"
+  notify:
+    - "restart apache"
+
+- name: set timezone in php.ini
+  lineinfile: dest=/etc/php/5.6/apache2/php.ini regexp=^[;]?date.timezone line="date.timezone = Europe/Berlin"
+  notify:
+    - "restart apache"
+
+- name: Check existence of root directory for virthost
+  stat:
+    path: /var/www/{{inventory_hostname_short}}.{{freifunk.domain}}
+  register: virthostroot
+
+- name: create root directory for virthost
+  file: name=/var/www/{{inventory_hostname_short}}.{{freifunk.domain}} state=directory
+  when: virthostroot.stat.islnk is not defined
+
+- name: Deploy virthost config
+  template:
+    src: templates/virthost.conf.j2
+    dest: /etc/apache2/sites-available/{{inventory_hostname_short}}.{{freifunk.domain}}.conf
+  notify:
+    - "restart apache"
+
+- name: Enable virthost site with a2ensite 
+  shell: a2ensite -q {{inventory_hostname_short}}.{{freifunk.domain}}.conf
+  args:
+    creates: /etc/apache2/sites-enabled/{{inventory_hostname_short}}.{{freifunk.domain}}.conf
+  notify:
+    - "restart apache"
+
+- name: Enable mod_rewrite
+  shell: a2enmod rewrite
+
+- name: install letsencrypt
+  apt:
+    pkg: python-letsencrypt-apache
+    update_cache: no
+    state: installed
+
+- name: Create certificate
+  shell: letsencrypt --non-interactive --agree-tos --email {{freifunk.email}} --apache --domains {{inventory_hostname_short}}.{{freifunk.domain}}
+  args:
+    creates: /etc/letsencrypt/live/{{inventory_hostname_short}}.{{freifunk.domain}}/cert.pem 
+
+- name: Install renewal cron
+  cron:
+    name: "Let's Encrypt Renewal"
+    weekday: "1"
+    hour: "2"
+    minute: "30"
+    job: "/usr/bin/letsencrypt renew >> /var/log/le-renew.log"

+ 3 - 0
roles/dienste_lamp/templates/my.cnf.j2

@@ -0,0 +1,3 @@
+[client]
+user=root
+password={{ mysql_root_password }}

+ 13 - 0
roles/dienste_lamp/templates/virthost.conf.j2

@@ -0,0 +1,13 @@
+<VirtualHost *:80>
+        ServerName {{inventory_hostname_short}}.{{freifunk.domain}}
+        ServerAdmin {{freifunk.email}}
+        DocumentRoot /var/www/{{inventory_hostname_short}}.{{freifunk.domain}}
+        ErrorLog ${APACHE_LOG_DIR}/{{inventory_hostname_short}}.{{freifunk.domain}}-error.log
+        CustomLog ${APACHE_LOG_DIR}/{{inventory_hostname_short}}.{{freifunk.domain}}-access.log combined
+	<Directory /var/www/{{inventory_hostname_short}}.{{freifunk.domain}}>
+		Options -Indexes 
+		AllowOverride All
+	</Directory>
+        RewriteEngine On
+        RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
+</VirtualHost> 

+ 104 - 0
roles/dienste_osticket/tasks/main.yml

@@ -0,0 +1,104 @@
+- name: Install required packages for osTicket
+  apt:
+    pkg: "{{ item }}"
+    update_cache: no
+    state: installed
+  with_items:
+    - sendmail
+    - unzip
+ 
+- name: Create database for osticket
+  mysql_db: name=osticket state=present
+
+- name: Create database user for osticket
+  mysql_user: name=osticket host=localhost password=osticket state=present priv=osticket.*:ALL
+  register: createdbuser
+
+- name: Reload privilege tables
+  command: 'mysql -ne "{{ item }}"'
+  with_items:
+    - FLUSH PRIVILEGES
+  changed_when: False
+  when: createdbuser.changed
+
+- name: create directory for osticket
+  file: name=/opt/osticket state=directory
+
+- name: get osTicket
+  get_url:
+    url: "http://osticket.com/sites/default/files/download/osTicket-v1.10.zip"
+    dest: /opt/osticket/osTicket-v1.10.zip
+  register: getosticket
+
+- name: unarchive osTicket
+  unarchive:
+    src: /opt/osticket/osTicket-v1.10.zip
+    dest: /opt/osticket/
+    remote_src: True
+  when: getosticket.changed
+
+- name: get german language file
+  get_url:
+    url: "http://osticket.com/sites/default/files/download/lang/de.phar"
+    dest: /opt/osticket/upload/include/i18n/de.phar
+
+- name: Adjust permissions of /opt/osticket/upload
+  file:
+    path: /opt/osticket/upload
+    owner: www-data
+    group: www-data
+    recurse: yes
+
+- name: copy ost-sampleconfig.php to ost-config.php
+  shell: cp /opt/osticket/upload/include/ost-sampleconfig.php /opt/osticket/upload/include/ost-config.php
+  args:
+    creates: /opt/osticket/upload/include/ost-config.php  
+
+- name: Adjust permissions of /opt/osticket/upload/include/ost-config.php
+  file:
+    path: /opt/osticket/upload/include/ost-config.php
+    mode: 0666
+
+- name: get webroot state
+  stat: path=/var/www/{{inventory_hostname_short}}.{{freifunk.domain}}
+  register: webroot_stat
+
+- name: remove old webroot directory
+  file: src=/opt/osticket/upload dest=/var/www/{{inventory_hostname_short}}.{{freifunk.domain}} state=absent
+  when: webroot_stat.stat.isdir is defined and webroot_stat.stat.isdir
+
+- name: link osticket to webroot
+  file: src=/opt/osticket/upload dest=/var/www/{{inventory_hostname_short}}.{{freifunk.domain}} state=link
+
+- name: setup already moved?
+  stat: path=/opt/osticket/upload/setup
+  register: setup_stat
+
+##############################################################################################################
+- pause:
+    prompt: "Please execute setup assistent on https://{{inventory_hostname_short}}.{{freifunk.domain}}/setup"
+  when: setup_stat.stat.exists
+##############################################################################################################
+
+- name: Adjust permissions of /opt/osticket/upload/include/ost-config.php
+  file:
+    path: /opt/osticket/upload/include/ost-config.php
+    mode: 0644
+
+- name: Move folder setup to setup_hidden
+  command: mv /opt/osticket/upload/setup /opt/osticket/upload/setup_hidden
+  when: setup_stat.stat.exists
+
+- name: Adjust permissions of /opt/osticket/upload/setup_hidden
+  file:
+    path: /opt/osticket/upload/setup_hidden
+    owner: root
+    group: root
+    mode: 0700
+    recurse: yes
+ 
+- name: Install cron for osticket
+  cron:
+    name: "osTicket"
+    minute: "*/5"
+    job: "php /opt/osticket/upload/api/cron.php"

+ 8 - 0
roles/fastd/files/status.pl

@@ -0,0 +1,8 @@
+#!/usr/bin/perl -w
+use strict;
+use IO::Socket::UNIX qw( SOCK_STREAM );
+$ARGV[0] or die("Usage: status.pl <socket>\n");
+my $socket = IO::Socket::UNIX->new(Type => SOCK_STREAM, Peer => $ARGV[0],) or die("Can't connect to server: $!\n");
+foreach my $line (<$socket>) {
+    print $line;
+}

+ 4 - 0
roles/fastd/handlers/main.yml

@@ -0,0 +1,4 @@
+---
+- name: restart fastd
+  service: name=fastd state=restarted
+  

+ 68 - 0
roles/fastd/tasks/main.yml

@@ -0,0 +1,68 @@
+---
+# Prüfe Repo-Quelle
+- name: Schlüssel hinzufügen
+  apt_key: keyserver=keyserver.ubuntu.com  id=16EF3F64CB201D9C
+
+- name: set fastd-repo
+  apt_repository: repo='deb http://repo.universe-factory.net/debian/ sid main' state=present
+
+# Fastd-Daemon, Habeged-Daemon
+
+- name: install fastd (vpn daemon) and haveged (entropy daemon)
+  apt:
+    pkg: "{{ item }}"
+    update_cache: yes
+    state: installed
+  with_items:
+    - fastd
+    - haveged
+
+- name: create config directory
+  file: path=/etc/fastd/vpn state=directory
+
+# generate new fastd keypair if no fastd_key file exists
+# new key will only be generated, if no secret,key file exists (public key doesn't matter)
+- name: generate fastd key (if not exists)
+  shell: fastd --generate-key
+  register: fastd_key_generated
+  args:
+    creates: /etc/fastd/vpn/secret.key
+  notify:
+    - restart fastd
+
+# write public & private key to seperate keyfiles, if new fastd key is generated
+- template: src=secret.key.j2 dest=/etc/fastd/vpn/secret.key owner=root group=root mode=0600
+  when: fastd_key_generated|changed
+- template: src=public.key.j2 dest=/etc/fastd/vpn/public.key
+  when: fastd_key_generated|changed
+
+- name: create dummy peer directory
+  file: path=/etc/fastd/vpn/peers state=directory
+
+# create dummy peer file
+- name: create dummy peer
+  template: src=dummy.j2 dest=/etc/fastd/vpn/peers/dummy
+
+# create fastd config
+- name: create config
+  template: src=fastd.conf.j2 dest=/etc/fastd/vpn/fastd.conf
+  notify:
+    - restart fastd
+
+- name: create verify directory
+  file: path=/var/gateway-ffms/fastd/ state=directory
+
+# todo: bessere location wählen
+- name: create verify script (blacklisting)
+  template: src=verify.sh.j2 dest=/var/gateway-ffms/fastd/verify.sh
+
+- stat: path=/var/gateway-ffms/fastd/blacklist
+  register: blacklist_file
+
+- name: create blacklist file (if not exists)
+  file: path=/var/gateway-ffms/fastd/blacklist state=touch
+  when: blacklist_file.stat.exists == False
+
+- name: status.pl nach /root kopieren
+  copy: src=status.pl dest=/root/status.pl owner=root group=root mode=0755
+

+ 3 - 0
roles/fastd/templates/dummy.j2

@@ -0,0 +1,3 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+# A dummy peer is needed so fastd will start 
+key "THIS-IS-A-DUMMY";

+ 56 - 0
roles/fastd/templates/fastd.conf.j2

@@ -0,0 +1,56 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+# Bind to a fixed address and port, IPv4 and IPv6
+bind {{ansible_eth0.ipv4.address}}:{{fastd.port}} interface "eth0";
+
+{% for v6 in ansible_eth0.ipv6 %}
+{% if v6.scope == 'global' %}
+bind [{{v6.address}}]:{{fastd.port}} interface "eth0";
+{% endif %}
+{% endfor %}
+
+# Set the user, fastd will work as
+user "nobody";
+
+# Set the interface name
+interface "mesh-vpn";
+
+# Set the mode, the interface will work as
+mode tap;
+
+# Set the mtu of the interface (salsa2012 with ipv6 will need 1406)
+mtu 1406;
+
+# Set the methods (aes128-gcm preferred, salsa2012+umac preferred for nodes)
+method "aes128-gcm";
+method "salsa2012+umac";
+method "salsa2012+gmac";
+
+# Secret key generated by `fastd --generate-key`
+include "secret.key";
+
+# Log everything to syslog
+log to syslog level debug;
+
+# Include peers from our git-repos
+include peers from "/etc/fastd/vpn/peers/";
+
+# Status Socket
+status socket "/tmp/fastd-status";
+
+# Configure a shell command that is run on connection attempts by unknown peers (true means, all attempts are accepted)
+# on verify "true";
+on verify "
+  /bin/bash /var/gateway-ffms/fastd/verify.sh $PEER_KEY
+";
+
+# Configure a shell command that is run when fastd comes up
+on up "
+  chmod ugo+rw /tmp/fastd-status
+  ip link set dev $INTERFACE address de:ad:be:ef:43:{{server_id}}
+  ip link set dev $INTERFACE up
+  batctl if add $INTERFACE
+{% if fastd.ip_rule_42 %}
+  ip rule add from {{ffrl_nat_ip}} lookup 42
+  ip -6 rule add from {{ff_network.v6_network}} lookup 42
+{% endif %}
+";

+ 2 - 0
roles/fastd/templates/public.key.j2

@@ -0,0 +1,2 @@
+# {{ ansible_managed }} 
+key "{{fastd_key_generated.stdout_lines[1]|replace("Public: ","")}}";

+ 2 - 0
roles/fastd/templates/secret.key.j2

@@ -0,0 +1,2 @@
+# {{ ansible_managed }} 
+secret "{{fastd_key_generated.stdout_lines[0]|replace("Secret: ","")}}";

+ 13 - 0
roles/fastd/templates/verify.sh.j2

@@ -0,0 +1,13 @@
+#!/bin/bash
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+# Implementierung einer Fastd Blacklist 
+# Das Script wird aus Fastd beim Aufbau einer Verbidung aufgerufen
+# Die geblockten Keys werden in der Datei blacklist aufgeführt
+
+PEER_KEY=$1
+
+if /bin/grep -Fq $PEER_KEY /var/gateway-ffms/fastd/blacklist; then
+        exit 1
+else
+        exit 0
+fi

+ 1 - 0
roles/gateways_2nd_vnic/handlers/main.yml

@@ -0,0 +1 @@
+---

+ 6 - 0
roles/gateways_2nd_vnic/tasks/2nd_vnic_interface.yml

@@ -0,0 +1,6 @@
+---
+
+- name: Setup secondary vnic interface (used for internal routing to old supernodes)
+  template:
+    dest: "/etc/network/interfaces.d/05_2nd_vnic_interface.cfg"
+    src: "2nd_vnic_interface.cfg.j2"

+ 3 - 0
roles/gateways_2nd_vnic/tasks/main.yml

@@ -0,0 +1,3 @@
+---
+
+- include: 2nd_vnic_interface.yml

+ 14 - 0
roles/gateways_2nd_vnic/templates/2nd_vnic_interface.cfg.j2

@@ -0,0 +1,14 @@
+
+# ip rule regeln um FF Trafic erstmal über den ospf link zu dem alten sndor1 zu schicken und da per NAT weiterzuleiten
+
+auto {{ secondary_vnic }}
+iface {{ secondary_vnic }} inet static
+    address {{ secondary_vnic_ip4 }}
+    netmask {{ secondary_vnic_netmask4 }}
+    pre-up ip rule add from 10.233.128.0/17 table ffnet
+    pre-up ip rule add to 10.233.128.0/17 table ffnet
+    post-up ip route add default via 10.233.254.5 dev eth1 table ffnet
+    pre-down ip route del default via 10.233.254.5 dev eth1 table ffnet
+    post-down ip rule del from 10.233.128.0/17 table ffnet
+    post-down ip rule del to 10.233.128.0/17 table ffnet
+

+ 6 - 0
roles/gateways_batman/handlers/main.yml

@@ -0,0 +1,6 @@
+---
+- name: restart networking
+  shell: systemctl restart networking; if systemctl -q is-active isc-dhcp-server; then systemctl restart isc-dhcp-server; fi; if systemctl -q is-active kea-dhcp4.service; then systemctl restart kea-dhcp4.service; fi; if systemctl -q is-active tunneldigger; then systemctl restart tunneldigger; fi
+
+- name: restart fastd
+  service: name=fastd state=restarted

+ 21 - 0
roles/gateways_batman/tasks/main.yml

@@ -0,0 +1,21 @@
+# creating batman interface
+- name: Create interfaces - batman file
+  template: src="batman.j2" dest="/etc/network/interfaces.d/10_batman.cfg"
+  notify:
+    - restart networking
+  when: domaenenliste is defined
+
+#append line in interfaces file for reading additional config files
+- name: let read interfaces from interfaces
+  lineinfile: dest="/etc/network/interfaces" line="source /etc/network/interfaces.d/*"
+  notify:
+    - restart networking
+  when: domaenenliste is defined
+
+- name: Routingtabelle 42 auch ffnet nennen
+  lineinfile: dest="/etc/iproute2/rt_tables" line="42   ffnet"
+  when: domaenenliste is defined
+
+- name: Drei Sekunden nach Kernelpanik automatisch neu starten
+  sysctl: name="kernel.panic" value=3 sysctl_set=yes state=present reload=yes
+  when: domaenenliste is defined

+ 47 - 0
roles/gateways_batman/templates/batman.j2

@@ -0,0 +1,47 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+
+# Batman Interface 
+# - Erstellt das virtuelle Interface fuer das Batman-Modul und bindet dieses an die Netzwerkbruecke
+# - Die unten angelegte Routing-Tabelle wird spaeter fuer das Routing innerhalb von Freifunk (Router/VPN) verwendet
+
+{% for item in domaenenliste|dictsort %}
+auto bat{{item[0]}}
+iface bat{{item[0]}} inet static
+        address {{domaenen[item[0]].ffv4_network | ipaddr(item[1].server_id) | ipaddr('address') }}
+        netmask {{domaenen[item[0]].ffv4_network | ipaddr('netmask')}}
+        pre-up modprobe batman-adv
+        pre-up ip link add bat{{item[0]}} type batadv
+        post-up ip link set dev bat{{item[0]}} up
+        post-up batctl -m bat{{item[0]}} it 10000
+        post-up batctl -m bat{{item[0]}} gw server {{batman.downstream}}/{{batman.upstream}}
+        post-up batctl -m bat{{item[0]}} if add br{{item[0]}} ||:
+{% for host in groups['supernodes'] %}
+{% if host != inventory_hostname %}
+{% if hostvars[host].domaenenliste is defined %}
+{% for item2 in hostvars[host].domaenenliste|dictsort %}
+{% if item[0] == item2[0] %}
+        post-up batctl -m bat{{item[0]}} if add t{{item[0]}}-{{host}} ||:
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endfor %}
+        post-up ip rule add from all fwmark 0x1 table ffnet pref 16000 ||:
+        post-up ip rule add iif bat{{item[0]}} table ffnet pref 16000 ||:
+        post-up ip rule add iif lo lookup ffnet suppress_prefixlength 0 pref 16500 ||:
+        post-down ip rule del from all fwmark 0x1 table ffnet ||:
+        post-down ip rule del iif bat{{item[0]}} table ffnet ||:
+        post-down ip rule del iif lo lookup ffnet suppress_prefixlength 0 ||:
+
+iface bat{{item[0]}} inet6 static
+        address {{domaenen[item[0]].ffv6_network | ipaddr(item[1].server_id) | ipaddr('address') }}
+        netmask {{domaenen[item[0]].ffv6_network | ipaddr('prefix')}}
+        post-up ip -6 rule add from all fwmark 0x1 table ffnet pref 16000 ||:
+        post-up ip -6 rule add iif bat{{item[0]}} table ffnet pref 16000 ||:
+        post-up ip -6 rule add iif lo lookup ffnet suppress_prefixlength 0 pref 16500 ||:
+        post-up ip -6 rule add from {{domaenen[item[0]].ffv6_network | ipaddr(item[1].server_id) | ipaddr('address') }} lookup ffnet pref 16000 ||:
+        post-down ip -6 rule del from all fwmark 0x1 table ffnet ||:
+        post-down ip -6 rule del iif bat{{item[0]}} table ffnet ||:
+        post-down ip -6 rule del iif lo lookup ffnet suppress_prefixlength 0 ||:
+        post-down ip -6 rule del from {{domaenen[item[0]].ffv6_network | ipaddr(item[1].server_id) | ipaddr('address') }} lookup ffnet ||:
+{% endfor %}

+ 3 - 0
roles/gateways_dhcp/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: restart isc-dhcp-server
+  service: name=isc-dhcp-server state=restarted

+ 45 - 0
roles/gateways_dhcp/tasks/main.yml

@@ -0,0 +1,45 @@
+---
+
+- name: install requirements
+  apt: pkg=rsync state=installed
+
+- name: create persitent folder dhcpd data
+  file: path=/var/lib/dhcp_persistent state=directory mode=0755
+  notify:
+    - restart isc-dhcp-server
+
+- name: Ramdisk in fstab eintragen
+  mount: name=/var/lib/dhcp src=tmpfs fstype=tmpfs opts='defaults,size=100M' state=mounted
+  notify:
+    - restart isc-dhcp-server
+
+- name: create dir for tmpfs scripts
+  file: path=/usr/src/dhcpd state=directory
+
+- name: tmpfs start script for dhcpd
+  template: src=openramdisk.j2 dest=/usr/src/dhcpd/openramdisk mode="a+x"
+
+- name: tmpfs stop script for dhcpd
+  template: src=closeramdisk.j2 dest=/usr/src/dhcpd/closeramdisk mode="a+x"
+
+- name: tmpfs systemd service for dhcpd
+  template: src=dhcpd-tmpfs.service.j2 dest=/lib/systemd/system/dhcpd-tmpfs.service
+
+- name: enable dhcpd-tmpfs service
+  service: name=dhcpd-tmpfs enabled=yes state=started
+
+- name: install isc-dhcp-server
+  apt: pkg=isc-dhcp-server state=installed
+
+- name: create dhcp defaults 
+  template: src=isc-dhcp-server.j2 dest=/etc/default/isc-dhcp-server
+  notify:
+    - restart isc-dhcp-server
+  
+- name: create dhcpd config
+  template: src=dhcpd.conf.j2 dest=/etc/dhcp/dhcpd.conf
+  notify:
+    - restart isc-dhcp-server
+
+- stat: path=/var/lib/dhcp/dhcpd.leases
+  register: leases4_file

+ 2 - 0
roles/gateways_dhcp/templates/closeramdisk.j2

@@ -0,0 +1,2 @@
+#!/bin/bash
+rsync --archive /var/lib/dhcp/ /var/lib/dhcp_persistent/

+ 14 - 0
roles/gateways_dhcp/templates/dhcpd-tmpfs.service.j2

@@ -0,0 +1,14 @@
+[Unit]
+Description=Ramdisk for dhcpd
+After=syslog.target
+Requires=local-fs.target
+After=local-fs.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/src/dhcpd/openramdisk
+ExecStop=/usr/src/dhcpd/closeramdisk
+
+[Install]
+WantedBy=isc-dhcp-server.service

+ 28 - 0
roles/gateways_dhcp/templates/dhcpd.conf.j2

@@ -0,0 +1,28 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+default-lease-time {{dhcp_global.lease_default}};
+max-lease-time {{dhcp_global.lease_max}};
+
+authoritative;
+
+log-facility local7;
+
+{% for domaene in domaenenliste|dictsort %}
+subnet {{domaenen[domaene[0]].ffv4_network | ipaddr('network')}} netmask {{domaenen[domaene[0]].ffv4_network | ipaddr('netmask')}} {
+    interface bat{{domaene[0]}};
+    range {{domaene[1].dhcp_start}} {{domaene[1].dhcp_ende}};
+
+    option routers {{domaenen[domaene[0]].ffv4_network | ipaddr(domaene[1].server_id) | ipaddr('address') }};
+{% if public_dns_ip is defined %}
+    option domain-name-servers {{public_dns_ip }};
+{% else %}
+    option domain-name-servers {{domaenen[domaene[0]].ffv4_network | ipaddr(domaene[1].server_id) | ipaddr('address') }};
+{% endif %}
+
+    option interface-mtu {{dhcp_global.mtu}};
+{% if dhcp_global.domain_search is defined %}
+    option domain-name  "{{dhcp_global.domain_search}}";
+    option domain-search "{{dhcp_global.domain_search}}";
+{% endif %}
+}
+
+{% endfor %}

+ 3 - 0
roles/gateways_dhcp/templates/isc-dhcp-server.j2

@@ -0,0 +1,3 @@
+# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
+#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
+INTERFACES="{% for domaene in domaenenliste|dictsort %}bat{{domaene[0]}} {% endfor %}"

+ 2 - 0
roles/gateways_dhcp/templates/openramdisk.j2

@@ -0,0 +1,2 @@
+#!/bin/bash
+rsync --archive /var/lib/dhcp_persistent/ /var/lib/dhcp/

+ 3 - 0
roles/gateways_gre_upstream/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: restart networking
+  shell: systemctl restart networking; if systemctl -q is-active isc-dhcp-server; then systemctl restart isc-dhcp-server; fi; if systemctl -q is-active kea-dhcp4.service; then systemctl restart kea-dhcp4.service; fi; if systemctl -q is-active tunneldigger; then systemctl restart tunneldigger; fi

+ 23 - 0
roles/gateways_gre_upstream/tasks/main.yml

@@ -0,0 +1,23 @@
+---
+- name: let read interfaces from interfaces
+  lineinfile: dest="/etc/network/interfaces" line="source /etc/network/interfaces.d/*"
+  notify:
+    - restart networking
+
+- name: Konfig für die lo-Schnittstelle
+  template: src="lo.j2" dest="/etc/network/interfaces.d/00_lo.cfg"
+  notify:
+    - restart networking
+
+- name: lo-Block aus interfaces entfernen
+  lineinfile: dest="/etc/network/interfaces" line="auto lo" state="absent"
+
+- name: lo-Block aus interfaces entfernen
+  lineinfile: dest="/etc/network/interfaces" line="iface lo inet loopback" state="absent"
+
+- name: Create interfaces - gretap to ffrl or ffnw
+  template: src="gre_upstream.j2" dest="/etc/network/interfaces.d/40_gre_upstream.cfg"
+  notify:
+    - restart networking
+  when: ffrl_tun is defined or ffnw_tun is defined
+

+ 39 - 0
roles/gateways_gre_upstream/templates/gre_upstream.j2

@@ -0,0 +1,39 @@
+{% if ffrl_tun is defined %}
+{% for tun in ffrl_tun %}
+
+auto tun-ffrl-{{tun.name}}
+iface tun-ffrl-{{tun.name}} inet static
+        address {{tun.v4_remote | ipaddr( tun.v4_remote.split('.')[3] | int + 1) | ipaddr('address') }}
+        netmask {{tun.v4_remote | ipaddr('netmask')}}
+        pre-up ip tunnel add $IFACE mode gre local {{ansible_default_ipv4.address}} remote {{tun.gre_target | ipaddr('address') }} ttl 255
+        post-up ip link set $IFACE mtu 1400
+        post-down ip tunnel del $IFACE
+        post-up ip rule add iif $IFACE lookup ffnet
+        pre-down ip rule del iif $IFACE lookup ffnet ||:
+iface tun-ffrl-{{tun.name}} inet6 static
+        address {{tun.v6_remote | ipaddr('2') | ipaddr('address') }}
+        netmask {{tun.v6_remote | ipaddr('prefix')}}
+        post-up ip -6 rule add iif $IFACE lookup ffnet
+        pre-down ip -6 rule del iif $IFACE lookup ffnet ||:
+{% endfor %}
+{% endif %}
+
+{% if ffnw_tun is defined %}
+{% for tun in ffnw_tun %}
+
+auto tun-ffnw-{{tun.name}}
+iface tun-ffnw-{{tun.name}} inet static
+        address {{tun.v4_remote | ipaddr( tun.v4_remote.split('.')[3] | int + 1) | ipaddr('address') }}
+        netmask {{tun.v4_remote | ipaddr('netmask')}}
+        pre-up ip tunnel add $IFACE mode gre local {{ansible_default_ipv4.address}} remote {{tun.gre_target | ipaddr('address') }} ttl 255
+        post-up ip link set $IFACE mtu 1400
+        post-down ip tunnel del $IFACE
+        post-up ip rule add iif $IFACE lookup ffnet
+        pre-down ip rule del iif $IFACE lookup ffnet ||:
+iface tun-ffnw-{{tun.name}} inet6 static
+        address {{tun.v6_remote | ipaddr('2') | ipaddr('address') }}
+        netmask {{tun.v6_remote | ipaddr('prefix')}}
+        post-up ip -6 rule add iif $IFACE lookup ffnet
+        pre-down ip -6 rule del iif $IFACE lookup ffnet ||:
+{% endfor %}
+{% endif %}

+ 20 - 0
roles/gateways_gre_upstream/templates/lo.j2

@@ -0,0 +1,20 @@
+auto lo
+iface lo inet loopback
+{% if ffrl_tun is defined and ffrl_nat_ip is defined %}
+        up ip address add {{ ffrl_nat_ip }} dev lo
+        up ip rule add from {{ ffrl_nat_ip }} table ffnet
+        up ip rule add iif lo table ffnet suppress_prefixlength 0
+        up ip -6 rule add iif lo table ffnet suppress_prefixlength 0
+{% endif %}
+{% if ffnw_tun is defined %}
+        up ip address add {{ ffnw_nat_ip }} dev lo
+        up ip rule add from {{ ffnw_nat_ip }} table ffnet
+        up ip rule add iif lo table ffnet suppress_prefixlength 0
+        up ip -6 rule add iif lo table ffnet suppress_prefixlength 0
+{% endif %}
+{% if ffnw_tun is not defined and ffrl_tun is not defined %}
+        up ip address add 10.0.0.{{vm_id}} dev lo
+        up ip rule add from 10.0.0.{{vm_id}} table ffnet
+        up ip rule add iif lo table ffnet suppress_prefixlength 0
+        up ip -6 rule add iif lo table ffnet suppress_prefixlength 0
+{% endif %}

+ 3 - 0
roles/gateways_gretap/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: restart networking
+  shell: systemctl restart networking; if systemctl -q is-active isc-dhcp-server; then systemctl restart isc-dhcp-server; fi; if systemctl -q is-active kea-dhcp4.service; then systemctl restart kea-dhcp4.service; fi; if systemctl -q is-active tunneldigger; then systemctl restart tunneldigger; fi

+ 16 - 0
roles/gateways_gretap/tasks/main.yml

@@ -0,0 +1,16 @@
+---
+# Tasks for getap network interfaces
+
+# create file for gre interfaces
+- name: Create interfaces - inter_gre file
+  template: src="gretap.j2" dest="/etc/network/interfaces.d/30_gretap.cfg"
+  notify:
+    - restart networking
+  when: domaenenliste is defined
+
+#append line in interfaces file for reading additional config files
+- name: let read interfaces from interfaces
+  lineinfile: dest="/etc/network/interfaces" line="source /etc/network/interfaces.d/*"
+  notify:
+    - restart networking
+  when: domaenenliste is defined

+ 39 - 0
roles/gateways_gretap/templates/gretap.j2

@@ -0,0 +1,39 @@
+# This file is managed by ansible, don't make changes here - they will be overwritten.
+{% set indexer = [0] %}
+{% set hosts = [] %}
+{% for domaene in domaenenliste|dictsort %}
+{% for dummy in hosts %}
+{% if hosts.pop() %}
+{% endif %}
+{% endfor %}
+{% if hosts|length and hosts.pop() %}
+{% endif %}
+{% for host in groups['mapserver'] %}
+{% if hosts.append(host) %}
+{% endif %}
+{% endfor %}
+{% for host in groups['supernodes'] %}
+{% if ansible_ssh_host != hostvars[host].ansible_ssh_host and hostvars[host].domaenenliste is defined and domaene[0] in hostvars[host].domaenenliste and hosts.append(host) %}
+{% endif %}
+{% endfor %}
+{% for host in hosts %}
+{% if hostvars[host] is defined %}
+{% if indexer.append(indexer.pop() + 1) %}{% endif %}{# increment indexer by 1 #}
+
+# GRETAP Tunnel for domaene-{{domaene[0]}} to {{host}} ({{hostvars[host].ansible_ssh_host}})
+auto t{{domaene[0]}}-{{host}}
+iface t{{domaene[0]}}-{{host}} inet manual
+{% if build_tunnels_over_ipv6_if_available is defined and build_tunnels_over_ipv6_if_available == "yes" and ansible_default_ipv6.address is defined %}
+        pre-up ip link add $IFACE type ip6gretap local {{ansible_default_ipv6.address}} remote {{hostvars[host]['ansible_default_ipv6']['address']}} dev {{ansible_default_ipv6.interface}} key {{domaene[0]|int}}
+{% else %}
+        pre-up ip link add $IFACE type gretap local {{ansible_default_ipv4.address}} remote {{hostvars[host].ansible_ssh_host}} dev eth0 key {{domaene[0]|int}}
+{% endif %}
+        pre-up ip link set dev $IFACE address de:ad:be:ef:{{indexer[0]}}:{{vm_id}}
+        pre-up ip link set $IFACE up
+        post-up batctl -m bat{{domaene[0]}} if add $IFACE ||:
+        pre-down batctl -m bat{{domaene[0]}} if del $IFACE ||:
+        post-down ip link del $IFACE
+
+{% endif %}
+{% endfor %}
+{% endfor %}

+ 3 - 0
roles/gateways_kea_build/handlers/main.yml

@@ -0,0 +1,3 @@
+---
+- name: reload systemd
+  shell: systemctl daemon-reload 

+ 52 - 0
roles/gateways_kea_build/tasks/main.yml

@@ -0,0 +1,52 @@
+# This role builds ISC KEA for running PostgreSQL as Database engine
+---
+- name: Install required packages for building KEA
+  apt:
+    pkg: "{{ item }}"
+    update_cache: yes
+    cache_valid_time: 1800
+    state: present
+    install_recommends: no
+  with_items:
+    - git
+    - g++
+    - automake
+    - autoconf
+    - libtool
+    - pkg-config
+    - libboost-all-dev
+    - openssl
+    - libssl-dev
+    - ca-certificates
+    - liblog4cplus-dev
+    - postgresql-server-dev-all
+    - libpq-dev
+  when: domaenenliste is defined
+
+- name: Clone ISC KEA git repo and checkout branch v1_2_0
+  git: repo=https://github.com/isc-projects/kea.git dest=/srv/kea clone=yes update=no version=v1_2_0
+  when: domaenenliste is defined
+
+- name: Build ISC KEA
+  shell: "{{item}}"
+  args:
+    chdir: "/srv/kea"
+    creates: "/usr/local/sbin/kea-dhcp4"
+  with_items:
+    - "autoreconf --install"
+    - "./configure --with-dhcp-pgsql"
+    - "make -j $(grep -ic 'model name' /proc/cpuinfo)"
+    - "make install"
+    - "ldconfig"
+  when: domaenenliste is defined
+
+- name: Depoly systemd files
+  template: src="{{item}}" dest="/lib/systemd/system/{{item[:-3]}}"
+  with_items:
+    - kea-dhcp4.service.j2
+    - kea-dhcp6.service.j2
+    - kea-dhcp-ddns.service.j2
+  notify:
+    - reload systemd
+  when: domaenenliste is defined
+

+ 14 - 0
roles/gateways_kea_build/templates/kea-dhcp-ddns.service.j2

@@ -0,0 +1,14 @@
+[Unit]
+Description=Kea DHCP-DDNS Server
+Documentation=man:kea-dhcp-ddns(8)
+Wants=network-online.target{% if kea.database.type == "postgresql" %} postgresql.service{% endif %}
+
+After=network-online.target time-sync.target{% if kea.database.type == "postgresql" %} postgresql.service{% endif %}
+
+
+[Service]
+ExecStart=/usr/local/sbin/kea-dhcp-ddns -c /etc/kea/kea.conf
+ExecReload=/usr/local/sbin/keactrl reload -s dhcp_ddns
+
+[Install]
+WantedBy=multi-user.target

+ 14 - 0
roles/gateways_kea_build/templates/kea-dhcp4.service.j2

@@ -0,0 +1,14 @@
+[Unit]
+Description=Kea DHCPv4 Server
+Documentation=man:kea-dhcp4(8)
+Wants=network-online.target{% if kea.database.type == "postgresql" %} postgresql.service{% endif %}
+
+After=network-online.target time-sync.target{% if kea.database.type == "postgresql" %} postgresql.service{% endif %}
+
+
+[Service]
+ExecStart=/usr/local/sbin/kea-dhcp4 -c /etc/kea/kea.conf
+ExecReload=/usr/local/sbin/keactrl reload -s dhcp4
+
+[Install]
+WantedBy=multi-user.target

+ 14 - 0
roles/gateways_kea_build/templates/kea-dhcp6.service.j2

@@ -0,0 +1,14 @@
+[Unit]
+Description=Kea DHCPv6 Server
+Documentation=man:kea-dhcp6(8)
+Wants=network-online.target{% if kea.database.type == "postgresql" %} postgresql.service{% endif %}
+
+After=network-online.target time-sync.target{% if kea.database.type == "postgresql" %} postgresql.service{% endif %}
+
+
+[Service]
+ExecStart=/usr/local/sbin/kea-dhcp6 -c /etc/kea/kea.conf
+ExecReload=/usr/local/sbin/keactrl reload -s dhcp6
+
+[Install]
+WantedBy=multi-user.target

+ 2 - 0
roles/gateways_kea_configure/handlers/main.yml

@@ -0,0 +1,2 @@
+- name: reload-or-restart kea-dhcp4.service
+  shell: systemctl reload-or-restart kea-dhcp4.service

+ 48 - 0
roles/gateways_kea_configure/tasks/main.yml

@@ -0,0 +1,48 @@
+# Configure ISC KEA
+---
+
+- name: check whether isc-dhcp-server.service is running
+  shell: "systemctl status isc-dhcp-server.service"
+  register: _isc_dhcp_status
+  failed_when:  False
+  changed_when: False
+  check_mode: no
+  when: domaenenliste is defined
+
+- name: check whether isc-dhcp-server.service is enabled
+  shell: "systemctl is-enabled isc-dhcp-server.service"
+  register: _isc_dhcp_enabled
+  failed_when:  False
+  changed_when: False
+  check_mode: no
+  when: domaenenliste is defined
+
+- name: stop isc-dhcp
+  service: name=isc-dhcp-server state=stopped
+  when:
+    - domaenenliste is defined
+    - _isc_dhcp_status.rc == 0
+
+- name: disable isc-dhcp
+  service: name=isc-dhcp-server enabled=no
+  when:
+    - domaenenliste is defined
+    - _isc_dhcp_enabled.rc == 0
+
+- name: enable kea-dhcp4.service
+  service: name=kea-dhcp4.service enabled=yes
+  when: domaenenliste is defined
+
+- name: Create /etc/kea directory
+  file: path=/etc/kea state=directory mode=0755
+  when: domaenenliste is defined
+
+- name: Create /var/kea directory
+  file: path=/var/kea state=directory mode=0755
+  when: domaenenliste is defined
+
+- name: create /etc/kea/kea.conf
+  template: src=keav4.conf.j2 dest=/etc/kea/kea.conf
+  notify:
+    - reload-or-restart kea-dhcp4.service
+  when: domaenenliste is defined

+ 0 - 0
roles/gateways_kea_configure/templates/keav4.conf.j2


Some files were not shown because too many files changed in this diff