summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2017-04-01 04:53:28 +0200
committerSuren A. Chilingaryan <csa@suren.me>2017-04-01 04:53:28 +0200
commite7ed329bd81c2273c03e94c93c9ce9c1d01cdc86 (patch)
tree444778102e4f73b83ef9462235b7f614b004b264
downloadands-e7ed329bd81c2273c03e94c93c9ce9c1d01cdc86.tar.gz
ands-e7ed329bd81c2273c03e94c93c9ce9c1d01cdc86.tar.bz2
ands-e7ed329bd81c2273c03e94c93c9ce9c1d01cdc86.tar.xz
ands-e7ed329bd81c2273c03e94c93c9ce9c1d01cdc86.zip
Initial import
-rw-r--r--.gitignore3
-rw-r--r--group_vars/OSEv3.yml65
-rw-r--r--group_vars/all.yml3
-rw-r--r--group_vars/ands.yml5
-rw-r--r--group_vars/baremetal.yml3
-rw-r--r--group_vars/production.yml7
-rw-r--r--group_vars/staging.yml26
-rw-r--r--group_vars/testing.yml20
-rw-r--r--group_vars/virtual.yml10
-rw-r--r--inventories/staging.erb44
-rw-r--r--inventories/testing.erb47
-rw-r--r--opts.sh117
-rw-r--r--playbooks/ands-prepare.yml46
-rw-r--r--playbooks/ands-setup-vm.yml5
l---------playbooks/group_vars1
-rw-r--r--playbooks/heketi-destroy.yml5
l---------playbooks/host_vars1
-rw-r--r--playbooks/local.yml22
-rw-r--r--playbooks/maintain.yml11
-rw-r--r--playbooks/openshift-add-nodes.yml7
-rw-r--r--playbooks/openshift-install.yml22
l---------playbooks/openshift-redeploy-certificates.yml1
-rw-r--r--playbooks/openshift-setup-projects.yml28
-rw-r--r--playbooks/openshift-setup-storage.yml37
-rw-r--r--playbooks/openshift-setup-users.yml24
-rw-r--r--playbooks/openshift-setup-vpn.yml13
-rw-r--r--playbooks/openshift-setup.yml34
l---------playbooks/projects1
l---------playbooks/roles1
-rw-r--r--playbooks/tmp_role.yml6
l---------playbooks/users1
-rw-r--r--roles/ands_facts/README7
-rw-r--r--roles/ands_facts/defaults/main.yml11
-rw-r--r--roles/ands_facts/tasks/detect_data_path.yml10
-rw-r--r--roles/ands_facts/tasks/main.yml35
l---------roles/ands_facts/vars1
-rw-r--r--roles/ands_kaas/defaults/main.yml11
-rw-r--r--roles/ands_kaas/tasks/file.yml9
-rw-r--r--roles/ands_kaas/tasks/keys.yml37
-rw-r--r--roles/ands_kaas/tasks/main.yml12
-rw-r--r--roles/ands_kaas/tasks/oc.yml10
-rw-r--r--roles/ands_kaas/tasks/ocitem.yml13
-rw-r--r--roles/ands_kaas/tasks/ocscript.yml8
-rw-r--r--roles/ands_kaas/tasks/project.yml76
-rw-r--r--roles/ands_kaas/tasks/sync.yml8
-rw-r--r--roles/ands_kaas/tasks/sync_all.yml13
-rw-r--r--roles/ands_kaas/tasks/template.yml17
-rw-r--r--roles/ands_kaas/tasks/templates.yml20
-rw-r--r--roles/ands_kaas/tasks/volume.yml11
-rw-r--r--roles/ands_kaas/templates/0-gfs-volumes.yml.j238
-rw-r--r--roles/ands_kaas/templates/6-kaas-pods.yml.j2173
-rw-r--r--roles/ands_openshift/defaults/main.yml11
-rw-r--r--roles/ands_openshift/files/gfs-svc.yml16
-rw-r--r--roles/ands_openshift/files/heketi/heketi.json23
-rw-r--r--roles/ands_openshift/handlers/main.yml4
-rw-r--r--roles/ands_openshift/tasks/heketi.yml13
-rw-r--r--roles/ands_openshift/tasks/heketi_perms.yml9
-rw-r--r--roles/ands_openshift/tasks/heketi_resources.yml74
-rw-r--r--roles/ands_openshift/tasks/hostnames.yml15
-rw-r--r--roles/ands_openshift/tasks/main.yml6
-rw-r--r--roles/ands_openshift/tasks/ssh.yml21
-rw-r--r--roles/ands_openshift/tasks/ssh_keygen.yml12
-rw-r--r--roles/ands_openshift/tasks/storage.yml4
-rw-r--r--roles/ands_openshift/tasks/storage_resources.yml33
-rw-r--r--roles/ands_openshift/tasks/users.yml8
-rw-r--r--roles/ands_openshift/tasks/users_resources.yml40
-rw-r--r--roles/ands_openshift/templates/gfs-ep.yml.j220
-rw-r--r--roles/ands_openshift/templates/heketi/heketi-sc.yml.j221
-rw-r--r--roles/ands_openshift/templates/heketi/heketi_template.json.j2232
-rw-r--r--roles/ands_openshift/templates/heketi/topology.json.j228
-rw-r--r--roles/ands_storage/README25
-rw-r--r--roles/ands_storage/defaults/main.yml13
-rw-r--r--roles/ands_storage/handlers/main.yml5
-rw-r--r--roles/ands_storage/tasks/detect_device.yml10
-rw-r--r--roles/ands_storage/tasks/main.yml45
-rw-r--r--roles/ands_vagrant_vm/README19
-rw-r--r--roles/ands_vagrant_vm/defaults/main.yml8
-rw-r--r--roles/ands_vagrant_vm/files/rebuild.sh9
-rwxr-xr-xroles/ands_vagrant_vm/files/run.sh12
-rw-r--r--roles/ands_vagrant_vm/handlers/main.yml2
-rw-r--r--roles/ands_vagrant_vm/tasks/main.yml20
-rw-r--r--roles/ands_vagrant_vm/templates/Vagrantfile.j251
-rw-r--r--roles/common/README11
-rw-r--r--roles/common/tasks/main.yml23
-rw-r--r--roles/docker/README18
-rw-r--r--roles/docker/defaults/main.yml3
-rw-r--r--roles/docker/tasks/main.yml32
-rw-r--r--roles/docker/tasks/storage.yml41
-rw-r--r--roles/glusterfs/README26
-rw-r--r--roles/glusterfs/defaults/main.yml11
l---------roles/glusterfs/tasks/cfg/vols2.yml1
-rw-r--r--roles/glusterfs/tasks/cfg/vols3.yml13
-rw-r--r--roles/glusterfs/tasks/common.yml16
-rw-r--r--roles/glusterfs/tasks/create_domain.yml8
-rw-r--r--roles/glusterfs/tasks/create_volume.yml4
-rw-r--r--roles/glusterfs/tasks/main.yml13
-rw-r--r--roles/glusterfs/tasks/mount_domain.yml12
-rw-r--r--roles/glusterfs/tasks/mount_volume.yml8
-rw-r--r--roles/glusterfs/tasks/server.yml31
l---------roles/glusterfs/tasks/tmp/vols2.yml1
-rw-r--r--roles/glusterfs/tasks/tmp/vols3.yml11
-rw-r--r--roles/glusterfs/tasks/volumes.yml15
-rw-r--r--roles/keepalived/.gitignore2
-rw-r--r--roles/keepalived/README13
-rw-r--r--roles/keepalived/defaults/main.yml12
-rw-r--r--roles/keepalived/handlers/main.yml3
-rw-r--r--roles/keepalived/tasks/main.yml22
-rw-r--r--roles/keepalived/templates/keepalived.conf.j236
l---------roles/openshift_certificate_expiry1
-rw-r--r--roles/openshift_resource/defaults/main.yml1
-rw-r--r--roles/openshift_resource/tasks/command.yml17
-rw-r--r--roles/openshift_resource/tasks/lookup.yml6
-rw-r--r--roles/openshift_resource/tasks/main.yml22
-rw-r--r--roles/openshift_resource/tasks/resource.yml20
-rw-r--r--roles/openshift_resource/tasks/template.yml25
-rw-r--r--roles/openvpn/README12
-rw-r--r--roles/openvpn/defaults/main.yml15
-rw-r--r--roles/openvpn/files/ca/ca.crt22
-rw-r--r--roles/openvpn/files/ca/ca.key50
-rw-r--r--roles/openvpn/files/keys/dh1024.pem18
-rw-r--r--roles/openvpn/files/openvpn_logrotate.conf9
-rw-r--r--roles/openvpn/handlers/main.yml12
-rw-r--r--roles/openvpn/tasks/config.yml28
-rw-r--r--roles/openvpn/tasks/keys.yml13
-rw-r--r--roles/openvpn/tasks/main.yml62
-rw-r--r--roles/openvpn/templates/katrin/ccd.j22
-rw-r--r--roles/openvpn/templates/katrin/ccd/ikkatrinadei.ka.fzk.de.j23
-rw-r--r--roles/openvpn/templates/katrin/ccd/ipechilinga4.ka.fzk.de.j21
-rw-r--r--roles/openvpn/templates/katrin/openvpn_client.j224
-rw-r--r--roles/openvpn/templates/katrin/openvpn_server.j226
-rwxr-xr-xsetup.sh60
-rw-r--r--setup/configs/labels.yml6
-rw-r--r--setup/configs/openshift.yml12
-rw-r--r--setup/configs/secrets.yml10
-rw-r--r--setup/configs/volumes.yml37
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.d/README9
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.d/autoindex.conf94
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.d/ssl.conf217
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.d/userdir.conf36
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.d/welcome.conf18
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-base.conf67
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-dav.conf3
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-lua.conf1
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-mpm.conf19
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-optional.conf20
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-proxy.conf16
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-ssl.conf1
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-systemd.conf2
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/01-cgi.conf14
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf/httpd.conf353
-rw-r--r--setup/projects/katrin/files/etc/apache2-kaas/conf/magic385
l---------setup/projects/katrin/files/etc/apache2-kaas/logs1
l---------setup/projects/katrin/files/etc/apache2-kaas/modules1
l---------setup/projects/katrin/files/etc/apache2-kaas/run1
-rw-r--r--setup/projects/katrin/files/www/kaas/index.html1
-rw-r--r--setup/projects/katrin/keys/kaas.crt22
-rw-r--r--setup/projects/katrin/keys/kaas.key90
-rw-r--r--setup/projects/katrin/templates/00-katrin-restricted.yml.j2.excl43
-rw-r--r--setup/projects/katrin/templates/katrin.yml.j2.bk135
-rw-r--r--setup/projects/katrin/vars/globals.yml2
-rw-r--r--setup/projects/katrin/vars/katrin.yml7
-rw-r--r--setup/projects/katrin/vars/pods.yml22
-rw-r--r--setup/users/htpasswd3
l---------setup/users/users.yml1
-rw-r--r--vm/vagrant-router/Vagrantfile35
-rw-r--r--vm/vagrant-router/inventory.erb2
-rwxr-xr-xvm/vagrant-router/rebuild.sh5
-rw-r--r--vm/vagrant-router/router.yml16
168 files changed, 4487 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3ee1163
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.vault-pass
+.vagrant
+*.retry
diff --git a/group_vars/OSEv3.yml b/group_vars/OSEv3.yml
new file mode 100644
index 0000000..5e19b7d
--- /dev/null
+++ b/group_vars/OSEv3.yml
@@ -0,0 +1,65 @@
+### Deployment Type
+deployment_type: "origin"
+#openshift_release: "v1.4"
+#openshift_image_tag: "v1.4.1"
+openshift_release: "v1.5"
+#openshift_image_tag: "v1.5.0"
+openshift_image_tag: "v1.5.0-rc.0"
+openshift_hosted_metrics_deployer_version: "v1.5.0-rc.0"
+
+
+containerized: true
+openshift_master_cluster_method: "native"
+
+### Configuration
+openshift_install_examples: true
+osn_storage_plugin_deps: ['ceph', 'glusterfs']
+openshift_hosted_metrics_deploy: true
+#openshift_metrics_project: openshift-infra
+ppenshift_hosted_metrics_storage_kind: dynamic
+# seems ignored, so lets set to default
+#openshift_metrics_hawkular_hostname: "hawkular-metrics.{{ ands_openshift_subdomain }}"
+
+
+openshift_master_pod_eviction_timeout: 30s
+
+# Verify that it does not cause problems
+os_firewall_use_firewalld: true
+
+
+# Alternative metrics & cockpit, this is purely documented so we keep it out
+#openshift_use_manageiq: true
+osm_use_cockpit: true
+osm_cockpit_plugins: ['cockpit-kubernetes']
+
+#Recommended to avoid: No package matching 'origin-docker-excluder-1.5.0*' found available
+enable_excluders: false
+enable_docker_excluder: false
+
+# Required for IPFailover
+openshift_clock_enabled: true
+
+### Authentication
+openshift_master_identity_providers: [{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}]
+openshift_master_htpasswd_users: {'pdv': '$apr1$ACvj6uUa$Nm1Vq8hZq3RzTtaYpAHv01', 'csa': '$apr1$IqEwdnzy$UAdd8ZSFnXommBbj29w3c0'}
+
+# Network & DNS configuration
+openshift_master_cluster_hostname: "{{ ands_openshift_lb }}"
+#openshift_master_cluster_public_hostname: "{{ ands_openshift_lb }}"
+openshift_master_default_subdomain: "{{ ands_openshift_subdomain }}"
+openshift_master_ingress_ip_network_cidr: "{{ ands_openshift_ingress_network }}"
+
+
+# Node configuration
+openshift_schedulable: true
+
+openshift_ip: "{{ ands_openshift_network | ipaddr(ands_host_id) | ipaddr('address') }}"
+openshift_hostname: "{{ ansible_hostname }}"
+openshift_public_hostname: "{{ ansible_hostname }}.{{ ands_cluster_domain }}"
+
+#openshift_public_ip: "{{ ands_openshift_network | ipaddr(ands_host_id) | ipaddr('address') }}"
+#openshift_hostname: "{{ ands_openshift_network | ipaddr(ands_host_id) | ipaddr('address') }}"
+#openshift_public_hostname: "{{ ands_openshift_public_network | ipaddr(ands_host_id) | ipaddr('address') }}"
+
+openshift_node_labels: "{{ ands_openshift_labels }}"
+
diff --git a/group_vars/all.yml b/group_vars/all.yml
new file mode 100644
index 0000000..f29206f
--- /dev/null
+++ b/group_vars/all.yml
@@ -0,0 +1,3 @@
+ansible_ssh_user: root
+glusterfs_version: 39
+
diff --git a/group_vars/ands.yml b/group_vars/ands.yml
new file mode 100644
index 0000000..58570c6
--- /dev/null
+++ b/group_vars/ands.yml
@@ -0,0 +1,5 @@
+# This should be here, the variables from the role are not propogated to hostvars
+
+#ands_master_id: "{{ ('masters' in group_names) | ternary(groups.masters.index(('masters' in group_names) | ternary(inventory_hostname, groups.masters[0])), -1) }}"
+ands_storage_hostname: "{{ ands_storage_network | default(false) | ternary(ands_storage_network | default('') | ipaddr(ands_host_id) | ipaddr('address'), ansible_fqdn) }}"
+
diff --git a/group_vars/baremetal.yml b/group_vars/baremetal.yml
new file mode 100644
index 0000000..032e53f
--- /dev/null
+++ b/group_vars/baremetal.yml
@@ -0,0 +1,3 @@
+glusterfs_transport: rdma
+
+ands_host_id: "{{ ansible_hostname | regex_replace('^ipekatrin(\\d+)(\\.|$)', '\\1') }}"
diff --git a/group_vars/production.yml b/group_vars/production.yml
new file mode 100644
index 0000000..24b189f
--- /dev/null
+++ b/group_vars/production.yml
@@ -0,0 +1,7 @@
+ands_storage_network: 192.168.12.0/24
+
+ands_openshift_lb: kaas.kit.edu
+ands_openshift_subdomain: kaas.kit.edu
+ands_openshift_network: 192.168.26.0/24
+ands_openshift_public_network: 192.168.26.0/24
+ands_openshift_ingress_network: 192.168.16.0/22
diff --git a/group_vars/staging.yml b/group_vars/staging.yml
new file mode 100644
index 0000000..7eed847
--- /dev/null
+++ b/group_vars/staging.yml
@@ -0,0 +1,26 @@
+ands_storage_network: 192.168.212.0/24
+
+ands_cluster_domain: ipe.kit.edu
+#ands_openshift_lb: openshift.ipe.kit.edu
+#ands_openshift_subdomain: openshift.ipe.kit.edu
+ands_openshift_lb: openshift.suren.me
+ands_openshift_subdomain: openshift.suren.me
+ands_openshift_network: 192.168.212.0/24
+ands_openshift_public_network: 192.168.226.0/24
+ands_openshift_ingress_network: 192.168.216.0/24
+
+ands_ipfailover_interface: eth1
+ands_ipfailover_vips: [141.52.64.28/24]
+
+katrin_openvpn_subnet_bits: 24
+katrin_openvpn_subnet_offset: 221
+katrin_openvpn_network: "192.168.0.0/16"
+
+vagrant_hostname_template: ipeshift
+vagrant_cpu_cores: 4
+vagrant_mem_size: 16
+vagrant_disk_size: 240
+
+
+#ands_disable_dynamic_provisioning: true
+#ands_provision_without_dns: true
diff --git a/group_vars/testing.yml b/group_vars/testing.yml
new file mode 100644
index 0000000..ac7ee89
--- /dev/null
+++ b/group_vars/testing.yml
@@ -0,0 +1,20 @@
+ands_storage_network: 192.168.12.0/24
+
+ands_cluster_domain: ipe.kit.edu
+ands_openshift_lb: katrin.suren.me
+#ands_openshift_subdomain: katrin.suren.me
+ands_openshift_subdomain: apps.suren.me
+#ands_openshift_network: 192.168.26.0/24
+ands_openshift_network: 192.168.12.0/24
+ands_openshift_public_network: 192.168.26.0/24
+ands_openshift_ingress_network: 192.168.16.0/24
+
+ands_ipfailover_interface: eth1
+ands_ipfailover_vips: [141.52.64.15/24, 141.52.64.17/24]
+
+katrin_openvpn_subnet_bits: 24
+katrin_openvpn_subnet_offset: 111
+katrin_openvpn_network: "192.168.0.0/16"
+
+vagrant_hostname_template: ipekatrin
+
diff --git a/group_vars/virtual.yml b/group_vars/virtual.yml
new file mode 100644
index 0000000..f76bafc
--- /dev/null
+++ b/group_vars/virtual.yml
@@ -0,0 +1,10 @@
+glusterfs_transport: tcp
+
+ands_data_device: "/dev/sdb"
+ands_data_volume_size: "20G"
+ands_heketi_volume_size: "20G"
+
+docker_storage_device: "/dev/sdb"
+docker_storage_vg: "ands"
+
+ands_host_id: "{{ ansible_hostname | regex_replace('^[\\w\\d]*\\w(\\d+)(\\.|$)', '\\1') }}"
diff --git a/inventories/staging.erb b/inventories/staging.erb
new file mode 100644
index 0000000..5779304
--- /dev/null
+++ b/inventories/staging.erb
@@ -0,0 +1,44 @@
+[masters]
+192.168.226.[1:2]
+
+[simple_storage_nodes]
+192.168.226.[3:3]
+
+[simple_nodes]
+
+[staging:children]
+nodes
+vagrant
+
+[virtual:children]
+nodes
+
+[OSEv3:children]
+masters
+nodes
+etcd
+
+[etcd:children]
+masters
+simple_storage_nodes
+
+[storage_nodes:children]
+masters
+simple_storage_nodes
+
+[nodes:children]
+masters
+simple_storage_nodes
+simple_nodes
+
+[ands_servers:children]
+nodes
+
+[ands_storage_servers:children]
+storage_nodes
+
+[ands:children]
+ands_servers
+
+[vagrant]
+ipepdvcompute3.ipe.kit.edu vagrant_project=staging
diff --git a/inventories/testing.erb b/inventories/testing.erb
new file mode 100644
index 0000000..0f6e2c5
--- /dev/null
+++ b/inventories/testing.erb
@@ -0,0 +1,47 @@
+[masters]
+ipekatrin[1:2].katrin.kit.edu
+
+[simple_storage_nodes]
+ipekatrin[3:3].katrin.kit.edu
+#ipetest.katrin.kit.edu ands_host_id=5
+
+[simple_nodes]
+#ipekatrin[3:3].katrin.kit.edu
+#strnage_name.katrin.kit.edu ands_host_id=1
+
+[testing:children]
+nodes
+vagrant
+
+[virtual:children]
+nodes
+
+[OSEv3:children]
+masters
+nodes
+etcd
+
+[etcd:children]
+masters
+simple_storage_nodes
+
+[storage_nodes:children]
+masters
+simple_storage_nodes
+
+[nodes:children]
+masters
+simple_storage_nodes
+simple_nodes
+
+[ands_servers:children]
+nodes
+
+[ands_storage_servers:children]
+storage_nodes
+
+[ands:children]
+ands_servers
+
+[vagrant]
+ipepdvcompute3.ipe.kit.edu vagrant_project=testing
diff --git a/opts.sh b/opts.sh
new file mode 100644
index 0000000..020fb44
--- /dev/null
+++ b/opts.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+inventory="inventories/testing.erb"
+group="nodes"
+
+usage() {
+ cat << END
+Usage: $0 [-i inventory] [-g group] <action> [extra-args-to-ansible]
+
+Parameters:
+ inventory - specifies name of inventory to use (testing, staging, production)
+ group - specifies node group to use if role is considered in action
+
+Actions:
+ -h - show help and exit
+
+ Initial system installation
+ all - full install, all the following steps in sequence:
+ local - configure local ssh client
+ prepare - perform all required pre-configuration before setting openshift
+ openshift - setup OpenShift cluster
+ configure - configures OpenShift cluster (Storage, Users, OpenVPN tunnels)
+ projects - installs configuration files and OpenShift resources for KaaS and other configured projects
+
+ Scaling the cluster
+ nodes - complete action: prepares the nodes, scales up the cluster, and reconfigures storage
+ prepare - prepares the new nodes
+ openshift-nodes - scales OpenShift cluster (master scallability is not checked)
+ configure - Configures new nodes (Storage, Users, OpenVPN tunnels)
+
+ Configuration of new resources, etc.
+ users - configure user roles & passwords
+ storage - reconfigure Gluster and OpenShift volumes
+ projects - reconfigures OpenShift resources if necessary
+ vpn - reconfigure VPN tunnels
+ certs - re-generate OpenShift x509 certificates
+ check - check current setup and report if any maintenace should be peformed
+ setup <type> - executes specific configuration task from ands-openshift
+ Tasks: hostnames, users, ssh, storage, heketi
+
+ Custom actions
+ playbook.yml - execute the specified playbook
+ role - generates temporary playbook and executes the role
+
+END
+ echo
+ [ -n "$1" ] && echo "Error: $1"
+ exit
+}
+
+apply() {
+ export ANSIBLE_HOST_KEY_CHECKING=False
+
+ [ -n "$1" ] || usage "No action specified"
+
+ action=$1
+ shift 1
+
+ if [ -f "$action" ]; then
+ playbook=$action
+ elif [ -d "roles/$action" ]; then
+ role=$action
+ else
+ usage "Role '$action' is not existing"
+ fi
+
+ clean=""
+ if [ -z "$playbook" ]; then
+ echo "Executing a specific role '$role' on '$group'"
+ playbook="playbooks/tmp_role.yml"
+ clean="playbooks/tmp_role.*"
+
+ cat <<END > playbooks/tmp_role.yml
+- name: Common setup procedures
+ hosts: $group
+ remote_user: root
+ roles:
+ - ands_facts
+ - $role
+END
+ fi
+
+ ansible-playbook --vault-password-file .vault-pass -i $inventory $playbook $@
+
+ if [ -n "$clean" ]; then
+ rm -rf "$clean"
+ fi
+
+ return $?
+}
+
+while getopts ":i:g:h" o; do
+ case "${o}" in
+ h)
+ usage
+ ;;
+ i)
+ inventory=${OPTARG}
+ [ -f $inventory ] || [ -f inventories/${inventory}.erb ] || usage "Specified inventory '$inventory' is not found"
+ [ -f $inventory ] || inventory=inventories/${inventory}.erb
+ ;;
+ g)
+ group=${OPTARG}
+ ;;
+ \?)
+ usage "Invalid option: -$OPTARG"
+ ;;
+ :)
+ usage "Option -$OPTARG requires an argument"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+
+shift $((OPTIND-1))
diff --git a/playbooks/ands-prepare.yml b/playbooks/ands-prepare.yml
new file mode 100644
index 0000000..1b4fc2a
--- /dev/null
+++ b/playbooks/ands-prepare.yml
@@ -0,0 +1,46 @@
+- name: Common setup procedures
+ hosts: ands
+ roles:
+ - role: ands_facts
+ - role: common
+
+- name: Keepalived service
+ hosts: masters
+ roles:
+ - role: keepalived
+ vars:
+ keepalived_vips: "{{ ands_ipfailover_vips | default([]) }}"
+ keepalived_iface: "{{ ands_ipfailover_interface | default('eth0') }}"
+ keepalived_password: "{{ ands_secrets.keepalived }}"
+
+#OpenVPN started before Origin-node causes problems
+#- name: OpenVPN service
+# hosts: nodes
+# roles:
+# - role: openvpn
+# vars:
+# openvpn_config: "katrin"
+# openvpn_lb: "{{ ands_openshift_lb }}"
+# openvpn_servers: "masters"
+
+- name: Configures Ands storage
+ hosts: ands_storage_servers
+ roles:
+ - role: ands_storage
+
+- name: Docker setup
+ hosts: nodes
+ roles:
+ - role: docker
+ vars:
+ docker_exclude_vgs: "{{ [ ands_data_vg ] }}"
+
+- name: Configure GlusterFS cluster
+ hosts: ands_servers
+ roles:
+ - role: glusterfs
+ vars:
+ glusterfs_network: "{{ ands_storage_network }}"
+ glusterfs_servers: "{{ ands_storage_servers }}"
+ glusterfs_bricks_path: "{{ ands_data_path }}/glusterfs"
+ glusterfs_domains: "{{ ands_storage_domains }}"
diff --git a/playbooks/ands-setup-vm.yml b/playbooks/ands-setup-vm.yml
new file mode 100644
index 0000000..d97916d
--- /dev/null
+++ b/playbooks/ands-setup-vm.yml
@@ -0,0 +1,5 @@
+- name: Common setup procedures
+ hosts: vagrant
+ roles:
+ - role: ands_vagrant_vm
+
diff --git a/playbooks/group_vars b/playbooks/group_vars
new file mode 120000
index 0000000..de38180
--- /dev/null
+++ b/playbooks/group_vars
@@ -0,0 +1 @@
+../group_vars/ \ No newline at end of file
diff --git a/playbooks/heketi-destroy.yml b/playbooks/heketi-destroy.yml
new file mode 100644
index 0000000..b29679b
--- /dev/null
+++ b/playbooks/heketi-destroy.yml
@@ -0,0 +1,5 @@
+---
+- hosts: storage_nodes
+ tasks:
+ - name: Destroy Heketi volumes
+ shell: "yes | pvremove /dev/{{ansible_lvm.lvs.ands_heketi.vg}}/katrin_heketi --force --force"
diff --git a/playbooks/host_vars b/playbooks/host_vars
new file mode 120000
index 0000000..f1e217d
--- /dev/null
+++ b/playbooks/host_vars
@@ -0,0 +1 @@
+../host_vars/ \ No newline at end of file
diff --git a/playbooks/local.yml b/playbooks/local.yml
new file mode 100644
index 0000000..9e6ca38
--- /dev/null
+++ b/playbooks/local.yml
@@ -0,0 +1,22 @@
+- name: Store known hosts of 'all' the hosts in the inventory file
+ hosts: localhost
+ connection: local
+
+ vars:
+ ssh_known_hosts_command: "ssh-keyscan -T 10"
+ ssh_known_hosts_file: "{{ lookup('env','HOME') + '/.ssh/known_hosts' }}"
+ ssh_known_hosts: "{{ groups['all'] }}"
+
+ tasks:
+ - name: For each host, scan for its ssh public key
+ shell: "ssh-keyscan {{ item }},`dig +short {{ item }}`"
+ with_items: "{{ ssh_known_hosts }}"
+ register: ssh_known_host_results
+ ignore_errors: yes
+
+ - name: Add/update the public key in the '{{ ssh_known_hosts_file }}'
+ known_hosts:
+ name: "{{ item.item }}"
+ key: "{{ item.stdout }}"
+ path: "{{ ssh_known_hosts_file }}"
+ with_items: "{{ ssh_known_host_results.results }}"
diff --git a/playbooks/maintain.yml b/playbooks/maintain.yml
new file mode 100644
index 0000000..3167252
--- /dev/null
+++ b/playbooks/maintain.yml
@@ -0,0 +1,11 @@
+- name: Check cert expirys
+ hosts: nodes:masters:etcd
+ become: yes
+ gather_facts: no
+ vars:
+ openshift_certificate_expiry_save_json_results: yes
+ openshift_certificate_expiry_generate_html_report: yes
+ openshift_certificate_expiry_html_report_path: ./report
+ openshift_certificate_expiry_show_all: yes
+ roles:
+ - role: openshift_certificate_expiry
diff --git a/playbooks/openshift-add-nodes.yml b/playbooks/openshift-add-nodes.yml
new file mode 100644
index 0000000..ccb5d1c
--- /dev/null
+++ b/playbooks/openshift-add-nodes.yml
@@ -0,0 +1,7 @@
+- name: Configure cluster hosts names
+ hosts: nodes
+ roles:
+ - { role: ands_facts }
+ - { role: ands_openshift, subrole: hostnames }
+
+- include: ../../openshift-ansible/playbooks/byo/openshift-node/scaleup.yml
diff --git a/playbooks/openshift-install.yml b/playbooks/openshift-install.yml
new file mode 100644
index 0000000..c54f4ee
--- /dev/null
+++ b/playbooks/openshift-install.yml
@@ -0,0 +1,22 @@
+- name: Configure cluster hosts names
+ hosts: nodes
+ roles:
+ - { role: ands_facts }
+ - { role: ands_openshift, subrole: hostnames }
+
+- name: Temporary provision /etc/hosts with Masters IP.
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" line="{{ ands_openshift_network | ipaddr(node_id) | ipaddr('address') }} {{ ands_openshift_lb }}" regexp=".*{{ ands_openshift_lb }}$" state="present"
+ when: (ands_provision_without_dns | default(false))
+ vars:
+ node_id: "{{ hostvars[groups['masters'][0]]['ands_host_id'] }}"
+
+
+- include: ../../openshift-ansible/playbooks/byo/config.yml
+
+- name: Remove temporary entries in /etc/hosts
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" regexp=".*{{ ands_openshift_lb }}$" state="absent"
+ when: (ands_provision_without_dns | default(false))
diff --git a/playbooks/openshift-redeploy-certificates.yml b/playbooks/openshift-redeploy-certificates.yml
new file mode 120000
index 0000000..2ac0c05
--- /dev/null
+++ b/playbooks/openshift-redeploy-certificates.yml
@@ -0,0 +1 @@
+../../openshift-ansible/playbooks/byo/openshift-cluster/redeploy-certificates.yml \ No newline at end of file
diff --git a/playbooks/openshift-setup-projects.yml b/playbooks/openshift-setup-projects.yml
new file mode 100644
index 0000000..46d6767
--- /dev/null
+++ b/playbooks/openshift-setup-projects.yml
@@ -0,0 +1,28 @@
+- name: Configure users & user projects
+ hosts: masters
+ roles:
+ - { role: ands_facts }
+
+- name: Temporary provision /etc/hosts with Masters IP.
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" line="{{ ands_openshift_network | ipaddr(node_id) | ipaddr('address') }} {{ ands_openshift_lb }}" regexp=".*{{ ands_openshift_lb }}$" state="present"
+ when: (ands_provision_without_dns | default(false))
+ vars:
+ node_id: "{{ hostvars[groups['masters'][0]]['ands_host_id'] }}"
+
+- name: Configure users & user projects
+ hosts: masters
+ roles:
+ - { role: ands_openshift, subrole: users }
+ - { role: ands_kaas }
+ vars:
+ kaas_projects: "{{ ands_openshift_projects.keys() }}"
+ kaas_openshift_volumes: "{{ ands_openshift_volumes }}"
+
+
+- name: Remove temporary entries in /etc/hosts
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" regexp=".*{{ ands_openshift_lb }}$" state="absent"
+ when: (ands_provision_without_dns | default(false))
diff --git a/playbooks/openshift-setup-storage.yml b/playbooks/openshift-setup-storage.yml
new file mode 100644
index 0000000..387b775
--- /dev/null
+++ b/playbooks/openshift-setup-storage.yml
@@ -0,0 +1,37 @@
+---
+- name: Configure GlusterFS storage
+ hosts: nodes
+ roles:
+ - { role: ands_facts }
+
+- name: Configure GlusterFS storage
+ hosts: nodes
+ roles:
+ - { role: glusterfs, subrole: volumes }
+ vars:
+ glusterfs_network: "{{ ands_storage_network }}"
+ glusterfs_servers: "{{ ands_storage_servers }}"
+ glusterfs_bricks_path: "{{ ands_data_path }}/glusterfs"
+ glusterfs_domains: "{{ ands_storage_domains }}"
+
+
+- name: Temporary provision /etc/hosts with Masters IP.
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" line="{{ ands_openshift_network | ipaddr(node_id) | ipaddr('address') }} {{ ands_openshift_lb }}" regexp=".*{{ ands_openshift_lb }}$" state="present"
+ when: (ands_provision_without_dns | default(false))
+ vars:
+ node_id: "{{ hostvars[groups['masters'][0]]['ands_host_id'] }}"
+
+- name: Configure OpenShift volumes
+ hosts: masters
+ roles:
+ - { role: ands_openshift, subrole: storage }
+
+- name: Remove temporary entries in /etc/hosts
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" regexp=".*{{ ands_openshift_lb }}$" state="absent"
+ when: (ands_provision_without_dns | default(false))
+
+# we also reconfigure kaas to populate new configs?
diff --git a/playbooks/openshift-setup-users.yml b/playbooks/openshift-setup-users.yml
new file mode 100644
index 0000000..d160823
--- /dev/null
+++ b/playbooks/openshift-setup-users.yml
@@ -0,0 +1,24 @@
+- name: Configure users
+ hosts: masters
+ roles:
+ - { role: ands_facts }
+
+
+- name: Temporary provision /etc/hosts with Masters IP.
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" line="{{ ands_openshift_network | ipaddr(node_id) | ipaddr('address') }} {{ ands_openshift_lb }}" regexp=".*{{ ands_openshift_lb }}$" state="present"
+ when: (ands_provision_without_dns | default(false))
+ vars:
+ node_id: "{{ hostvars[groups['masters'][0]]['ands_host_id'] }}"
+
+- name: Configure users
+ hosts: masters
+ roles:
+ - { role: ands_openshift, subrole: users }
+
+- name: Remove temporary entries in /etc/hosts
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" regexp=".*{{ ands_openshift_lb }}$" state="absent"
+ when: (ands_provision_without_dns | default(false))
diff --git a/playbooks/openshift-setup-vpn.yml b/playbooks/openshift-setup-vpn.yml
new file mode 100644
index 0000000..be5fe45
--- /dev/null
+++ b/playbooks/openshift-setup-vpn.yml
@@ -0,0 +1,13 @@
+- name: Common setup procedures
+ hosts: ands
+ roles:
+ - role: ands_facts
+
+- name: OpenVPN service
+ hosts: nodes
+ roles:
+ - role: openvpn
+ vars:
+ openvpn_config: "katrin"
+ openvpn_lb: "{{ ands_openshift_lb }}"
+ openvpn_servers: "masters"
diff --git a/playbooks/openshift-setup.yml b/playbooks/openshift-setup.yml
new file mode 100644
index 0000000..4b98f39
--- /dev/null
+++ b/playbooks/openshift-setup.yml
@@ -0,0 +1,34 @@
+- name: Common setup procedures
+ hosts: ands
+ roles:
+ - role: ands_facts
+
+
+- name: Temporary provision /etc/hosts with Masters IP.
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" line="{{ ands_openshift_network | ipaddr(node_id) | ipaddr('address') }} {{ ands_openshift_lb }}" regexp=".*{{ ands_openshift_lb }}$" state="present"
+ when: (ands_provision_without_dns | default(false))
+ vars:
+ node_id: "{{ hostvars[groups['masters'][0]]['ands_host_id'] }}"
+
+- name: Various OpenShift resources
+ hosts: nodes
+ roles:
+ - role: ands_openshift
+
+- name: Remove temporary entries in /etc/hosts
+ hosts: nodes:!masters
+ tasks:
+ - lineinfile: dest="/etc/hosts" regexp=".*{{ ands_openshift_lb }}$" state="absent"
+ when: (ands_provision_without_dns | default(false))
+
+
+- name: OpenVPN service
+ hosts: nodes
+ roles:
+ - role: openvpn
+ vars:
+ openvpn_config: "katrin"
+ openvpn_lb: "{{ ands_openshift_lb }}"
+ openvpn_servers: "masters"
diff --git a/playbooks/projects b/playbooks/projects
new file mode 120000
index 0000000..aacce37
--- /dev/null
+++ b/playbooks/projects
@@ -0,0 +1 @@
+../setup/projects/ \ No newline at end of file
diff --git a/playbooks/roles b/playbooks/roles
new file mode 120000
index 0000000..d8c4472
--- /dev/null
+++ b/playbooks/roles
@@ -0,0 +1 @@
+../roles \ No newline at end of file
diff --git a/playbooks/tmp_role.yml b/playbooks/tmp_role.yml
new file mode 100644
index 0000000..f004204
--- /dev/null
+++ b/playbooks/tmp_role.yml
@@ -0,0 +1,6 @@
+- name: Common setup procedures
+ hosts: nodes
+ remote_user: root
+ roles:
+ - ands_facts
+ - ands_openshift
diff --git a/playbooks/users b/playbooks/users
new file mode 120000
index 0000000..1e70137
--- /dev/null
+++ b/playbooks/users
@@ -0,0 +1 @@
+../setup/users/ \ No newline at end of file
diff --git a/roles/ands_facts/README b/roles/ands_facts/README
new file mode 100644
index 0000000..09abd03
--- /dev/null
+++ b/roles/ands_facts/README
@@ -0,0 +1,7 @@
+This is simplified Ands role which tries to detect storage configuration and set facts required for other
+roles.
+
+Facts:
+ - ands_data_vg
+ - ands_data_path
+ \ No newline at end of file
diff --git a/roles/ands_facts/defaults/main.yml b/roles/ands_facts/defaults/main.yml
new file mode 100644
index 0000000..257685d
--- /dev/null
+++ b/roles/ands_facts/defaults/main.yml
@@ -0,0 +1,11 @@
+ands_data_device_default_threshold: 10
+
+ands_empty_lv: { 'vg': '' }
+
+ands_data_lv: "ands_data"
+ands_data_vg: "{{ ( ansible_lvm['lvs'][ands_data_lv] | default(ands_empty_lv) )['vg'] }}"
+ands_heketi_lv: "ands_heketi"
+ands_heketi_vg: "{{ ( ansible_lvm['lvs'][ands_heketi_lv] | default(ands_empty_lv) )['vg'] }}"
+
+ands_storage_servers: "{{ groups.ands_storage_servers | map('extract', hostvars, 'ands_storage_hostname') | list }}"
+#openshift_storage_nodes: "{{ groups.storage_nodes | map('extract', hostvars, 'ands_storage_hostname') | list }}"
diff --git a/roles/ands_facts/tasks/detect_data_path.yml b/roles/ands_facts/tasks/detect_data_path.yml
new file mode 100644
index 0000000..0837e12
--- /dev/null
+++ b/roles/ands_facts/tasks/detect_data_path.yml
@@ -0,0 +1,10 @@
+---
+- name: Try to detect ands_data_path
+ set_fact: ands_data_path="{{ item.mount }}"
+ with_items: "{{ ansible_mounts }}"
+ no_log: true
+ when:
+ - not ands_data_path is defined
+ - ansible_lvm.lvs[ands_data_lv] is defined
+ - ansible_lvm.lvs[ands_data_lv].size_g > ( ands_data_device_threshold | default(ands_data_device_default_threshold) )
+ - item.device == "/dev/mapper/{{ands_data_vg}}-{{ands_data_lv}}"
diff --git a/roles/ands_facts/tasks/main.yml b/roles/ands_facts/tasks/main.yml
new file mode 100644
index 0000000..52cc5bc
--- /dev/null
+++ b/roles/ands_facts/tasks/main.yml
@@ -0,0 +1,35 @@
+- include_vars: dir="vars"
+
+- include: detect_data_path.yml
+ when: not ands_data_path is defined
+
+- name: Detect Heketi
+ set_fact: ands_storage_domains="{{ ands_storage_domains | union([ands_heketi_domain]) }}"
+ when: ansible_lvm.lvs[ands_heketi_lv] is defined
+
+- name: Set some facts
+ set_fact:
+ ands_storage_servers: "{{ ands_storage_servers }}"
+
+- name: Set some facts
+ set_fact:
+ ands_data_vg: "{{ ands_data_vg }}"
+ when: ands_data_vg != ""
+
+- name: Set some facts
+ set_fact:
+ ands_data_lv: "{{ ands_data_lv }}"
+ when: ands_data_lv != ""
+
+- name: Set some facts
+ set_fact:
+ ands_heketi_vg: "{{ ands_heketi_vg }}"
+ when: ands_heketi_vg != ""
+
+- name: Set some facts
+ set_fact:
+ ands_heketi_lv: "{{ ands_heketi_lv }}"
+ when: ands_heketi_lv != ""
+
+#- command: yum-complete-transaction --cleanup-only
+
diff --git a/roles/ands_facts/vars b/roles/ands_facts/vars
new file mode 120000
index 0000000..c56a6fe
--- /dev/null
+++ b/roles/ands_facts/vars
@@ -0,0 +1 @@
+../../setup/configs/ \ No newline at end of file
diff --git a/roles/ands_kaas/defaults/main.yml b/roles/ands_kaas/defaults/main.yml
new file mode 100644
index 0000000..3835453
--- /dev/null
+++ b/roles/ands_kaas/defaults/main.yml
@@ -0,0 +1,11 @@
+kaas_resync: false
+kaas_projects: "{{ ands_openshift_projects.keys() }}"
+
+kaas_template_root: "{{ ands_paths.provision }}/kaas/"
+
+kaas_glusterfs_endpoints: gfs
+kaas_openshift_volumes: "{{ ands_openshift_volumes }}"
+
+kaas_default_volume_capacity: "1Ti"
+kaas_default_file_owner: root
+kaas_default_file_group: root
diff --git a/roles/ands_kaas/tasks/file.yml b/roles/ands_kaas/tasks/file.yml
new file mode 100644
index 0000000..9a36e74
--- /dev/null
+++ b/roles/ands_kaas/tasks/file.yml
@@ -0,0 +1,9 @@
+---
+- name: "Setting up files in {{ path }}"
+ file:
+ path: "{{ path }}"
+ recurse: "{{ file.recurse | default(true) }}"
+ mode: "{{ file.mode | default( ((file.state | default('directory')) == 'directory') | ternary('0755', '0644') ) }}"
+ owner: "{{ file.owner | default(kaas_project_config.file_owner) | default(kaas_default_file_owner) }}"
+ group: "{{ file.group | default(kaas_project_config.file_group) | default(kaas_default_file_group) }}"
+ state: "{{ file.state | default('directory') }}"
diff --git a/roles/ands_kaas/tasks/keys.yml b/roles/ands_kaas/tasks/keys.yml
new file mode 100644
index 0000000..2096c75
--- /dev/null
+++ b/roles/ands_kaas/tasks/keys.yml
@@ -0,0 +1,37 @@
+---
+- name: Try to locate pubkey file
+ set_fact: "kaas_{{ pod.key }}_pubkey={{ lookup('file', item) }}"
+ with_first_found:
+ - paths:
+ - "{{ kaas_project_path }}/keys/"
+ files:
+ - "{{ pod.key }}.crt"
+ - "{{ pod.key }}.pub"
+ - "{{ pod.value.service.host | default('default') }}.crt"
+ - "{{ pod.value.service.host | default('default') }}.pub"
+ skip: true
+
+- name: Try to locate privkey file
+ set_fact: "kaas_{{ pod.key }}_privkey={{ lookup('file', item) }}"
+ with_first_found:
+ - paths:
+ - "{{ kaas_project_path }}/keys/"
+ files:
+ - "{{ pod.key }}.key"
+ - "{{ pod.key }}.pem"
+ - "{{ pod.value.service.host | default('default') }}.key"
+ - "{{ pod.value.service.host | default('default') }}.pem"
+ skip: true
+
+- name: Try to locate CA file
+ set_fact: "kaas_{{ pod.key }}_ca={{ lookup('file', item) }}"
+ with_first_found:
+ - paths:
+ - "{{ kaas_project_path }}/keys/"
+ files:
+ - "{{ pod.key }}.ca"
+ - "{{ pod.value.service.host | default('default') }}.ca"
+ - ca-bundle.pem
+ - ca.pem
+ - ca.crt
+ skip: true
diff --git a/roles/ands_kaas/tasks/main.yml b/roles/ands_kaas/tasks/main.yml
new file mode 100644
index 0000000..c9fb857
--- /dev/null
+++ b/roles/ands_kaas/tasks/main.yml
@@ -0,0 +1,12 @@
+---
+- name: Provision OpenShift resources & configurations
+# include: only_templates.yml
+ include: project.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ with_items: "{{ kaas_projects }}"
+ loop_control:
+ loop_var: kaas_project
+ vars:
+ kaas_template_path: "{{ kaas_template_root }}/{{ kaas_project }}"
+ kaas_project_path: "{{playbook_dir}}/projects/{{ kaas_project }}"
diff --git a/roles/ands_kaas/tasks/oc.yml b/roles/ands_kaas/tasks/oc.yml
new file mode 100644
index 0000000..d3504f8
--- /dev/null
+++ b/roles/ands_kaas/tasks/oc.yml
@@ -0,0 +1,10 @@
+---
+- name: Configure KaaS resources
+ include_role:
+ name: openshift_resource
+ tasks_from: command.yml
+ vars:
+ resource: "{{ ocitem.resource | default('') }}"
+ command: "{{ ocitem.oc }}"
+ project: "{{ kaas_project }}"
+ recreate: "{{ ocitem.recreate | default(false) }}"
diff --git a/roles/ands_kaas/tasks/ocitem.yml b/roles/ands_kaas/tasks/ocitem.yml
new file mode 100644
index 0000000..f21e8cd
--- /dev/null
+++ b/roles/ands_kaas/tasks/ocitem.yml
@@ -0,0 +1,13 @@
+---
+- name: OpenShift templates
+ include: templates.yml
+ run_once: true
+ vars:
+ kaas_template_glob: "{{ ocitem.template }}"
+ when: ocitem.template is defined
+
+- name: OpenShift commands
+ include: oc.yml
+ delegate_to: "{{ groups.masters[0] }}"
+ run_once: true
+ when: ocitem.oc is defined
diff --git a/roles/ands_kaas/tasks/ocscript.yml b/roles/ands_kaas/tasks/ocscript.yml
new file mode 100644
index 0000000..4927de4
--- /dev/null
+++ b/roles/ands_kaas/tasks/ocscript.yml
@@ -0,0 +1,8 @@
+---
+- include: ocitem.yml
+ delegate_to: "{{ groups.masters[0] }}"
+ run_once: true
+ with_items: "{{ kaas_project_config.oc }}"
+ loop_control:
+ loop_var: ocitem
+ \ No newline at end of file
diff --git a/roles/ands_kaas/tasks/project.yml b/roles/ands_kaas/tasks/project.yml
new file mode 100644
index 0000000..002596b
--- /dev/null
+++ b/roles/ands_kaas/tasks/project.yml
@@ -0,0 +1,76 @@
+---
+- name: Load global variables
+ include_vars: "{{kaas_project_path}}/vars/globals.yml"
+ when: "'{{kaas_project_path}}/vars/globals.yml' | is_file"
+
+- name: Load variables
+ include_vars: dir="{{kaas_project_path}}/vars" name="kaas_project_config"
+ when: "'{{kaas_project_path}}/vars' | is_dir"
+
+- name: Ensure OpenShift template directory exists
+ file: path="{{ kaas_template_path }}" state="directory" mode=0755 owner=root group=root
+
+- name: Configure KaaS volumes
+ include: volume.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ with_dict: "{{ kaas_project_config.volumes | default(kaas_openshift_volumes) }}"
+ loop_control:
+ loop_var: osv
+ vars:
+ query: "[*].volumes.{{osv.value.volume}}.mount"
+ mntpath: "{{ (ands_storage_domains | json_query(query)) }}"
+ path: "{{ mntpath[0] ~ (osv.value.path | default('')) }}"
+ name: "{{osv.key}}"
+ volume: "{{osv.value}}"
+ when: ( mntpath | length ) > 0
+
+- name: Copy static configuration
+ include: sync_all.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ with_items: "{{ lookup('pipe', search).split('\n') }}"
+ loop_control:
+ loop_var: osv_path
+ vars:
+ search: "find {{ kaas_project_path }}/files/ -type d -mindepth 1 -maxdepth 1"
+ osv: "{{ osv_path | basename }}"
+ pvar: "kaas_{{ osv }}_path"
+ local_path: "{{ osv_path }}"
+ remote_path: "{{ hostvars[inventory_hostname][pvar] }}"
+ when:
+ - osv in kaas_openshift_volumes
+ - hostvars[inventory_hostname][pvar] is defined
+
+- name: Configure KaaS files
+ include: file.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ with_items: "{{ kaas_project_config.files | default(ands_openshift_files) }}"
+ loop_control:
+ loop_var: file
+ vars:
+ pvar: "kaas_{{ file.osv }}_path"
+ path: "{{ hostvars[inventory_hostname][pvar] }}/{{ file.path }}"
+ when: file.osv in ( kaas_project_config.volumes | default(kaas_openshift_volumes) )
+
+- name: Load OpenSSL keys
+ include: keys.yml
+ delegate_to: "{{ groups.masters[0] }}"
+ run_once: true
+ with_dict: "{{ kaas_project_config.pods }}"
+ loop_control:
+ loop_var: pod
+
+- name: "Run OC script"
+ include: ocscript.yml
+ delegate_to: "{{ groups.masters[0] }}"
+ run_once: true
+ when: kaas_project_config.oc is defined
+
+- name: "Configure all templates"
+ include: templates.yml
+ delegate_to: "{{ groups.masters[0] }}"
+ run_once: true
+ when: kaas_project_config.oc is undefined
+
diff --git a/roles/ands_kaas/tasks/sync.yml b/roles/ands_kaas/tasks/sync.yml
new file mode 100644
index 0000000..399cb66
--- /dev/null
+++ b/roles/ands_kaas/tasks/sync.yml
@@ -0,0 +1,8 @@
+---
+- name: Check if already exists
+ stat: path="{{ item_dest }}"
+ register: result
+
+- name: "Sync '{{ item_name }}'"
+ synchronize: src="{{ item_src }}" dest="{{ remote_path }}/" archive=yes
+ when: (result.stat.exists == False) or (kaas_resync | default(false))
diff --git a/roles/ands_kaas/tasks/sync_all.yml b/roles/ands_kaas/tasks/sync_all.yml
new file mode 100644
index 0000000..58a1710
--- /dev/null
+++ b/roles/ands_kaas/tasks/sync_all.yml
@@ -0,0 +1,13 @@
+# If delegation is enabled, synchronize will look from files on delegated host not locally
+
+- name: "Analyze '{{ local_path | basename }}'"
+# debug: msg="{{ local_path }} - {{ item_name }} - {{ item }}"
+ include: sync.yml
+ run_once: true
+ with_items: "{{ lookup('pipe', filesearch).split('\n') }}"
+ vars:
+ filesearch: "find '{{ local_path }}' -mindepth 1 -maxdepth 1"
+ item_name: "{{ item | basename }}"
+ item_src: "{{ local_path }}/{{ item_name }}"
+ item_dest: "{{ remote_path }}/{{ item_name }}"
+ when: item != ""
diff --git a/roles/ands_kaas/tasks/template.yml b/roles/ands_kaas/tasks/template.yml
new file mode 100644
index 0000000..6a81dd7
--- /dev/null
+++ b/roles/ands_kaas/tasks/template.yml
@@ -0,0 +1,17 @@
+- name: Populate template
+ template: src="{{ item }}" dest="{{ kaas_template_path }}/{{ item | basename | regex_replace('\.j2','') }}" owner=root group=root mode="0644"
+ register: result
+ with_first_found:
+ - paths:
+ - "{{ role_path }}/templates/"
+ - "{{ kaas_project_path }}/templates/"
+ files:
+ - "{{ tmpl_name }}"
+
+- name: Configure KaaS resources
+ include_role: name="openshift_resource"
+ vars:
+ template: "{{ tmpl_name | basename | regex_replace('\\.j2','') }}"
+ template_path: "{{ kaas_template_path }}"
+ project: "{{ kaas_project }}"
+ recreate: "{{ result | changed | ternary (true, false) }}"
diff --git a/roles/ands_kaas/tasks/templates.yml b/roles/ands_kaas/tasks/templates.yml
new file mode 100644
index 0000000..75d43f3
--- /dev/null
+++ b/roles/ands_kaas/tasks/templates.yml
@@ -0,0 +1,20 @@
+---
+# Sorting is not enforeced
+- name: "Find KaaS templates"
+ command: "echo {{ item | quote }}"
+ register: results
+ changed_when: false
+ with_fileglob:
+ - "{{ role_path }}/templates/{{ kaas_template_glob | default('*') }}.j2"
+ - "{{ kaas_project_path }}/templates/{{ kaas_template_glob | default('*') }}.j2"
+
+- name: "Sort and execute KaaS templates"
+ include: "template.yml"
+ delegate_to: "{{ groups.masters[0] }}"
+ run_once: true
+ with_items: "{{ sorted_tmpl }}"
+ vars:
+ sorted_tmpl: "{{ results | json_query('results[*].stdout_lines') | sum(start=[]) | map('basename') | sort | unique }}"
+ loop_control:
+ loop_var: tmpl_name
+
diff --git a/roles/ands_kaas/tasks/volume.yml b/roles/ands_kaas/tasks/volume.yml
new file mode 100644
index 0000000..b82e55f
--- /dev/null
+++ b/roles/ands_kaas/tasks/volume.yml
@@ -0,0 +1,11 @@
+---
+- name: "Configure {{ name }} fact"
+ set_fact: "kaas_{{ name }}_path={{ path }}"
+
+- name: "Ensure {{ path }} exists"
+ file:
+ path: "{{ path }}"
+ state: "directory"
+ mode: "{{ volume.mode | default(0755) }}"
+ owner: "{{ volume.owner | default(kaas_project_config.file_owner) | default(kaas_default_file_owner) }}"
+ group: "{{ volume.group | default(kaas_project_config.file_group) | default(kaas_default_file_group) }}"
diff --git a/roles/ands_kaas/templates/0-gfs-volumes.yml.j2 b/roles/ands_kaas/templates/0-gfs-volumes.yml.j2
new file mode 100644
index 0000000..a162c8b
--- /dev/null
+++ b/roles/ands_kaas/templates/0-gfs-volumes.yml.j2
@@ -0,0 +1,38 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name:
+ annotations:
+ descriptions: "KATRIN Volumes"
+objects:
+{% for name, vol in (kaas_project_config.volumes | default(kaas_openshift_volumes)).iteritems() %}
+ - apiVersion: v1
+ kind: PersistentVolume
+ metadata:
+ name: {{ vol.name | default(name) }}
+ spec:
+ persistentVolumeReclaimPolicy: Retain
+ glusterfs:
+ endpoints: {{ kaas_glusterfs_endpoints }}
+ path: {{ vol.volume }}
+ readOnly: {{ not (vol.write | default(false)) }}
+ accessModes:
+ - {{ vol.access | default('ReadWriteMany') }}
+ capacity:
+ storage: {{ vol.capacity | default(kaas_default_volume_capacity) }}
+ claimRef:
+ name: {{ vol.name | default(name) }}
+ namespace: {{ kaas_project }}
+ - apiVersion: v1
+ kind: PersistentVolumeClaim
+ metadata:
+ name: {{ vol.name | default(name) }}
+ spec:
+ volumeName: {{ vol.name | default(name) }}
+ accessModes:
+ - {{ vol.access | default('ReadWriteMany') }}
+ resources:
+ requests:
+ storage: {{ vol.capacity | default(kaas_default_volume_capacity) }}
+{% endfor %}
diff --git a/roles/ands_kaas/templates/6-kaas-pods.yml.j2 b/roles/ands_kaas/templates/6-kaas-pods.yml.j2
new file mode 100644
index 0000000..9849bd3
--- /dev/null
+++ b/roles/ands_kaas/templates/6-kaas-pods.yml.j2
@@ -0,0 +1,173 @@
+#jinja2: trim_blocks: "true", lstrip_blocks: "false"
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: {{ kaas_project }}-pods
+ annotations:
+ descriptions: {{ kaas_project_config.description | default(kaas_project ~ "auto-generated pod template") }}
+objects:
+{% for name, pod in (kaas_project_config.pods | default(kaas_openshift_volumes)).iteritems() %}
+ {% set pubkey = "kaas_" ~ name ~ "_pubkey" %}
+ {% set privkey = "kaas_" ~ name ~ "_privkey" %}
+ {% set cakey = "kaas_" ~ name ~ "_ca" %}
+ {% if pod.service is defined %}
+ - apiVersion: v1
+ kind: Service
+ metadata:
+ name: {{ pod.name | default(name) }}
+ spec:
+ selector:
+ name: {{ pod.name | default(name) }}
+ {% if pod.service.ports is defined %}
+ ports:
+ {% for port in pod.service.ports %}
+ {% set portmap = (port | string).split('/') %}
+ - name: "{{ portmap[0] }}"
+ port: {{ portmap[0] }}
+ targetPort: {{ (portmap[1] is defined) | ternary(portmap[1], portmap[0]) }}
+ {% endfor %}
+ {% endif %}
+ {% if (pod.service.ports is defined) and (pod.service.host is defined) %}
+ {% set first_port = (pod.service.ports[0] | string).split('/')[0] %}
+ - apiVersion: v1
+ kind: Route
+ metadata:
+ name: kaas
+ spec:
+ host: {{ pod.service.host }}
+ to:
+ kind: Service
+ name: {{ pod.name | default(name) }}
+ port:
+ targetPort: {{ first_port }}
+ {% if (first_port == "80") %}
+ tls:
+ termination: edge
+ insecureEdgeTerminationPolicy: Allow
+ {% if hostvars[inventory_hostname][pubkey] is defined %}
+ certificate: |-
+ {{ hostvars[inventory_hostname][pubkey] | indent(10) }}
+ {% endif %}
+ {% if hostvars[inventory_hostname][privkey] is defined %}
+ key: |-
+ {{ hostvars[inventory_hostname][privkey] | indent(10) }}
+ {% endif %}
+ {% if hostvars[inventory_hostname][cakey] is defined %}
+ caCertificate: |-
+ {{ hostvars[inventory_hostname][cakey] | indent(10) }}
+ {% endif %}
+ {% endif %}
+ {% endif %}
+ {% endif %}
+ - apiVersion: v1
+ kind: DeploymentConfig
+ metadata:
+ name: kaas
+ spec:
+ replicas: {{ pod.sched.replicas | default(1) }}
+ selector:
+ name: {{ pod.name | default(name) }}
+ template:
+ metadata:
+ name: {{ pod.name | default(name) }}
+ labels:
+ name: {{ pod.name | default(name) }}
+ strategy:
+ type: {{ pod.sched.strategy | default('Rolling') }}
+ triggers:
+ - type: ConfigChange
+ spec:
+ {% if pod.selector is defined %}
+ nodeSelector:
+ {% for skey, sval in pod.selector.iteritems() %}
+ {{ skey }}: "{{ sval }}"
+ {% endfor %}
+ {% endif %}
+ {% set mappings = (pod.images | json_query('[*].mappings') | length) %}
+ {% if mappings > 0 %}
+ volumes:
+ {% for img in pod.images %}
+ {% set imgidx = loop.index %}
+ {% for vol in img.mappings %}
+ - name: vol-{{imgidx}}-{{loop.index}}
+ persistentVolumeClaim:
+ claimName: {{ vol.name }}
+ {% endfor %}
+ {% endfor %}
+ {% endif %}
+ containers:
+ {% for img in pod.images %}
+ {% set imgidx = loop.index %}
+ - name: {{ img.name | default(pod.name) | default(name) }}
+ image: {{ img.image }}
+ imagePullPolicy: Always
+ ports:
+ {% if img.ports is defined %}
+ {% for port in img.ports %}
+ - containerPort: {{ port }}
+ {% endfor %}
+ {% else %}
+ {% for port in pod.service.ports %}
+ {% set portmap = (port | string).split('/') %}
+ - containerPort: {{ (portmap[1] is defined) | ternary(portmap[1], portmap[0]) }}
+ {% endfor %}
+ {% endif %}
+ {% if img.env is defined %}
+ env:
+ {% for env_name, env_val in img.env.iteritems() %}
+ {% set env_parts = (env_val | string).split('@') %}
+ {% if env_parts[0] == "secret" %}
+ - name: {{ env_name }}
+ {% set env_sec = (env_parts[1] | string).split('/') %}
+ valueFrom:
+ secretKeyRef:
+ name: {{ env_sec[0] }}
+ key: {{ env_sec[1] }}
+ {% elif env_parts[0] == "cm" %}
+ {% set env_cm = (env_parts[1] | string).split('/') %}
+ valueFrom:
+ configMapKeyRef:
+ name: {{ env_cm[0] }}
+ key: {{ env_cm[1] }}
+ {% else %}
+ value: {{ env_val }}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ {% if img.mappings is defined %}
+ volumeMounts:
+ {% for vol in img.mappings %}
+ - name: vol-{{imgidx}}-{{loop.index}}
+ subPath: {{ (((kaas_project_config.volumes | default(kaas_openshift_volumes))[vol.name].path | default("")) ~ "/") | regex_replace('^/','') }}{{ vol.path | default("") }}
+ mountPath: {{ vol.mount }}
+ {% endfor %}
+ {% endif %}
+ {% if img.probes is defined %}
+ {% for probe in img.probes %}
+ {% if (probe.type is undefined) %}
+ {% set seq = ['livenessProbe', 'readynessProbe'] %}
+ {% elif (probe.type == "liveness") %}
+ {% set seq = ['livenessProbe'] %}
+ {% else %}
+ {% set seq = ['readynessProbe'] %}
+ {% endif %}
+ {% for type in seq %}
+ {{ type }}:
+ timeoutSeconds: {{ probe.timeout | default(1) }}
+ initialDelaySeconds: {{ probe.delay | default(10) }}
+ {% if (probe.cmd is defined) %}
+ command: "{{ probe.cmd }}"
+ {% elif (probe.path is defined) %}
+ httpGet:
+ path: {{ probe.path }}
+ port: {{ probe.port | default(80) }}
+ {% else %}
+ tcpSocket:
+ port: {{ probe.port | default(80) }}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ {% endif %}
+ {% endfor %}
+{% endfor %}
diff --git a/roles/ands_openshift/defaults/main.yml b/roles/ands_openshift/defaults/main.yml
new file mode 100644
index 0000000..857c389
--- /dev/null
+++ b/roles/ands_openshift/defaults/main.yml
@@ -0,0 +1,11 @@
+openshift_all_subroles: "{{ [ 'hostnames', 'users', 'ssh', 'storage', 'heketi' ] }}"
+openshift_subroles: "{{ ( subrole is defined ) | ternary( [ subrole ], openshift_all_subroles ) }}"
+
+openshift_namespace: "default"
+ands_disable_dynamic_provisioning: false
+
+ssh_template_path: "{{ ands_paths.provision }}/ssh/"
+storage_template_path: "{{ ands_paths.provision }}/gfs/"
+heketi_template_path: "{{ ands_paths.provision }}/heketi/"
+
+openshift_storage_nodes: "{{ groups.storage_nodes | map('extract', hostvars, 'ands_storage_hostname') | list }}"
diff --git a/roles/ands_openshift/files/gfs-svc.yml b/roles/ands_openshift/files/gfs-svc.yml
new file mode 100644
index 0000000..359f3b1
--- /dev/null
+++ b/roles/ands_openshift/files/gfs-svc.yml
@@ -0,0 +1,16 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: gfs
+ annotations:
+ descriptions: "GlusterFS endpoints & service"
+ tags: glusterfs
+objects:
+ - apiVersion: v1
+ kind: Service
+ metadata:
+ name: gfs
+ spec:
+ ports:
+ - port: 1
diff --git a/roles/ands_openshift/files/heketi/heketi.json b/roles/ands_openshift/files/heketi/heketi.json
new file mode 100644
index 0000000..9efe610
--- /dev/null
+++ b/roles/ands_openshift/files/heketi/heketi.json
@@ -0,0 +1,23 @@
+{
+ "_port_comment": "Heketi Server Port Number",
+ "port" : "8080",
+
+ "use_auth" : false,
+ "jwt" : {
+ "admin" : {
+ "key" : "My Secret"
+ },
+ "user" : {
+ "key" : "My Secret"
+ }
+ },
+
+ "glusterfs" : {
+ "executor" : "ssh",
+ "sshexec": {
+ "keyfile": "/etc/heketi_keys/id_rsa",
+ "user": "root"
+ },
+ "db" : "/var/lib/heketi/heketi.db"
+ }
+}
diff --git a/roles/ands_openshift/handlers/main.yml b/roles/ands_openshift/handlers/main.yml
new file mode 100644
index 0000000..e46b2a9
--- /dev/null
+++ b/roles/ands_openshift/handlers/main.yml
@@ -0,0 +1,4 @@
+---
+- name: heketi_topology
+ debug: msg="heketi-cli -s http://heketi.{{ openshift_master_default_subdomain }} --user=admin --secret={{ ands_secrets.heketi.admin | quote }} topology load --json={{ heketi_template_path }}/topology.json"
+# command: heketi-cli -s "http://heketi.{{ openshift_master_default_subdomain }}" --user="admin" --secret={{ ands_secrets.heketi.admin | quote }} topology load --json="{{ heketi_template_path }}/topology.json"
diff --git a/roles/ands_openshift/tasks/heketi.yml b/roles/ands_openshift/tasks/heketi.yml
new file mode 100644
index 0000000..149f85d
--- /dev/null
+++ b/roles/ands_openshift/tasks/heketi.yml
@@ -0,0 +1,13 @@
+---
+- block:
+ - name: Ensure all required packages are installed
+ yum: name={{item}} state=present
+ with_items:
+ - heketi-client
+
+ - include: heketi_resources.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ when: ansible_lvm.lvs.{{ ands_heketi_lv }} is defined
+
+ when: ansible_lvm.lvs.{{ ands_heketi_lv }} is defined
diff --git a/roles/ands_openshift/tasks/heketi_perms.yml b/roles/ands_openshift/tasks/heketi_perms.yml
new file mode 100644
index 0000000..4df6260
--- /dev/null
+++ b/roles/ands_openshift/tasks/heketi_perms.yml
@@ -0,0 +1,9 @@
+---
+- name: Mount heketidb volume
+ mount: name="{{ heketi_template_path }}/heketidbstorage" src="localhost:heketidbstorage" fstype="glusterfs" opts="defaults,_netdev" state="mounted"
+
+- name: Allow writting to heketidb
+ file: path="{{ heketi_template_path }}/heketidbstorage" owner="root" group="root" mode=0777
+
+- name: Mount heketidb volume
+ mount: name="{{ heketi_template_path }}/heketidbstorage" state="absent"
diff --git a/roles/ands_openshift/tasks/heketi_resources.yml b/roles/ands_openshift/tasks/heketi_resources.yml
new file mode 100644
index 0000000..06ae6b3
--- /dev/null
+++ b/roles/ands_openshift/tasks/heketi_resources.yml
@@ -0,0 +1,74 @@
+---
+- name: Ensure heketi configuration directory exists
+ file: path="{{ heketi_template_path }}" state="directory" mode=0600 owner=root group=root
+
+- name: Check if secret exists
+ command: oc -n "{{ openshift_namespace }}" get secret/heketi
+ register: result
+ failed_when: false
+ changed_when: (result | failed)
+
+- name: Create secret for dynamic volume provisioning
+ command: "kubectl create secret generic heketi --type=kubernetes.io/glusterfs --from-literal=key={{ ands_secrets.heketi.admin | quote }} --from-literal=user={{ ands_secrets.heketi.user | quote }} --namespace={{ openshift_namespace }}"
+ when: (result | changed)
+
+- name: Copy Heketi configuration
+ copy: src="heketi/heketi.json" dest="{{ heketi_template_path }}/heketi.json" owner=root group=root mode="0644"
+ register: result1
+
+- name: Check if configMap exists
+ command: oc -n "{{ openshift_namespace }}" get cm/heketi
+ register: result2
+ failed_when: false
+ changed_when: (result2 | failed)
+
+- name: Desotry existing Heketi configuration
+ command: oc -n "{{ openshift_namespace }}" delete cm/heketi
+ when: ( result1 | changed ) and (not (result2 | changed))
+
+- name: Create heketiConfigmap
+ command: oc -n "{{ openshift_namespace }}" create cm heketi --from-file="{{ heketi_template_path }}/heketi.json"
+ when: (result1 | changed) or (result2 | changed)
+
+- name: Check if Heketi POD is running
+ command: oc -n "{{ openshift_namespace }}" get dc/heketi --template "{{ '{{.status.availableReplicas}}' }}"
+ register: result
+ failed_when: false
+ changed_when: (result | failed) or ((result.stdout | int) < 1)
+
+- name: Fix GlusterFS volume permissions
+ include: heketi_perms.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ when: (result | changed)
+
+- name: Copy Heketi Template
+ template: src="heketi/heketi_template.json.j2" dest="{{ heketi_template_path }}/heketi_template.json" owner=root group=root mode="0644"
+ register: result
+
+- name: Create Heketi Pod
+ include_role: name="openshift_resource"
+ vars:
+ template: heketi_template.json
+ template_path: "{{ heketi_template_path }}"
+ project: "{{ openshift_namespace }}"
+ recreate: "{{ result | changed | ternary (true, false) }}"
+
+- name: Wait until heketi service is running
+ wait_for: host="heketi.{{ openshift_master_default_subdomain }}" port=80 state=present
+
+- name: Copy Heketi topology
+ template: src="heketi/topology.json.j2" dest="{{ heketi_template_path }}/topology.json" owner=root group=root mode="0644"
+ notify: heketi_topology
+
+- name: Copy Heketi storage class
+ template: src="heketi/heketi-sc.yml.j2" dest="{{ heketi_template_path }}/heketi-sc.yml" owner=root group=root mode="0644"
+ register: result
+
+- name: Setup Heketi-based dynamic volume provisioning
+ include_role: name="openshift_resource"
+ vars:
+ template: heketi-sc.yml
+ template_path: "{{ heketi_template_path }}"
+ project: "{{ openshift_namespace }}"
+ recreate: "{{ result | changed | ternary (true, false) }}"
diff --git a/roles/ands_openshift/tasks/hostnames.yml b/roles/ands_openshift/tasks/hostnames.yml
new file mode 100644
index 0000000..e489a8c
--- /dev/null
+++ b/roles/ands_openshift/tasks/hostnames.yml
@@ -0,0 +1,15 @@
+---
+#- name: Remove obsolte hostnames from /etc/hosts
+# lineinfile: dest="/etc/hosts" regexp="{{ hostvars[item]['openshift_hostname'] }}" state="absent"
+# with_inventory_hostnames:
+# - nodes
+
+
+- name: Configure all cluster hostnames in /etc/hosts
+ lineinfile: dest="/etc/hosts" line="{{ hostvars[item]['openshift_ip'] }} {{ hostvars[item]['openshift_public_hostname'] }} {{ hostvars[item]['openshift_hostname'] }}" regexp="{{ hostvars[item]['openshift_hostname'] }}" state="present"
+ with_inventory_hostnames:
+ - nodes
+
+- name: Provision /etc/hosts to ensure that all masters servers are accessing Master API on loopback device
+ lineinfile: dest="/etc/hosts" line="127.0.0.1 {{ openshift_master_cluster_hostname }}" regexp=".*{{ openshift_master_cluster_hostname }}$" state="present"
+ when: "'masters' in group_names"
diff --git a/roles/ands_openshift/tasks/main.yml b/roles/ands_openshift/tasks/main.yml
new file mode 100644
index 0000000..f72123f
--- /dev/null
+++ b/roles/ands_openshift/tasks/main.yml
@@ -0,0 +1,6 @@
+---
+- name: "Configuring OpenShift"
+ include: "{{ current_subrole }}.yml"
+ with_items: "{{ openshift_subroles }}"
+ loop_control:
+ loop_var: current_subrole
diff --git a/roles/ands_openshift/tasks/ssh.yml b/roles/ands_openshift/tasks/ssh.yml
new file mode 100644
index 0000000..7d8d99d
--- /dev/null
+++ b/roles/ands_openshift/tasks/ssh.yml
@@ -0,0 +1,21 @@
+---
+- name: Check if ssh secret exists
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ command: oc -n "{{ openshift_namespace }}" get secret/ands-ssh
+ register: result
+ changed_when: (result | failed)
+ failed_when: false
+
+- include: ssh_keygen.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
+ when: (result | changed)
+
+- name: Read SSH public key
+ shell: cat "{{ ssh_template_path }}/id_rsa.pub"
+ changed_when: false
+ register: result
+
+- name: Distribute public keys
+ authorized_key: user="root" key="{{result.stdout}}" state=present manage_dir=yes exclusive=no
diff --git a/roles/ands_openshift/tasks/ssh_keygen.yml b/roles/ands_openshift/tasks/ssh_keygen.yml
new file mode 100644
index 0000000..21a7b0a
--- /dev/null
+++ b/roles/ands_openshift/tasks/ssh_keygen.yml
@@ -0,0 +1,12 @@
+---
+- name: Ensure ssh directory exists
+ file: path="{{ ssh_template_path }}" state="directory" mode=0600 owner=root group=root
+
+- name: Generate ssh-key
+ command: ssh-keygen -t rsa -C "ands-ssh@ipe.kit.edu" -N "" -f "{{ ssh_template_path }}"/id_rsa creates="{{ ssh_template_path }}/id_rsa"
+
+- name: Create ssh secret
+ command: oc -n "{{ openshift_namespace }}" secrets new ands-ssh id_rsa="{{ ssh_template_path }}"/id_rsa id_rsa_pub="{{ ssh_template_path }}/id_rsa.pub"
+
+- name: Ensure ssh secret key is removed
+ file: path="{{ ssh_template_path }}/id_rsa" state=absent
diff --git a/roles/ands_openshift/tasks/storage.yml b/roles/ands_openshift/tasks/storage.yml
new file mode 100644
index 0000000..be2583a
--- /dev/null
+++ b/roles/ands_openshift/tasks/storage.yml
@@ -0,0 +1,4 @@
+---
+- include: storage_resources.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
diff --git a/roles/ands_openshift/tasks/storage_resources.yml b/roles/ands_openshift/tasks/storage_resources.yml
new file mode 100644
index 0000000..5adf69e
--- /dev/null
+++ b/roles/ands_openshift/tasks/storage_resources.yml
@@ -0,0 +1,33 @@
+---
+- name: Ensure OpenShift template directory exists
+ file: path="{{ storage_template_path }}" state="directory" mode=0644 owner=root group=root
+
+- name: Copy GlusterFS service template
+ copy: src="gfs-svc.yml" dest="{{ storage_template_path }}/gfs-svc.yml" owner=root group=root mode="0644"
+ register: result
+
+- name: Configure GFS service & endpoints
+ include_role: name="openshift_resource"
+ vars:
+ template: gfs-svc.yml
+ template_path: "{{ storage_template_path }}"
+ project: "{{ prj_item }}"
+ recreate: "{{ result | changed | ternary (true, false) }}"
+ with_items: "{{ ands_openshift_projects.keys() | union(['default']) }}"
+ loop_control:
+ loop_var: prj_item
+
+- name: Configure GlusterFS end-points
+ template: src="gfs-ep.yml.j2" dest="{{ storage_template_path }}/gfs-ep.yml" owner=root group=root mode="0644"
+ register: result
+
+- name: Configure GFS service & endpoints
+ include_role: name="openshift_resource"
+ vars:
+ template: gfs-ep.yml
+ template_path: "{{ storage_template_path }}"
+ project: "{{ prj_item }}"
+ recreate: "{{ result | changed | ternary (true, false) }}"
+ with_items: "{{ ands_openshift_projects.keys() | union(['default']) }}"
+ loop_control:
+ loop_var: prj_item
diff --git a/roles/ands_openshift/tasks/users.yml b/roles/ands_openshift/tasks/users.yml
new file mode 100644
index 0000000..c816203
--- /dev/null
+++ b/roles/ands_openshift/tasks/users.yml
@@ -0,0 +1,8 @@
+---
+- name: Copy htpasswd to /etc/origin/master
+ copy: src="users/htpasswd" dest="/etc/origin/master/htpasswd" mode=0644 owner=root group=root force=yes backup=no
+ when: "'masters' in group_names"
+
+- include: users_resources.yml
+ run_once: true
+ delegate_to: "{{ groups.masters[0] }}"
diff --git a/roles/ands_openshift/tasks/users_resources.yml b/roles/ands_openshift/tasks/users_resources.yml
new file mode 100644
index 0000000..35323cb
--- /dev/null
+++ b/roles/ands_openshift/tasks/users_resources.yml
@@ -0,0 +1,40 @@
+---
+- name: Configure cluster roles
+ command: "oc adm policy add-cluster-role-to-user {{ item.key.split('/')[0] }} {{ item.value.replace(' ','').split(',') | join(' ') }}"
+ with_dict: "{{ ands_openshift_roles }}"
+ when: "{{ item.key.split('/') | length == 1 }}"
+
+- name: Get project list
+ command: "oc get projects -o json"
+ changed_when: false
+ register: results
+
+- name: Find missing projects
+ set_fact: new_projects="{{ ands_openshift_projects.keys() | difference (results.stdout | from_json | json_query('items[*].metadata.name')) }}"
+ when: (results | succeeded)
+
+- name: Create missing projects
+ command: "oc adm new-project --description '{{ ands_openshift_projects[item] }}' {{ item }}"
+ with_items: "{{ new_projects | default([]) }}"
+
+- name: Configure per project roles
+ command: "oc adm policy add-role-to-user -n {{ item.key.split('/')[0] }} {{ item.key.split('/')[1] }} {{ item.value.replace(' ','').split(',') | join(' ') }}"
+ with_dict: "{{ ands_openshift_roles }}"
+ when: "{{ item.key.split('/') | length == 2 }}"
+
+- name: Get user list
+ command: "oc get users -o json"
+ changed_when: false
+ register: results
+
+- name: Find removed users
+ set_fact: removed_users="{{ results.stdout | from_json | json_query('items[*].metadata.name') | difference(ands_openshift_users.keys()) }}"
+ when: (results | succeeded)
+
+- name: Create missing projects
+ command: "oc delete identity htpasswd_auth:{{ item }}"
+ with_items: "{{ removed_users | default([]) }}"
+
+- name: Create missing projects
+ command: "oc delete user {{ item }}"
+ with_items: "{{ removed_users | default([]) }}"
diff --git a/roles/ands_openshift/templates/gfs-ep.yml.j2 b/roles/ands_openshift/templates/gfs-ep.yml.j2
new file mode 100644
index 0000000..de3acac
--- /dev/null
+++ b/roles/ands_openshift/templates/gfs-ep.yml.j2
@@ -0,0 +1,20 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: gfs
+ annotations:
+ descriptions: "GlusterFS endpoints & service"
+ tags: glusterfs
+objects:
+ - apiVersion: v1
+ kind: Endpoints
+ metadata:
+ name: gfs
+ subsets:
+{% for node in openshift_storage_nodes %}
+ - addresses:
+ - ip: {{ node }}
+ ports:
+ - port: 1
+{% endfor %}
diff --git a/roles/ands_openshift/templates/heketi/heketi-sc.yml.j2 b/roles/ands_openshift/templates/heketi/heketi-sc.yml.j2
new file mode 100644
index 0000000..23ce6ce
--- /dev/null
+++ b/roles/ands_openshift/templates/heketi/heketi-sc.yml.j2
@@ -0,0 +1,21 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: heketi-sc
+ annotations:
+ descriptions: "Heketi Dynamic Volume Provisioning"
+ tags: heketi
+objects:
+ - apiVersion: storage.k8s.io/v1beta1
+ kind: StorageClass
+ metadata:
+ name: heketi
+ annotations:
+ storageclass.beta.kubernetes.io/is-default-class: "true"
+ provisioner: kubernetes.io/glusterfs
+ parameters:
+ resturl: "http://heketi.{{ openshift_master_default_subdomain }}"
+ restuser: "admin"
+ secretName: "heketi"
+ secretNamespace: "default"
diff --git a/roles/ands_openshift/templates/heketi/heketi_template.json.j2 b/roles/ands_openshift/templates/heketi/heketi_template.json.j2
new file mode 100644
index 0000000..221662b
--- /dev/null
+++ b/roles/ands_openshift/templates/heketi/heketi_template.json.j2
@@ -0,0 +1,232 @@
+{
+ "kind": "Template",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "heketi",
+ "labels": {
+ "glusterfs": "heketi-template"
+ },
+ "annotations": {
+ "description": "Heketi service deployment template",
+ "tags": "glusterfs,heketi"
+ }
+ },
+ "labels": {
+ "template": "heketi"
+ },
+ "objects": [
+ {
+ "kind": "PersistentVolume",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "heketidb"
+ },
+ "spec": {
+ "persistentVolumeReclaimPolicy": "Retain",
+ "glusterfs": {
+ "endpoints": "gfs",
+ "path": "heketidbstorage"
+ },
+ "accessModes": [ "ReadWriteMany" ],
+ "capacity": {
+ "storage": "1Gi"
+ },
+ "claimRef": {
+ "name": "heketidb",
+ "namespace": "default"
+ }
+ }
+ },
+ {
+ "kind": "PersistentVolumeClaim",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "heketidb"
+ },
+ "spec": {
+ "volumeName": "heketidb",
+ "accessModes": [ "ReadWriteMany" ],
+ "resources": {
+ "requests": {
+ "storage": "1Gi"
+ }
+ }
+ }
+ },
+ {
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "heketi",
+ "labels": {
+ "glusterfs": "heketi"
+ },
+ "annotations": {
+ "description": "Exposes Heketi service"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "heketi",
+ "port": 8080,
+ "targetPort": 8080
+ }
+ ],
+ "selector": {
+ "name": "heketi"
+ }
+ }
+ },
+ {
+ "kind": "Route",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "heketi",
+ "labels": {
+ "glusterfs": "heketi"
+ }
+ },
+ "spec": {
+ "host": "heketi.{{ openshift_master_default_subdomain }}",
+ "to": {
+ "kind": "Service",
+ "name": "heketi"
+ }
+ }
+ },
+ {
+ "kind": "DeploymentConfig",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "heketi",
+ "labels": {
+ "glusterfs": "heketi"
+ },
+ "annotations": {
+ "description": "Defines how to deploy Heketi"
+ }
+ },
+ "spec": {
+ "replicas": 1,
+ "selector": {
+ "name": "heketi"
+ },
+ "template": {
+ "metadata": {
+ "name": "heketi",
+ "labels": {
+ "name": "heketi",
+ "glusterfs": "heketi"
+ }
+ },
+ "triggers": [
+ {
+ "type": "ConfigChange"
+ }
+ ],
+ "strategy": {
+ "type": "Recreate"
+ },
+ "spec": {
+ "nodeSelector": {
+ "master": "1"
+ },
+ "containers": [
+ {
+ "name": "heketi",
+ "image": "heketi/heketi:dev",
+ "imagePullPolicy": "Always",
+ "env": [
+ {
+ "name": "HEKETI_USER_KEY",
+ "valueFrom": {
+ "secretKeyRef": {
+ "name": "heketi",
+ "key": "user"
+ }
+ }
+ },
+ {
+ "name": "HEKETI_ADMIN_KEY",
+ "valueFrom": {
+ "secretKeyRef": {
+ "name": "heketi",
+ "key": "key"
+ }
+ }
+ },
+ {
+ "name": "HEKETI_FSTAB",
+ "value": "/var/lib/heketi/fstab"
+ },
+ {
+ "name": "HEKETI_SNAPSHOT_LIMIT",
+ "value": "14"
+ }
+ ],
+ "ports": [
+ {
+ "containerPort": 8080
+ }
+ ],
+ "volumeMounts": [
+ {
+ "name": "config",
+ "mountPath": "/etc/heketi",
+ "readOnly": true
+ },
+ {
+ "name": "ssh",
+ "mountPath": "/etc/heketi_keys",
+ "readOnly": true
+ },
+ {
+ "name": "db",
+ "mountPath": "/var/lib/heketi"
+ }
+ ],
+ "readinessProbe": {
+ "timeoutSeconds": 3,
+ "initialDelaySeconds": 3,
+ "httpGet": {
+ "path": "/hello",
+ "port": 8080
+ }
+ },
+ "livenessProbe": {
+ "timeoutSeconds": 3,
+ "initialDelaySeconds": 30,
+ "httpGet": {
+ "path": "/hello",
+ "port": 8080
+ }
+ }
+ }
+ ],
+ "volumes": [
+ {
+ "name": "ssh",
+ "secret": {
+ "secretName": "ands-ssh"
+ }
+ },
+ {
+ "name": "config",
+ "configMap": {
+ "name" : "heketi"
+ }
+ },
+ {
+ "name": "db",
+ "persistentVolumeClaim": {
+ "claimName" : "heketidb"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+} \ No newline at end of file
diff --git a/roles/ands_openshift/templates/heketi/topology.json.j2 b/roles/ands_openshift/templates/heketi/topology.json.j2
new file mode 100644
index 0000000..53d683e
--- /dev/null
+++ b/roles/ands_openshift/templates/heketi/topology.json.j2
@@ -0,0 +1,28 @@
+
+{
+ "clusters": [
+ {
+ "nodes": [
+{% set comma = joiner(",") %}
+{% for node in openshift_storage_nodes %}
+ {{ comma() }} {
+ "node": {
+ "hostnames": {
+ "manage": [
+ "{{ node }}"
+ ],
+ "storage": [
+ "{{ node }}"
+ ]
+ },
+ "zone": 1
+ },
+ "devices": [
+ "/dev/{{ansible_lvm.lvs[ands_heketi_lv].vg}}/{{ ands_heketi_lv }}"
+ ]
+ }
+{% endfor %}
+ ]
+ }
+ ]
+}
diff --git a/roles/ands_storage/README b/roles/ands_storage/README
new file mode 100644
index 0000000..d17a6cd
--- /dev/null
+++ b/roles/ands_storage/README
@@ -0,0 +1,25 @@
+Dependencies:
+ - Executed on the fat storage nodes
+ - Ands data VG and mount-point should be configured or they will default to 'ands' and /mnt/ands
+
+Parameters:
+ - ands_data_path: Mount point of Ands Data Volume, defaults to '/mnt/ands'
+ - ands_data_vg / ands_data_lv / ands_data_device / ands_data_volume_size: Configures the LV for Ands Data Volume, VG defaults to 'ands'
+ - The Katrin VG will be created if not existing. The first non-partitioned device with at least 'ands_data_device_threshold' GB of space
+ will be used unless device is directlys specified with 'ands_data_device'. If ands_data_vg already exists, the 'ands_data_deivce'
+ will be ignored.
+ - Unless 'ands_data_volume_size' is specified, all available space on VG will be used (after creating heketi volume if it
+ resides on the same VG)
+ - ands_heketi_vg / ands_heketi_lv / ands_heketi_device / ands_heketi_volume_size: Configures the LV for Heketi volume manager
+ - The heketi LV is only created if 'ands_heketi_volume_size' is specified in the inventory
+ - By default, the 'ands_data_vg' will be used to create heketi volumes.
+ - If ands_heketi_device is specified, the VG will be created if not existing.
+
+Facts:
+ - ands_data_path:
+ - ands_data_vg:
+
+Actions:
+ - Configures Ands VG & LV on the storage nodes (and detects appropriate devices unless set in inventory)
+ - Mounts Ands data volume
+ \ No newline at end of file
diff --git a/roles/ands_storage/defaults/main.yml b/roles/ands_storage/defaults/main.yml
new file mode 100644
index 0000000..3eb68b5
--- /dev/null
+++ b/roles/ands_storage/defaults/main.yml
@@ -0,0 +1,13 @@
+---
+ands_data_vg: "ands"
+#ands_data_vg: "katrin"
+ands_data_path: "/mnt/{{ ands_data_vg }}"
+ands_data_lv: "{{ ands_data_vg }}_data"
+ands_data_volume_size: "100%FREE"
+ands_data_fs: "xfs"
+
+ands_data_device_threshold: 8192
+
+ands_heketi_vg: "{{ ands_data_vg }}"
+ands_heketi_lv: "{{ ands_data_vg }}_heketi"
+#ands_heketi_volume_size: "1024G"
diff --git a/roles/ands_storage/handlers/main.yml b/roles/ands_storage/handlers/main.yml
new file mode 100644
index 0000000..9f55771
--- /dev/null
+++ b/roles/ands_storage/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: ands_heketi_change
+ command: pvresize "/dev/{{ ands_heketi_vg }}/{{ ands_heketi_lv }}"
+ when: heketi_stat_result.stat.exists
+
diff --git a/roles/ands_storage/tasks/detect_device.yml b/roles/ands_storage/tasks/detect_device.yml
new file mode 100644
index 0000000..0fb9764
--- /dev/null
+++ b/roles/ands_storage/tasks/detect_device.yml
@@ -0,0 +1,10 @@
+- name: find large block devices
+ set_fact: ands_data_device="/dev/{{ item.key }}"
+# debug: msg="{{ item.key }} - {{ (item.value.sectors | int) * (item.value.sectorsize | int) / 1024 / 1024 / 1024 }} GB"
+ with_dict: "{{ ansible_devices }}"
+ when:
+ - not ands_data_device is defined
+ - not item.value.partitions
+ - not item.value.holders
+ - item.value.sectors is defined
+ - ( (item.value.sectors | int) * (item.value.sectorsize | int) / 1024 / 1024 / 1024 ) > ands_data_device_threshold
diff --git a/roles/ands_storage/tasks/main.yml b/roles/ands_storage/tasks/main.yml
new file mode 100644
index 0000000..a86babe
--- /dev/null
+++ b/roles/ands_storage/tasks/main.yml
@@ -0,0 +1,45 @@
+---
+- name: Publish some facts
+ set_fact:
+ ands_data_vg: "{{ ands_data_vg }}"
+ ands_data_path: "{{ ands_data_path }}"
+
+- name: Analyze storage devices
+ include: detect_device.yml
+ when: not ands_data_device is defined
+
+- name: Create Ands VG
+ lvg: vg="{{ ands_data_vg }}" pvs="{{ ands_data_device }}"
+ when: ands_data_device is defined
+
+- name: Create Heketi VG
+ lvg: vg="{{ ands_heketi_vg }}" pvs="{{ ands_heketi_device }}"
+ when: ands_heketi_device is defined
+
+- name: Check if Heketi Volume already exists
+ stat: path="/dev/{{ ands_heketi_vg }}/{{ ands_heketi_lv }}"
+ register: heketi_stat_result
+ changed_when: false
+ when: ands_heketi_volume_size is defined
+
+- name: Create Heketi Volume
+ lvol: vg="{{ ands_heketi_vg }}" lv="{{ ands_heketi_lv }}" size="{{ ands_heketi_volume_size }}"
+ notify: ands_heketi_change
+ when: ands_heketi_volume_size is defined
+
+- name: Add Heketi to Storage Domains
+ set_fact: ands_storage_domains="{{ ands_storage_domains | union([ands_heketi_domain]) }}"
+ when:
+ - (ansible_lvm.lvs[ands_heketi_lv] is defined) or (ands_heketi_volume_size is defined)
+ - heketi_stat_result.stat.exists == False
+
+- name: Create Ands Data Volume
+ lvol: vg="{{ ands_data_vg }}" lv="{{ ands_data_lv }}" size="{{ ands_data_volume_size }}"
+
+- name: Ensure Ands Data Volume is formatted and resize if necessary
+ filesystem: fstype="xfs" resizefs="yes" dev="/dev/{{ ands_data_vg }}/{{ ands_data_lv }}"
+
+- name: Mount Ands Data Volume
+ mount: name="{{ ands_data_path }}" src="/dev/{{ ands_data_vg }}/{{ ands_data_lv }}" fstype="{{ ands_data_fs }}" opts="defaults" state="mounted"
+
+ \ No newline at end of file
diff --git a/roles/ands_vagrant_vm/README b/roles/ands_vagrant_vm/README
new file mode 100644
index 0000000..ca4f0d5
--- /dev/null
+++ b/roles/ands_vagrant_vm/README
@@ -0,0 +1,19 @@
+Dependencies:
+ - Executed on a single virtualization node
+ - The node should have vagrant configured
+
+Parameters:
+ - vagrant_hostname_template - The name prefix of generated hosts. I.e. if 'ipekatrin' is specified, the ipekatrin1, ipekatrin2, ... nodes will be produced
+ - vagrant_project - The vagrant project name, just specifies a subdirectory with virtual machines to allow parallel execution of VMs for testing and staging setups
+ - vagrant_projects_dir - Location of all vagrant projects
+ - vagrant_project_dir - Location of this specific vagrant project, normally is vagrant_projects_dir/vagrant_project
+ - vagrant_hosts - Number of VMs to generate, defaults to number of configured ands_hosts (i.e. OpenShift nodes currently)
+ - vagrant_cpu_cores - Number of CPU cores for each VM
+ - vagrant_mem_size - Memory per VM in GB
+ - vagrant_disk_size - Data disk size per VM in GB
+
+Facts:
+
+
+Actions:
+ - Creates and starts VMs
diff --git a/roles/ands_vagrant_vm/defaults/main.yml b/roles/ands_vagrant_vm/defaults/main.yml
new file mode 100644
index 0000000..93d92b6
--- /dev/null
+++ b/roles/ands_vagrant_vm/defaults/main.yml
@@ -0,0 +1,8 @@
+vagrant_hostname_template: ipeands
+vagrant_project: testing
+vagrant_projects_dir: /home/vagrant/projects
+vagrant_project_dir: "/home/vagrant/projects/{{vagrant_project}}"
+vagrant_disk_size: 60200
+vagrant_mem_size: 16384
+vagrant_cpu_cores: 4
+vagrant_hosts: {{ groups.ands_hosts | length }}
diff --git a/roles/ands_vagrant_vm/files/rebuild.sh b/roles/ands_vagrant_vm/files/rebuild.sh
new file mode 100644
index 0000000..73e100d
--- /dev/null
+++ b/roles/ands_vagrant_vm/files/rebuild.sh
@@ -0,0 +1,9 @@
+#! /bin/bash
+
+(
+ cd configs
+
+ vagrant destroy -f
+ vagrant up --parallel
+ vagrant provision
+)
diff --git a/roles/ands_vagrant_vm/files/run.sh b/roles/ands_vagrant_vm/files/run.sh
new file mode 100755
index 0000000..2fceb3d
--- /dev/null
+++ b/roles/ands_vagrant_vm/files/run.sh
@@ -0,0 +1,12 @@
+#! /bin/bash
+
+(
+ cd configs
+
+ VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.12.254 --netmask 255.255.255.0
+# ( ip addr show | grep 12 ) || ip addr add 192.168.12.254/24 dev vboxnet0
+ ( ip addr show | grep 212 ) || ip addr add 192.168.212.254/24 dev vboxnet0
+
+ vagrant up --parallel
+ vagrant provision
+)
diff --git a/roles/ands_vagrant_vm/handlers/main.yml b/roles/ands_vagrant_vm/handlers/main.yml
new file mode 100644
index 0000000..8c4f35d
--- /dev/null
+++ b/roles/ands_vagrant_vm/handlers/main.yml
@@ -0,0 +1,2 @@
+- name: vagrant
+ command: ./run.sh chdir="{{ vagrant_project_dir }}"
diff --git a/roles/ands_vagrant_vm/tasks/main.yml b/roles/ands_vagrant_vm/tasks/main.yml
new file mode 100644
index 0000000..7c3310d
--- /dev/null
+++ b/roles/ands_vagrant_vm/tasks/main.yml
@@ -0,0 +1,20 @@
+---
+- name: Ensure vagrant project dir is existing
+ file: name="{{ vagrant_project_dir }}/{{ item }}" state=directory
+ with_items:
+ - configs
+ - disks
+
+- name: Copy authorized_keys
+ copy: src="~/.ssh/authorized_keys" dest="{{ vagrant_project_dir }}/configs/authorized_keys" owner="root" group="root"
+
+- name: Copy scripts
+ copy: src="{{ item }}" dest="{{ vagrant_project_dir }}/{{ item }}" mode="0755"
+ with_items:
+ - run.sh
+ - rebuild.sh
+
+- name: Install Vagrantfile
+ template: src="Vagrantfile.j2" dest="{{ vagrant_project_dir }}/configs/Vagrantfile"
+ notify:
+ - vagrant
diff --git a/roles/ands_vagrant_vm/templates/Vagrantfile.j2 b/roles/ands_vagrant_vm/templates/Vagrantfile.j2
new file mode 100644
index 0000000..54128d4
--- /dev/null
+++ b/roles/ands_vagrant_vm/templates/Vagrantfile.j2
@@ -0,0 +1,51 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+{% set net = ands_openshift_network | ipaddr('network') | ipaddr(0) | regex_replace('\.\d+$', '') %}
+{% set storage_net = ands_storage_network | ipaddr('network') | ipaddr(0) | regex_replace('\.\d+$', '') %}
+{% set netid = ( net | regex_replace('^.*\.', '') ) %}
+{% set storage_netid = ( storage_net | regex_replace('^.*\.', '') ) %}
+{% set macid = ( (netid | length) > 2 ) | ternary(netid, "0" ~ netid) %}
+
+Vagrant.configure("2") do |config|
+ (1..{{ vagrant_hosts }}).each do |i|
+ config.vm.define "{{ vagrant_hostname_template }}#{i}" do |node|
+ node.vm.network "public_network", bridge: "br0", mac: "080027{{ macid }}02#{i}", ip: "{{ net }}.#{i}"
+ node.vm.network "private_network", mac: "080027{{ macid }}12#{i}", ip: "{{ storage_net }}.#{i}", name: "vboxnet0"
+ node.vm.box = "centos/7"
+ node.vm.hostname = "{{ vagrant_hostname_template }}#{i}.ipe.kit.edu"
+# node.vm.synced_folder "../data", "/root/data"
+
+# Configuring DHCP in 'vm.network' causes 2 DHCP clients (dhclinet & nm) running in parallel and getting 2 IPs.
+ node.vm.provision "shell", run: "always", inline: "( ip addr show | grep -v 141.52.64.15 | grep -v 141.52.64.17 | grep -v 141.52.64.28 | grep 141.52 ) || dhclient -cf /var/lib/NetworkManager/dhclient-eth0.conf eth1"
+ node.vm.provision "shell", run: "always", inline: "( ip addr show | grep {{ netid }}.#{i} ) || ip addr add 192.168.{{ netid }}.#{i}/24 dev eth1"
+ node.vm.provision "shell", run: "always", inline: "( ip addr show | grep {{ storage_netid }}.#{i} ) || ifcfg eth2 192.168.{{ storage_netid }}.#{i}"
+ node.vm.provision "shell", run: "always", inline: "chmod +r /etc/sysconfig/network-scripts/ifcfg-eth*"
+ node.vm.provision "shell", run: "always", inline: "chcon --reference /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth*"
+
+ node.vm.provision "shell" do |s|
+ ssh_pub_key = File.readlines("authorized_keys").first.strip
+ s.inline = <<-SHELL
+ mkdir -p /root/.ssh/
+ echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
+ SHELL
+ end
+
+ node.vm.provider "virtualbox" do |vb|
+ vb.memory = "{{ 1024 * (vagrant_mem_size | int) }}"
+ vb.cpus = {{ vagrant_cpu_cores }}
+ #vb.gui = true
+ vb.customize [
+ "modifyvm", :id,
+# "--ostype", "Linux_64",
+ "--audio", "none",
+ ]
+ vb.customize [
+ 'createhd', '--filename', "../disks/#{i}", '--format', 'VDI', '--size', {{ 1024 * (vagrant_disk_size | int) }}
+ ]
+ vb.customize [
+ 'storageattach', :id, '--storagectl', 'IDE Controller', '--port', 1, '--device', 0,'--type', 'hdd', '--medium', "../disks/#{i}.vdi"
+ ]
+ end
+ end
+ end
+end
diff --git a/roles/common/README b/roles/common/README
new file mode 100644
index 0000000..c8bd679
--- /dev/null
+++ b/roles/common/README
@@ -0,0 +1,11 @@
+Dependencies:
+ - Executed on all nodes
+ - No dependencies & no facts
+
+Parameters:
+ extra_packages: list of extra packages to install
+
+Actions:
+ - Enables standard repositories
+ - Install a set of common packages on all nodes (mc, etc.)
+ \ No newline at end of file
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
new file mode 100644
index 0000000..3f49a39
--- /dev/null
+++ b/roles/common/tasks/main.yml
@@ -0,0 +1,23 @@
+- name: Ensure all required repositories are configured
+ package: name={{item}} state=present
+ with_items:
+ - epel-release
+ - centos-release-openshift-origin
+
+# Seems we need iptables-services at least temporary...
+- name: Ensure all required packages are installed
+ package: name={{item}} state=present
+ with_items:
+ - mc
+ - bzr
+ - git
+ - yamllint
+ - pyOpenSSL
+ - python-passlib
+ - python2-ruamel-yaml
+ - python2-jmespath
+ - iptables-services
+
+- name: Ensure all extra packages are installed
+ package: name={{item}} state=present
+ with_items: "{{ extra_packages | default([]) }}"
diff --git a/roles/docker/README b/roles/docker/README
new file mode 100644
index 0000000..b9b1537
--- /dev/null
+++ b/roles/docker/README
@@ -0,0 +1,18 @@
+Dependencies:
+ - Executed on all nodes. On the storage nodes, the katrin_storage role should be executed before
+ - Unless docker_storage_vg is defined, it will try to detect the first VG with the space available and which is not equal to katrin_data_vg
+
+Parameters:
+ docker_storage_vg / docker_storage_device: Configures VG to use for docker images
+ - If docker_storage_vg is not set it will try to detect the first VG with space available and which is not listed in the 'docker_exclude_vgs'
+ - If such VG is not found, it will create VG on the specified device
+ docker_exclude_vgs: Lists VGs which should not be used to host Docker volumes
+ docker_min_size: Specifies the minimum size requirement of Docker LV
+ docker_volume_size: Adjust the size of Docker LV
+
+Facts:
+ - Nope
+
+Actions;
+ - Detects or creates Docker VG and creates inside the 'docker-pool' LV (autogrowing). The initial size may be given with docker_storage_size
+ - Installs docker, configures LVM storage backend, and enables docker service
diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml
new file mode 100644
index 0000000..6542789
--- /dev/null
+++ b/roles/docker/defaults/main.yml
@@ -0,0 +1,3 @@
+docker_min_size: 100
+docker_exclude_vgs: "{{ ands_data_vg is defined | ternary( [ ands_data_vg ], [] ) }}"
+docker_lv: "docker-pool"
diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml
new file mode 100644
index 0000000..1263cd2
--- /dev/null
+++ b/roles/docker/tasks/main.yml
@@ -0,0 +1,32 @@
+---
+- name: Ensure docker is installed
+ yum: name="docker" state="present"
+
+- name: start docker
+ service: name="docker" state="started"
+
+- name: Configure bridge-nf-call-iptables with sysctl
+ sysctl: name="net.bridge.bridge-nf-call-iptables" value=1 state=present sysctl_set=yes
+
+- name: Configure bridge-nf-call-ip6tables with sysctl
+ sysctl: name="net.bridge.bridge-nf-call-ip6tables" value=1 state=present sysctl_set=yes
+
+- name: Determine if loopback
+ shell: docker info | grep 'Data file:.*loop'
+ register: loop_device_check
+ failed_when: false
+ changed_when: loop_device_check.rc == 0
+
+- debug: msg="{{ loop_device_check.stderr }}"
+ when: loop_device_check.stderr
+
+- include: storage.yml
+ when: loop_device_check.rc == 0
+
+- name: extend the vg
+ lvol: vg="{{ ansible_lvm['lvs'][docker_lv]['vg'] }}" lv="docker_lv" size="{{ docker_volume_size }}"
+ when: docker_volume_size is defined
+
+- name: stop docker
+ service: name="docker" enabled=yes state=started
+ \ No newline at end of file
diff --git a/roles/docker/tasks/storage.yml b/roles/docker/tasks/storage.yml
new file mode 100644
index 0000000..595979c
--- /dev/null
+++ b/roles/docker/tasks/storage.yml
@@ -0,0 +1,41 @@
+---
+- name: list volume groups
+ set_fact: available_vg="{{ item.key }}"
+ with_dict: "{{ ansible_lvm.vgs }}"
+ when:
+ - not available_vg is defined
+ - not item.key in ( docker_exclude_vgs | default([]) )
+ - (item.value.free_g | int) > (docker_volume_size | default(docker_min_size))
+
+- set_fact: docker_storage_vg="{{ available_vg }}"
+ when: (not docker_storage_vg is defined) and (available_vg is defined)
+
+- fail: msg="Can't detect Docker VG"
+ when: not docker_storage_vg is defined
+
+- name: check to see if {{ docker_storage_device }} exists
+ command: "test -e {{ docker_storage_device }}"
+ when: docker_storage_device is defined
+
+- set_fact: docker_storage_config="VG={{ docker_storage_vg }} AUTO_EXTEND_POOL=true"
+
+- set_fact: docker_storage_config="{{ docker_storage_config }} DEVS={{ docker_storage_device }}"
+ when: ( docker_storage_device is defined ) and ( not ansible_lvm.vgs.{{ docker_storage_vg }} is defined )
+
+- name: stop docker
+ service: name="docker" state="stopped"
+
+- name: delete /var/lib/docker
+ file: path="/var/lib/docker" state=absent
+
+- name: generate docker-storage-setup config file
+ copy:
+ content: "{{ docker_storage_config }}"
+ dest: /etc/sysconfig/docker-storage-setup
+ owner: root
+ group: root
+ mode: 0664
+
+- name: docker storage setup
+ command: docker-storage-setup
+
diff --git a/roles/glusterfs/README b/roles/glusterfs/README
new file mode 100644
index 0000000..9a319d0
--- /dev/null
+++ b/roles/glusterfs/README
@@ -0,0 +1,26 @@
+Dependencies:
+ - Executed on all nodes.
+ * The GlusteFS servers are configured on all storage servers.
+ * The GlusterFS clients on all the servers
+ * The volumes are created in the configured domains
+ - Expects that partition for bricks is already prepared
+
+Parameters:
+ glusterfs_version: should be defined (without dot, like 39)
+ glusterfs_transport: Transport to use, defaults to rdma
+
+ glusterfs_network: CIDR for gluster internal Infiniband network
+ - if 192.168.12.0/24 is specified, the 'ipekatrin1' storage node will be mapped '192.168.12.1' IP, etc.
+ glusterfs_servers: List of storage servers in glusterfs_network
+ glusterfs_bricks_path: The location to store volume bricks, defaults to 'ands_data_path'/glusterfs
+ glusterfs_domains: Volume configuration
+
+Facts:
+
+Actions:
+ - Installs appropriate GlusterFS repositories (to match specified version)
+ - Installs required packages, only native clients on the servers without storage
+ - Enables firewalld if necessary and allows GlusterFS service
+ - Configures SELinux, etc.
+ - Probes all storage nodes using internal Infiniband IPs
+ - Creates requested volumes and mounts them
diff --git a/roles/glusterfs/defaults/main.yml b/roles/glusterfs/defaults/main.yml
new file mode 100644
index 0000000..9587a9b
--- /dev/null
+++ b/roles/glusterfs/defaults/main.yml
@@ -0,0 +1,11 @@
+---
+glusterfs_version: 39
+glusterfs_transport: rdma
+
+glusterfs_network: "{{ ands_storage_network }}"
+glusterfs_servers: "{{ ands_storage_servers }}"
+glusterfs_bricks_path: "{{ ands_data_path }}/glusterfs"
+glusterfs_domains: "{{ ands_storage_domains }}"
+
+glusterfs_all_subroles: "{{ [ 'software', 'volumes' ] }}"
+glusterfs_subroles: "{{ ( subrole is defined ) | ternary( [ subrole ], glusterfs_all_subroles ) }}"
diff --git a/roles/glusterfs/tasks/cfg/vols2.yml b/roles/glusterfs/tasks/cfg/vols2.yml
new file mode 120000
index 0000000..b6a3e8f
--- /dev/null
+++ b/roles/glusterfs/tasks/cfg/vols2.yml
@@ -0,0 +1 @@
+vols3.yml \ No newline at end of file
diff --git a/roles/glusterfs/tasks/cfg/vols3.yml b/roles/glusterfs/tasks/cfg/vols3.yml
new file mode 100644
index 0000000..d094797
--- /dev/null
+++ b/roles/glusterfs/tasks/cfg/vols3.yml
@@ -0,0 +1,13 @@
+---
+- name: "Create {{ name }} volume"
+ gluster_volume:
+ state: present
+ name: "{{ name }}"
+ cluster: "{{ domain_servers | join(',') }}"
+ replicas: "{{ domain_servers | length }}"
+ bricks: "{{ glusterfs_bricks_path }}/brick-{{ name }}"
+ transport: "{{ glusterfs_transport }}"
+
+
+- name: "Start {{ name }} volume"
+ gluster_volume: state="started" name="{{ name }}"
diff --git a/roles/glusterfs/tasks/common.yml b/roles/glusterfs/tasks/common.yml
new file mode 100644
index 0000000..7675cb9
--- /dev/null
+++ b/roles/glusterfs/tasks/common.yml
@@ -0,0 +1,16 @@
+---
+- name: Ensure GlusterFS repositories are present
+ yum: name="centos-release-gluster{{ glusterfs_version }}" state=present
+
+- name: Ensure GlusterFS is installed
+ yum: name={{item}} state=present
+ with_items:
+ - glusterfs-cli
+ - glusterfs-fuse
+ - glusterfs-libs
+ - glusterfs-rdma
+ - glusterfs
+ - libsemanage-python
+
+- name: Allow fuse in SELinux configuration
+ seboolean: name="virt_sandbox_use_fusefs" state="yes" persistent="yes"
diff --git a/roles/glusterfs/tasks/create_domain.yml b/roles/glusterfs/tasks/create_domain.yml
new file mode 100644
index 0000000..b3fc89e
--- /dev/null
+++ b/roles/glusterfs/tasks/create_domain.yml
@@ -0,0 +1,8 @@
+---
+- name: Configure volumes
+ include: create_volume.yml
+ with_dict: "{{ domain.volumes }}"
+ vars:
+ domain_servers: "{{ groups[domain.servers] | map('extract', hostvars, 'ands_storage_hostname') | list }}"
+ loop_control:
+ loop_var: volume
diff --git a/roles/glusterfs/tasks/create_volume.yml b/roles/glusterfs/tasks/create_volume.yml
new file mode 100644
index 0000000..9b955b0
--- /dev/null
+++ b/roles/glusterfs/tasks/create_volume.yml
@@ -0,0 +1,4 @@
+---
+- include: "{{ volume.value.type }}/vols{{((domain_servers | length) < 4) | ternary((domain_servers | length), 3) }}.yml"
+ vars:
+ name: "{{ volume.key }}"
diff --git a/roles/glusterfs/tasks/main.yml b/roles/glusterfs/tasks/main.yml
new file mode 100644
index 0000000..dbd1aad
--- /dev/null
+++ b/roles/glusterfs/tasks/main.yml
@@ -0,0 +1,13 @@
+---
+- include: common.yml
+ when:
+ - "'software' in glusterfs_subroles"
+
+- include: server.yml
+ when:
+ - "'software' in glusterfs_subroles"
+ - "'ands_storage_servers' in group_names"
+
+- include: volumes.yml
+ when:
+ - "'volumes' in glusterfs_subroles"
diff --git a/roles/glusterfs/tasks/mount_domain.yml b/roles/glusterfs/tasks/mount_domain.yml
new file mode 100644
index 0000000..94b6677
--- /dev/null
+++ b/roles/glusterfs/tasks/mount_domain.yml
@@ -0,0 +1,12 @@
+---
+- name: Mount volumes
+ include: mount_volume.yml
+ with_dict: "{{ domain.volumes }}"
+ vars:
+ name: "{{ volume.key }}"
+ path: "{{ volume.value.mount }}"
+ server_group: "{{ domain.servers }}"
+ domain_servers: "{{ groups[domain.servers] | map('extract', hostvars, 'ands_storage_hostname') | list }}"
+ when: volume.value.mount is defined
+ loop_control:
+ loop_var: volume
diff --git a/roles/glusterfs/tasks/mount_volume.yml b/roles/glusterfs/tasks/mount_volume.yml
new file mode 100644
index 0000000..2aea7f6
--- /dev/null
+++ b/roles/glusterfs/tasks/mount_volume.yml
@@ -0,0 +1,8 @@
+---
+- name: Mount {{ name }} volume
+ mount: name="{{ path }}" src="localhost:{{ name }}" fstype="glusterfs" opts="defaults,_netdev" state="mounted"
+ when: server_group in group_names
+
+- name: Mount {{ name }} volume
+ mount: name="{{ path }}" src="{{ domain_servers | join(",") }}:{{ name }}" fstype="glusterfs" opts="defaults,_netdev" state="mounted"
+ when: not server_group in group_names
diff --git a/roles/glusterfs/tasks/server.yml b/roles/glusterfs/tasks/server.yml
new file mode 100644
index 0000000..328a8c5
--- /dev/null
+++ b/roles/glusterfs/tasks/server.yml
@@ -0,0 +1,31 @@
+---
+- name: Ensure GlusterFS is installed
+ yum: name={{item}} state=present
+ with_items:
+ - glusterfs-server
+ - glusterfs-rdma
+
+- name: Ensure GlusterFS service is running
+ service: name=glusterd state=started enabled=yes
+
+- name: Ensure firewalld is running
+ service: name=firewalld state=started enabled=yes
+
+- name: Configure firewalld
+ firewalld: rich_rule="rule family=ipv4 source address={{glusterfs_network}} service name=glusterfs accept" state="enabled" permanent="true" immediate="true"
+ when: glusterfs_network is defined
+
+- name: Configure firewalld
+ firewalld: service="glusterfs" state="enabled" permanent="true" immediate="true"
+ when: not glusterfs_network is defined
+
+- name: Reload firewalld rules
+ shell: firewall-cmd --reload
+
+- name: Create folder for GlusterFS bricks
+ file: dest="{{glusterfs_bricks_path}}" owner="root" group="root" mode="0755" state="directory"
+
+- name: Configure gluster peers (on first host)
+ shell: gluster peer probe {{item}}
+ run_once: true
+ with_items: "{{ glusterfs_servers }}"
diff --git a/roles/glusterfs/tasks/tmp/vols2.yml b/roles/glusterfs/tasks/tmp/vols2.yml
new file mode 120000
index 0000000..b6a3e8f
--- /dev/null
+++ b/roles/glusterfs/tasks/tmp/vols2.yml
@@ -0,0 +1 @@
+vols3.yml \ No newline at end of file
diff --git a/roles/glusterfs/tasks/tmp/vols3.yml b/roles/glusterfs/tasks/tmp/vols3.yml
new file mode 100644
index 0000000..9565bb3
--- /dev/null
+++ b/roles/glusterfs/tasks/tmp/vols3.yml
@@ -0,0 +1,11 @@
+---
+- name: "Create {{ name }} volume"
+ gluster_volume:
+ state: present
+ name: "{{ name }}"
+ cluster: "{{ domain_servers | join(',') }}"
+ bricks: "{{ glusterfs_bricks_path }}/brick-{{ name }}"
+ transport: "{{ glusterfs_transport }}"
+
+- name: "Start {{ name }} volume"
+ gluster_volume: state="started" name="{{ name }}"
diff --git a/roles/glusterfs/tasks/volumes.yml b/roles/glusterfs/tasks/volumes.yml
new file mode 100644
index 0000000..e393c08
--- /dev/null
+++ b/roles/glusterfs/tasks/volumes.yml
@@ -0,0 +1,15 @@
+- name: Configure volume domains
+ include: create_domain.yml
+ run_once: true
+ delegate_to: "{{ groups[domain.servers][0] }}"
+ with_items: "{{ glusterfs_domains }}"
+ loop_control:
+ loop_var: domain
+
+- name: Mount volume domains
+ include: mount_domain.yml
+ when: ( domain.clients | default("---") ) in group_names
+ with_items: "{{ glusterfs_domains }}"
+ loop_control:
+ loop_var: domain
+
diff --git a/roles/keepalived/.gitignore b/roles/keepalived/.gitignore
new file mode 100644
index 0000000..aa16e10
--- /dev/null
+++ b/roles/keepalived/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store/*
+.vagrant/*
diff --git a/roles/keepalived/README b/roles/keepalived/README
new file mode 100644
index 0000000..956dbcb
--- /dev/null
+++ b/roles/keepalived/README
@@ -0,0 +1,13 @@
+Dependencies:
+ - Run on OpenShift master nodes
+
+Parameters:
+ - keepalived_vips: List of Virtual IPs
+ - keepalived_iface: Network interface
+
+Facts:
+
+Actions:
+ - Sets up and configures keepalived daemon
+ - Configures sysctl and firewall
+
diff --git a/roles/keepalived/defaults/main.yml b/roles/keepalived/defaults/main.yml
new file mode 100644
index 0000000..a7087b0
--- /dev/null
+++ b/roles/keepalived/defaults/main.yml
@@ -0,0 +1,12 @@
+---
+keepalived_vips: "{{ ands_ipfailover_vips | default([]) }}"
+keepalived_iface: "{{ ands_ipfailover_interface | default('eth0') }}"
+
+keepalived_master_prio: 80
+keepalived_backup_prio: 20
+keepalived_check_interval: 5
+
+keepalived_password: "{{ ands_secrets.keepalived }}"
+
+keepalived_node_id: "{{ play_hosts.index(inventory_hostname) }}"
+keepalived_num_nodes: "{{ play_hosts | length }}"
diff --git a/roles/keepalived/handlers/main.yml b/roles/keepalived/handlers/main.yml
new file mode 100644
index 0000000..2ac9fe3
--- /dev/null
+++ b/roles/keepalived/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart keepalived
+ service: name=keepalived state=restarted
diff --git a/roles/keepalived/tasks/main.yml b/roles/keepalived/tasks/main.yml
new file mode 100644
index 0000000..771faa7
--- /dev/null
+++ b/roles/keepalived/tasks/main.yml
@@ -0,0 +1,22 @@
+---
+- name: Install keepalived
+ yum: name=keepalived state=present
+ notify: restart keepalived
+
+- name: Configure net.ipv4.ip_nonlocal_bind with sysctl
+ sysctl: name="net.ipv4.ip_nonlocal_bind" value=1 state=present sysctl_set=yes
+
+- name: Ensure firewalld is running
+ service: name=firewalld state=started enabled=yes
+
+- name: Configure firewalld
+ firewalld: rich_rule="rule protocol value=vrrp accept" state="enabled" permanent="true" immediate="true"
+
+- name: Install configuration
+ template: src=keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf owner=root group=root mode=0600
+ tags: keepalived
+ notify: restart keepalived
+
+- name: Start keepalived
+ service: name=keepalived state=running
+ tags: keepalived
diff --git a/roles/keepalived/templates/keepalived.conf.j2 b/roles/keepalived/templates/keepalived.conf.j2
new file mode 100644
index 0000000..8d9a580
--- /dev/null
+++ b/roles/keepalived/templates/keepalived.conf.j2
@@ -0,0 +1,36 @@
+global_defs {
+}
+
+vrrp_script track {
+ script "[ -f /etc/keepalived/track.sh ] || exit 0 && /etc/keepalived/track.sh"
+ interval {{ keepalived_check_interval }}
+}
+
+{% for vips in keepalived_vips %}
+{% set id = ( vips | ipaddr('address') | regex_replace('^.*\.', '') ) %}
+
+vrrp_instance VI_{{ loop.index }} {
+
+ virtual_router_id {{ id }}
+
+ state {{ (( ( loop.index - 1) % (keepalived_num_nodes | int) ) == (keepalived_node_id | int) ) | ternary('MASTER', 'BACKUP') }}
+ state {{ (( ( loop.index - 1) % (keepalived_num_nodes | int) ) == (keepalived_node_id | int) ) | ternary(keepalived_master_prio, keepalived_backup_prio) }}
+
+ interface {{ keepalived_iface }}
+
+ virtual_ipaddress {
+ {{ vips }} dev {{ keepalived_iface }}
+ }
+
+ advert_int 1
+
+ authentication {
+ auth_type PASS
+ auth_pass {{ keepalived_password }}
+ }
+
+ track_script {
+ track
+ }
+}
+{% endfor %}
diff --git a/roles/openshift_certificate_expiry b/roles/openshift_certificate_expiry
new file mode 120000
index 0000000..789348e
--- /dev/null
+++ b/roles/openshift_certificate_expiry
@@ -0,0 +1 @@
+../../openshift-ansible/roles/openshift_certificate_expiry \ No newline at end of file
diff --git a/roles/openshift_resource/defaults/main.yml b/roles/openshift_resource/defaults/main.yml
new file mode 100644
index 0000000..ec44c4f
--- /dev/null
+++ b/roles/openshift_resource/defaults/main.yml
@@ -0,0 +1 @@
+template_path: "/mnt/provision/templates"
diff --git a/roles/openshift_resource/tasks/command.yml b/roles/openshift_resource/tasks/command.yml
new file mode 100644
index 0000000..c8e8d04
--- /dev/null
+++ b/roles/openshift_resource/tasks/command.yml
@@ -0,0 +1,17 @@
+- block:
+
+ - name: Lookup the specified resource
+ command: "oc get -n {{project}} {{resource}}"
+ register: result
+ failed_when: false
+ changed_when: (result | failed)
+
+ - name: Detroy existing resources
+ command: "oc delete -n {{project}} {{resource}}"
+ failed_when: false
+ when: (recreate|default(false))
+
+ - name: Executing command
+ command: "oc -n {{ project }} {{ command }}"
+ when: (recreate|default(false)) or (result | changed)
+ run_once: true
diff --git a/roles/openshift_resource/tasks/lookup.yml b/roles/openshift_resource/tasks/lookup.yml
new file mode 100644
index 0000000..07beb81
--- /dev/null
+++ b/roles/openshift_resource/tasks/lookup.yml
@@ -0,0 +1,6 @@
+---
+- name: Lookup the specified resource
+ command: "oc get -n {{project}} {{rkind}}/{{rname}}"
+ register: result
+ failed_when: false
+ changed_when: (result | failed)
diff --git a/roles/openshift_resource/tasks/main.yml b/roles/openshift_resource/tasks/main.yml
new file mode 100644
index 0000000..698efea
--- /dev/null
+++ b/roles/openshift_resource/tasks/main.yml
@@ -0,0 +1,22 @@
+---
+- block:
+ - name: "Read template {{ template }}"
+ command: cat '{{template_path}}/{{template}}'
+ changed_when: false
+ register: results
+
+ - name: Parse JSON templates
+ set_fact: tmpl="{{ results.stdout | from_json }}"
+ when: template.find(".json") != -1
+
+ - name: Parse YaML templates
+ set_fact: tmpl="{{ results.stdout | from_yaml }}"
+ when: template.find(".json") == -1
+
+ - include: template.yml
+ when: tmpl.kind == "Template"
+
+ - include: resource.yml
+ when: tmpl.kind != "Template"
+
+ run_once: true
diff --git a/roles/openshift_resource/tasks/resource.yml b/roles/openshift_resource/tasks/resource.yml
new file mode 100644
index 0000000..326abbb
--- /dev/null
+++ b/roles/openshift_resource/tasks/resource.yml
@@ -0,0 +1,20 @@
+---
+- block:
+ - name: Find out which resources we are going to configure
+ set_fact: rkind="{{ tmpl.kind }}" rname="{{ tmpl.metadata.name }}"
+
+ - name: Lookup the specified resource
+ command: "oc get -n {{project}} {{rkind}}/{{rname}}"
+ register: result
+ failed_when: false
+ changed_when: (result | failed)
+
+ - name: Detroy existing resources
+ command: "oc delete -n {{project}} {{rkind}}/{{rname}}"
+ failed_when: false
+ when: (recreate|default(false))
+
+ - name: Create resources defined in template
+ command: "oc create -n {{project}} -f '{{ template_path }}/{{ template }}' {{ create_args | default('') }}"
+ when: (recreate|default(false)) or (result | changed)
+ run_once: true
diff --git a/roles/openshift_resource/tasks/template.yml b/roles/openshift_resource/tasks/template.yml
new file mode 100644
index 0000000..c93dec5
--- /dev/null
+++ b/roles/openshift_resource/tasks/template.yml
@@ -0,0 +1,25 @@
+---
+- block:
+ - name: Find out which resources we are going to configure
+ set_fact: resources="{{ tmpl | json_query(query) }}"
+ vars:
+ query: "objects[*].{kind: kind, name: metadata.name}"
+
+ - name: Lookup the specified resource
+ command: "oc get -n {{project}} {{item.kind}}/{{item.name}}"
+ register: results
+ failed_when: false
+ changed_when: (results | failed)
+ with_items: "{{ resources | default([]) }}"
+# when: not (recreate|default(false))
+
+ - name: Detroy existing resources
+ command: "oc delete -n {{project}} {{resources[item|int].kind}}/{{resources[item|int].name}}"
+ failed_when: false
+ with_sequence: start=0 count="{{resources | default([]) | length}}"
+ when: ((recreate|default(false)) or (results | changed)) and (results.results[item|int].rc == 0)
+
+ - name: Create resources defined in template
+ shell: "oc process -f '{{ template_path }}/{{template}}' {{ template_args | default('') }} | oc create -n {{project}} -f - {{ create_args | default('') }}"
+ when: (recreate|default(false)) or (results | changed)
+ run_once: true
diff --git a/roles/openvpn/README b/roles/openvpn/README
new file mode 100644
index 0000000..9c64b0d
--- /dev/null
+++ b/roles/openvpn/README
@@ -0,0 +1,12 @@
+Dependencies:
+ - Runs on all OpenShift nodes
+
+Parameters:
+ - ands_openshift_lb: The load balancer which OpenVPN clients (non-master nodes) will be using to get into the network
+
+Facts:
+
+Actions:
+ - Sets up and configures OpenVPN servers & clients
+ - Opens firewall port
+
diff --git a/roles/openvpn/defaults/main.yml b/roles/openvpn/defaults/main.yml
new file mode 100644
index 0000000..513936a
--- /dev/null
+++ b/roles/openvpn/defaults/main.yml
@@ -0,0 +1,15 @@
+openvpn_port: 1194
+openvpn_dir: "/etc/openvpn"
+openvpn_config: "katrin"
+openvpn_config_file: "{{openvpn_dir}}/{{openvpn_config}}.conf"
+openvpn_keydir: "{{openvpn_dir}}/keys_{{openvpn_config}}"
+openvpn_ccdir: "{{openvpn_dir}}/ccd_{{openvpn_config}}"
+openvpn_service: "openvpn@{{openvpn_config}}.service"
+
+openvpn_lb: "{{ ands_openshift_lb }}"
+openvpn_servers: "masters"
+
+
+openvpn_server_id: "{{ (openvpn_servers in group_names) | ternary(groups[openvpn_servers].index((openvpn_servers in group_names) | ternary(inventory_hostname, groups[openvpn_servers][0])), -1) }}"
+openvpn_subnet_id: "{{ (katrin_openvpn_subnet_offset | int) + (openvpn_server_id | int) }}"
+openvpn_net: "{{ katrin_openvpn_network | ipsubnet(katrin_openvpn_subnet_bits, openvpn_subnet_id) }}"
diff --git a/roles/openvpn/files/ca/ca.crt b/roles/openvpn/files/ca/ca.crt
new file mode 100644
index 0000000..a37743b
--- /dev/null
+++ b/roles/openvpn/files/ca/ca.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDojCCAwugAwIBAgIJAMIDvuFyaww1MA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD
+VQQGEwJOTzERMA8GA1UECBMIbWlkZ2FhcmQxETAPBgNVBAcTCG1pZGdhYXJkMREw
+DwYDVQQKEwhEYXJrU29mdDELMAkGA1UECxMCQ0ExFDASBgNVBAMTC0RhcmtTb2Z0
+IENBMSgwJgYJKoZIhvcNAQkBFhlkYXJrc29mdEBkc2lkZS5keW5kbnMub3JnMB4X
+DTA5MTAyMjAyMTgzOVoXDTE5MTAyMDAyMTgzOVowgZMxCzAJBgNVBAYTAk5PMREw
+DwYDVQQIEwhtaWRnYWFyZDERMA8GA1UEBxMIbWlkZ2FhcmQxETAPBgNVBAoTCERh
+cmtTb2Z0MQswCQYDVQQLEwJDQTEUMBIGA1UEAxMLRGFya1NvZnQgQ0ExKDAmBgkq
+hkiG9w0BCQEWGWRhcmtzb2Z0QGRzaWRlLmR5bmRucy5vcmcwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAKDdlL90dk2ixdjG6Fm5hPjvqex2ZqIWk7l+hh9AJjhT
+oFYO5DKTb4JioKYA76KZ7uCgQzxhiDfma3agw7WGR8H+n28AzkxgqTEKWU4ysrxQ
+CtykKO3qs79iYHdcX1NRUAx22cpBnQjq7HJkXJWg5i+3RPSyk8Vl2QC8BzfiLH/D
+AgMBAAGjgfswgfgwHQYDVR0OBBYEFF+geRyB0QoAUHIRgtlq3sLwiZIIMIHIBgNV
+HSMEgcAwgb2AFF+geRyB0QoAUHIRgtlq3sLwiZIIoYGZpIGWMIGTMQswCQYDVQQG
+EwJOTzERMA8GA1UECBMIbWlkZ2FhcmQxETAPBgNVBAcTCG1pZGdhYXJkMREwDwYD
+VQQKEwhEYXJrU29mdDELMAkGA1UECxMCQ0ExFDASBgNVBAMTC0RhcmtTb2Z0IENB
+MSgwJgYJKoZIhvcNAQkBFhlkYXJrc29mdEBkc2lkZS5keW5kbnMub3JnggkAwgO+
+4XJrDDUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBey4alwOjkx6LG
+csNMOeofpSVr79muQALum9rdsZVBb93x9ygSJJ8ygCgolXDGF4uAGX31kbYtiANY
+rXef9gNWZLlMt2NPcJzV53hbXnFDYOSpFwUCFwvBAFkhIv4r1TjqxHSDiRdTda31
+0J1sESMtMZook/QKNx+46CQrjUGWzA==
+-----END CERTIFICATE-----
diff --git a/roles/openvpn/files/ca/ca.key b/roles/openvpn/files/ca/ca.key
new file mode 100644
index 0000000..f1df0c4
--- /dev/null
+++ b/roles/openvpn/files/ca/ca.key
@@ -0,0 +1,50 @@
+$ANSIBLE_VAULT;1.1;AES256
+66303364323939633166383539303539333162653336313339616434663839353333613063623262
+6564343033366235336230326161636661393638353336320a646631393037333838633831616532
+33653431326435636135643835613738333634636566373131323634633730343836353562633464
+3561313137613166660a613534623665646637386161633031393461343762663930633634616634
+33366532313537643035623239616137616561633366303132633430636234333534383563663236
+37346239353437333362663862626334383866623338653061326632646363383563356264336665
+65383962646131393165613838623661613865343165396135633761646137306436303266336634
+63356239373032303261353937393664663265396161366163356463633539393635643762366165
+66626230386662353361646663343464643534313332323565386230613463666238356261353730
+35663337626164333233323437393432336535383437653036643338363662313138363037323666
+61343061626262316461613838653834303764623733393131303035346336393333656233383666
+32666235356231663838386530306333383463616362303563363164343230383066303732666533
+38666435313437636132393836313630323839333237623130646366363633393939646261653763
+31313634313134623639303134653264646638666563366334366235653339303031313262346465
+39613934623461393438613363376566646432313931333731333939373966316464373137363431
+62626134303730613736316263616133323863616565326463656562656462316636613933393934
+65303761343762626232633634373233386334643334613337306562613938656136303837616637
+36643363386166373432306236333438663536303065363961613236366465356232303331376233
+32656637373235643839623539633761653164323230363763383737303566326239623530633962
+30616230363434363439383838633765633632663963323337393430643966616663383662643838
+32636465363130366232643933323066383965643032643537616531306239616662633932653866
+64363939343935323137356433373538613930653332303834386436386331313334333031376533
+39346130646439326531356239376531343730656232393331313633363765316439336565353331
+61316266356161366534636138363161643363666266616662306130353334323636363062393539
+65633565333037393264346265303461333734623233306563643732613432623330623232393637
+37323635323432343738376462646639313239313465383661353763306437373939353737356437
+30323037656231653534316665633431343137666665303831346139626539316561303739633339
+61666564643766343061623031666563663962626533313264323435343734343533656430636230
+34386634613739393433306361643634646266626462626333323936306234393430343331313366
+36363537373735613235383164343764643532316561616530306636636431386336323531306639
+66376435636339613963346463653162373137393531373031316635323561393239633661383035
+62343464336639643463633766396263623966613031633666336666333233316530363961336263
+62346334303363323437356535356665393065313665663566336661356334633637646561646135
+66656664303239336263313765623836393937303937343431666234343064636533363463396434
+35366333393738373063633834323038353065616364383234326531303666643139663431613437
+38623332333733356434636462643162396137623138663132336131306137623866346339623261
+32373139376636303636643766343864666263383239316437643533303463383866643830646563
+39353138623435633162663932313130303161656462316237353766313465646332326139653066
+33333138626665363766616630333166636530663163366163373432646463303838316134306463
+39383066396237313132636339656166353336386636373336366238623965643139646138376532
+39666235353662663439353263343834653734616337623938643137396134303835363662316263
+32636337303134383737343238643736373565366462313963353434623935616537613064613931
+33656337653866376630316134326431343139306661383162373163353966633565653336643738
+65653630373638616232663966613330303133366166383135366432353865636534633733343561
+64336631653833356639316135343437343631373831666265643763363262633966656337613535
+33613432323431646334633866626633343062656532666234316565396363346332306632303861
+37393739323835363462363362333966393732643565396532613734313938643737666365376236
+63343062303563393061613436623737303634393365306563363563616665336263326337636464
+3739
diff --git a/roles/openvpn/files/keys/dh1024.pem b/roles/openvpn/files/keys/dh1024.pem
new file mode 100644
index 0000000..39e2099
--- /dev/null
+++ b/roles/openvpn/files/keys/dh1024.pem
@@ -0,0 +1,18 @@
+$ANSIBLE_VAULT;1.1;AES256
+38326437373461343039653963383935386135613432376662636163636131656139393365616237
+6239376630626666303034353733383534666438636439640a663935663538366439363165613436
+35616530653061633137343034616633383833626438353131663264333565343635373239643864
+6233623239383637640a363637316237346561376264336534633563613462633464376238623165
+64653165666663663434316638633238313963383931326138396335613931306233343062346337
+65323438656461366132663266336637306435663064306636333631613135356635636136316665
+63343265616261653635303063346161613639636262363835623161626264636139326139366234
+61656336326434303038633532353334356165623438353637653162323462383962666536353938
+33633163343165353634393965663636306630623536343431633866633932666539656666626339
+38386131346365373237346230653962363639373337313130383263636130626133623838383936
+38326433666237393261616162306365336530383232343430613535356261323761626337386633
+64623637333763653462383635333035623164396130383066313238623633356665663937366563
+61333138393537653766346637656261373762636330386263333337633563356263326561313835
+30333931333966333235333732613931346538346237626664616439643737653032376363343662
+35643462646562393934316534386134663566633037613131326434323933373839653963663730
+61356166616566643665666330343039313630646438363239303039653537646566646461313530
+3566
diff --git a/roles/openvpn/files/openvpn_logrotate.conf b/roles/openvpn/files/openvpn_logrotate.conf
new file mode 100644
index 0000000..7dac758
--- /dev/null
+++ b/roles/openvpn/files/openvpn_logrotate.conf
@@ -0,0 +1,9 @@
+/var/log/openvpn.log {
+ rotate 4
+ weekly
+ missingok
+ notifempty
+ sharedscripts
+ copytruncate
+ delaycompress
+}
diff --git a/roles/openvpn/handlers/main.yml b/roles/openvpn/handlers/main.yml
new file mode 100644
index 0000000..befbcf5
--- /dev/null
+++ b/roles/openvpn/handlers/main.yml
@@ -0,0 +1,12 @@
+---
+- name: daemon-reload
+ command: systemctl daemon-reload
+
+- name: openvpn
+ service: name="{{openvpn_service}}" state=restarted
+
+- name: firewalld
+ shell: firewall-cmd --reload
+
+
+ \ No newline at end of file
diff --git a/roles/openvpn/tasks/config.yml b/roles/openvpn/tasks/config.yml
new file mode 100644
index 0000000..67fdfa1
--- /dev/null
+++ b/roles/openvpn/tasks/config.yml
@@ -0,0 +1,28 @@
+- name: create openvpn configuration directory
+ file: path="{{openvpn_dir}}" state=directory
+
+- name: create openvpn key directory
+ file: path="{{openvpn_keydir}}" state=directory
+
+- name: create openvpn client config directory
+ file: path="{{openvpn_ccdir}}" state=directory
+ when: openvpn_servers in group_names
+
+- name: copy templates
+ template: src="{{item}}" dest="{{openvpn_ccdir}}/{{ item | basename | regex_replace('\.j2','') }}" owner=root group=root mode="0644"
+ with_fileglob:
+ - ../templates/{{ openvpn_config }}/ccd/*
+ when: openvpn_servers in group_names
+
+- name: generate cluster templates
+ template: src="{{ openvpn_config }}/ccd.j2" dest="{{openvpn_ccdir}}/{{ hostvars[item]['ansible_hostname'] }}" owner=root group=root mode="0644"
+ vars:
+ id: "{{ hostvars[item]['ands_host_id'] }}"
+ with_inventory_hostnames:
+ - nodes:!{{openvpn_servers}}
+ when: openvpn_servers in group_names
+
+- name: create openvpn config file
+ template: src="{{ openvpn_config }}/{{ (openvpn_servers in group_names) | ternary('openvpn_server.j2', 'openvpn_client.j2') }}" dest="{{ openvpn_config_file }}" owner=root group=root
+ notify:
+ - openvpn
diff --git a/roles/openvpn/tasks/keys.yml b/roles/openvpn/tasks/keys.yml
new file mode 100644
index 0000000..dd9f4ec
--- /dev/null
+++ b/roles/openvpn/tasks/keys.yml
@@ -0,0 +1,13 @@
+- name: Copy CA private key
+ copy: src="ca/ca.key" dest="{{openvpn_keydir}}/" owner="root" group="root" mode="0400"
+
+- name: OpenSSL generate request
+ command: openssl req -subj '/CN={{ ansible_hostname }}' -new -keyout "node.key" -out "node.csr" -batch -nodes chdir="{{openvpn_keydir}}" creates="{{openvpn_keydir}}/node.csr"
+
+- name: Generate CA serial file
+ copy: content="01" dest="{{openvpn_keydir}}/ca.srl"
+
+- name: OpenSSL sign the request
+ command: openssl x509 -req -days 3650 -in "node.csr" -CA "ca.crt" -CAkey "ca.key" -out "node.crt" chdir="{{openvpn_keydir}}" creates="{{openvpn_keydir}}/node.crt"
+ notify:
+ - openvpn
diff --git a/roles/openvpn/tasks/main.yml b/roles/openvpn/tasks/main.yml
new file mode 100644
index 0000000..df49976
--- /dev/null
+++ b/roles/openvpn/tasks/main.yml
@@ -0,0 +1,62 @@
+---
+- name: Ensure OpenVPN and OpenSSL are installed
+ yum: name={{item}} state=present
+ with_items:
+ - openvpn
+ - openssl
+
+- name: copy openvpn logrotate config file
+ copy: src="openvpn_logrotate.conf" dest="/etc/logrotate.d/openvpn.conf" owner="root" group="root" mode="0400"
+
+- name: Copy CA certificate and the keys
+ copy: src="{{ item }}" dest="{{openvpn_keydir}}/" owner="root" group="root" mode="0400"
+ with_fileglob:
+ - ca/ca.crt
+ - keys/*
+
+- name: Check if OpenSSL certificate is already generated
+ stat: path="{{ openvpn_keydir }}/node.crt"
+ register: result
+
+- name: setup openvpn keys
+ include: keys.yml
+ when: result.stat.exists == False
+
+- name: Ensure CA key is removed
+ file: path="{{openvpn_keydir}}/ca.key" state=absent
+
+- name: setup openvpn configuration
+ include: config.yml
+
+- name: Ensure OpenVPN service is enabled
+ service: name="{{openvpn_service}}" enabled=yes
+
+- name: Check if we already reconfigured SystemD Unit
+ stat: path={{ item }}
+ register: result
+ vars:
+ item: "/etc/systemd/system/{{openvpn_service}}"
+
+- name: Copy SystemD Unit
+ copy: src="/usr/lib/systemd/system/openvpn@.service" dest="{{ item }}" remote_src=true
+ vars:
+ item: "/etc/systemd/system/{{openvpn_service}}"
+ when: result.stat.exists == False
+
+- name: Re-configure systemd to start OpenVPN after origin-node
+ lineinfile: dest="/etc/systemd/system/{{openvpn_service}}" regexp="^After=" line="After=network.target origin-node.service" state=present
+ notify: daemon-reload
+
+- name: Ensure OpenVPN service is running
+ service: name="{{openvpn_service}}" state=started
+
+- name: Ensure firewalld is running
+ service: name=firewalld state=started enabled=yes
+ when: openvpn_servers in group_names
+
+- name: Configure firewalld
+ firewalld: port="{{openvpn_port}}/tcp" state="enabled" permanent="true" immediate="true"
+ notify:
+ - firewalld
+ when: openvpn_servers in group_names
+
diff --git a/roles/openvpn/templates/katrin/ccd.j2 b/roles/openvpn/templates/katrin/ccd.j2
new file mode 100644
index 0000000..d278648
--- /dev/null
+++ b/roles/openvpn/templates/katrin/ccd.j2
@@ -0,0 +1,2 @@
+ifconfig-push {{ openvpn_net | ipaddr(id | int) | ipaddr('address') }} {{ openvpn_net | ipaddr('netmask') }}
+push "route 192.168.110.0 255.255.255.0 {{ openvpn_net | ipaddr(181) | ipaddr('address') }}"
diff --git a/roles/openvpn/templates/katrin/ccd/ikkatrinadei.ka.fzk.de.j2 b/roles/openvpn/templates/katrin/ccd/ikkatrinadei.ka.fzk.de.j2
new file mode 100644
index 0000000..e1a786d
--- /dev/null
+++ b/roles/openvpn/templates/katrin/ccd/ikkatrinadei.ka.fzk.de.j2
@@ -0,0 +1,3 @@
+#ifconfig-push clientIP serverIP
+ifconfig-push {{ openvpn_net | ipaddr(181) | ipaddr('address') }} {{ openvpn_net | ipaddr('netmask') }}
+iroute 192.168.110.0 255.255.255.0
diff --git a/roles/openvpn/templates/katrin/ccd/ipechilinga4.ka.fzk.de.j2 b/roles/openvpn/templates/katrin/ccd/ipechilinga4.ka.fzk.de.j2
new file mode 100644
index 0000000..3673a0b
--- /dev/null
+++ b/roles/openvpn/templates/katrin/ccd/ipechilinga4.ka.fzk.de.j2
@@ -0,0 +1 @@
+ifconfig-push {{ openvpn_net | ipaddr(90) | ipaddr('address') }} {{ openvpn_net | ipaddr('netmask') }}
diff --git a/roles/openvpn/templates/katrin/openvpn_client.j2 b/roles/openvpn/templates/katrin/openvpn_client.j2
new file mode 100644
index 0000000..a09322e
--- /dev/null
+++ b/roles/openvpn/templates/katrin/openvpn_client.j2
@@ -0,0 +1,24 @@
+client
+remote {{openvpn_lb}} {{openvpn_port}}
+proto tcp
+dev tun
+
+topology subnet
+
+ca {{openvpn_keydir}}/ca.crt
+cert {{openvpn_keydir}}/node.crt
+key {{openvpn_keydir}}/node.key
+dh {{openvpn_keydir}}/dh1024.pem
+
+resolv-retry infinite
+keepalive 5 15
+comp-lzo
+#user nobody
+#group nobody
+persist-key
+persist-tun
+
+log /var/log/openvpn_{{openvpn_config}}.log
+status /var/log/openvpn_{{openvpn_config}}_status.log
+verb 3
+
diff --git a/roles/openvpn/templates/katrin/openvpn_server.j2 b/roles/openvpn/templates/katrin/openvpn_server.j2
new file mode 100644
index 0000000..22c200d
--- /dev/null
+++ b/roles/openvpn/templates/katrin/openvpn_server.j2
@@ -0,0 +1,26 @@
+port {{openvpn_port}}
+dev tun
+
+topology subnet
+client-to-client
+server {{ openvpn_net | ipaddr('network') }} {{ openvpn_net | ipaddr('netmask') }}
+proto tcp
+
+ca {{openvpn_keydir}}/ca.crt
+cert {{openvpn_keydir}}/node.crt
+key {{openvpn_keydir}}/node.key
+dh {{openvpn_keydir}}/dh1024.pem
+
+keepalive 10 120
+comp-lzo
+#user nobody
+#group nobody
+persist-key
+persist-tun
+client-config-dir {{openvpn_ccdir}}
+log /var/log/openvpn_{{openvpn_config}}.log
+status /var/log/openvpn_{{openvpn_config}}_status.log
+verb 3
+
+route 192.168.110.0 255.255.255.0 {{ openvpn_net | ipaddr(181) | ipaddr('address') }}
+
diff --git a/setup.sh b/setup.sh
new file mode 100755
index 0000000..a61da44
--- /dev/null
+++ b/setup.sh
@@ -0,0 +1,60 @@
+#! /bin/bash
+
+. opts.sh
+
+
+case "${1}" in
+ all)
+ ./setup.sh prepare
+ ./setup.sh openshift
+ ./setup.sh configure
+ ./setup.sh projects
+ ;;
+ local)
+ apply playbooks/local.yml || exit 1
+ ;;
+ vm)
+ apply playbooks/ands-setup-vm.yml || exit 1
+ ;;
+ prepare)
+ apply playbooks/ands-prepare.yml || exit 1
+ ;;
+ openshift)
+ apply playbooks/openshift-install.yml || exit 1
+ ;;
+ configure)
+ apply playbooks/openshift-setup.yml || exit 1
+ ;;
+ projects)
+ apply playbooks/openshift-setup-projects.yml || exit 1
+ ;;
+ openshift-nodes)
+ apply playbooks/openshift-add-nodes.yml || exit 1
+ ;;
+ nodes)
+ ./setup.sh prepare || exit 1
+ ./setup.sh openshift-nodes || exit 1
+ ./setup.sh configure || exit 1
+ ;;
+ users)
+ apply playbooks/openshift-setup-users.yml || exit 1
+ ;;
+ storage)
+ apply playbooks/openshift-setup-storage.yml || exit 1
+ ;;
+ vpn)
+ apply playbooks/openshift-setup-vpn.yml || exit 1
+ ;;
+ certs)
+ apply playbooks/openshift-redeploy-certificates.yml --extra-vars "openshift_certificates_redeploy_ca=true" || exit 1
+ ;;
+ check)
+ apply playbooks/maintain.yml || exit
+ ;;
+ setup)
+ [ -n "$2" ] || usage "Specify that to setup"
+ apply ands_openshift -e "subrole=$2"
+ ;;
+ *)
+ apply $@ || exit 1
+esac
diff --git a/setup/configs/labels.yml b/setup/configs/labels.yml
new file mode 100644
index 0000000..1c5f19f
--- /dev/null
+++ b/setup/configs/labels.yml
@@ -0,0 +1,6 @@
+---
+ands_openshift_labels:
+ region: "infra"
+ zone: "default"
+ master: "{{ ( 'masters' in group_names ) | ternary(1, 0) }}"
+ fat_storage: "{{ ( 'storage_nodes' in group_names ) | ternary(1, 0) }}"
diff --git a/setup/configs/openshift.yml b/setup/configs/openshift.yml
new file mode 100644
index 0000000..eb3af3e
--- /dev/null
+++ b/setup/configs/openshift.yml
@@ -0,0 +1,12 @@
+---
+ands_openshift_projects:
+ katrin: KArlsruhe TRItium Neutrino
+
+ands_openshift_users:
+ pdv: IPE Administation Account
+ katrin: KATRIN Project
+ csa: Suren A. Chilingaryan <csa@suren.me>
+
+ands_openshift_roles:
+ cluster-admin: csa, pdv
+ katrin/admin: katrin
diff --git a/setup/configs/secrets.yml b/setup/configs/secrets.yml
new file mode 100644
index 0000000..5005be0
--- /dev/null
+++ b/setup/configs/secrets.yml
@@ -0,0 +1,10 @@
+$ANSIBLE_VAULT;1.1;AES256
+30383738386265633133306363326639656331333736303966633133333661383561373533303966
+6361396564626437656237663035616461656661316265610a306336373231616136393330616632
+39376265346133303332363235303635383239336463633234616261643161643639313732313536
+3264636131353136640a623238663037336261303063313564303665386561643030373064356536
+61633136393138656533336563346635656531376161376639656436343437326538366336643734
+35363464646131316366626234613737366633626166376339313832646239626265333637613261
+32353535356537323533373831396138326239643937623865613731373165393633626331623839
+66323039393136313431383264633731653965386261613336376263396531333862306562313337
+38346465613831613566353233346634373032663537353633643330363136343264
diff --git a/setup/configs/volumes.yml b/setup/configs/volumes.yml
new file mode 100644
index 0000000..2546f1c
--- /dev/null
+++ b/setup/configs/volumes.yml
@@ -0,0 +1,37 @@
+---
+ands_paths:
+ provision: /mnt/provision
+ openshift: /mnt/openshift
+ temporary: /mnt/temporary
+
+ands_heketi_domain:
+ servers: "storage_nodes"
+ volumes:
+ heketidbstorage: { type: "cfg" }
+
+ands_storage_domains:
+ - servers: "ands_storage_servers"
+ clients: "ands_servers"
+ volumes:
+ provision: { type: "cfg", mount: "{{ ands_paths.provision }}" }
+ - servers: "storage_nodes"
+ clients: "nodes"
+ volumes:
+ openshift: { type: "cfg", mount: "{{ ands_paths.openshift }}" }
+ temporary: { type: "tmp", mount: "{{ ands_paths.temporary }}" }
+# - ovirt:
+# - pdv:
+
+
+# Per project list (to distribute in multiple namespaces later)
+ands_openshift_volumes:
+ etc: { volume: "openshift", path: "/etc" }
+ src: { volume: "openshift", path: "/src" }
+ www: { volume: "openshift", path: "/www" }
+ log: { volume: "temporary", path: "/log", write: true}
+ tmp: { volume: "temporary", path: "/tmp", write: true}
+
+
+# Global list, we only take things from the volume of project
+ands_openshift_files:
+ - { osv: "etc", path: "apache2-kaas", state: "directory" }
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.d/README b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/README
new file mode 100644
index 0000000..f5e9661
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/README
@@ -0,0 +1,9 @@
+
+This directory holds configuration files for the Apache HTTP Server;
+any files in this directory which have the ".conf" extension will be
+processed as httpd configuration files. The directory is used in
+addition to the directory /etc/httpd/conf.modules.d/, which contains
+configuration files necessary to load modules.
+
+Files are processed in alphabetical order.
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.d/autoindex.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/autoindex.conf
new file mode 100644
index 0000000..55f658e
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/autoindex.conf
@@ -0,0 +1,94 @@
+#
+# Directives controlling the display of server-generated directory listings.
+#
+# Required modules: mod_authz_core, mod_authz_host,
+# mod_autoindex, mod_alias
+#
+# To see the listing of a directory, the Options directive for the
+# directory must include "Indexes", and the directory must not contain
+# a file matching those listed in the DirectoryIndex directive.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+#
+IndexOptions FancyIndexing HTMLTable VersionSort
+
+# We include the /icons/ alias for FancyIndexed directory listings. If
+# you do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "/opt/rh/httpd24/root/usr/share/httpd/icons/"
+
+<Directory "/opt/rh/httpd24/root/usr/share/httpd/icons">
+ Options Indexes MultiViews FollowSymlinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions. These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif /core
+AddIcon /icons/bomb.gif */core.*
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes. These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes.
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing. Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.d/ssl.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/ssl.conf
new file mode 100644
index 0000000..a70324b
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/ssl.conf
@@ -0,0 +1,217 @@
+#
+# When we also provide SSL we have to listen to the
+# the HTTPS port in addition.
+#
+Listen 0.0.0.0:8443 https
+
+##
+## SSL Global Context
+##
+## All SSL configuration in this context applies both to
+## the main server and all SSL-enabled virtual hosts.
+##
+
+# Pass Phrase Dialog:
+# Configure the pass phrase gathering process.
+# The filtering dialog program (`builtin' is a internal
+# terminal dialog) has to provide the pass phrase on stdout.
+SSLPassPhraseDialog builtin
+
+# Inter-Process Session Cache:
+# Configure the SSL Session Cache: First the mechanism
+# to use and second the expiring timeout (in seconds).
+SSLSessionCache shmcb:/opt/rh/httpd24/root/var/run/httpd/sslcache(512000)
+SSLSessionCacheTimeout 300
+
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the
+# SSL library. The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+SSLRandomSeed startup file:/dev/urandom 256
+SSLRandomSeed connect builtin
+#SSLRandomSeed startup file:/dev/random 512
+#SSLRandomSeed connect file:/dev/random 512
+#SSLRandomSeed connect file:/dev/urandom 512
+
+#
+# Use "SSLCryptoDevice" to enable any supported hardware
+# accelerators. Use "openssl engine -v" to list supported
+# engine names. NOTE: If you enable an accelerator and the
+# server does not start, consult the error logs and ensure
+# your accelerator is functioning properly.
+#
+SSLCryptoDevice builtin
+#SSLCryptoDevice ubsec
+
+##
+## SSL Virtual Host Context
+##
+
+<VirtualHost _default_:8443>
+
+# General setup for the virtual host, inherited from global configuration
+#DocumentRoot "/var/www/html"
+#ServerName www.example.com:8443
+
+# Use separate log files for the SSL virtual host; note that LogLevel
+# is not inherited from httpd.conf.
+ErrorLog |/usr/bin/cat
+TransferLog |/usr/bin/cat
+LogLevel warn
+
+# SSL Engine Switch:
+# Enable/Disable SSL for this virtual host.
+SSLEngine on
+
+# SSL Protocol support:
+# List the enable protocol levels with which clients will be able to
+# connect. Disable SSLv2 access by default:
+SSLProtocol all -SSLv2
+
+# SSL Cipher Suite:
+# List the ciphers that the client is permitted to negotiate.
+# See the mod_ssl documentation for a complete list.
+SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
+
+# Speed-optimized SSL Cipher configuration:
+# If speed is your main concern (on busy HTTPS servers e.g.),
+# you might want to force clients to specific, performance
+# optimized ciphers. In this case, prepend those ciphers
+# to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
+# Caveat: by giving precedence to RC4-SHA and AES128-SHA
+# (as in the example below), most connections will no longer
+# have perfect forward secrecy - if the server's key is
+# compromised, captures of past or future traffic must be
+# considered compromised, too.
+#SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
+#SSLHonorCipherOrder on
+
+# Server Certificate:
+# Point SSLCertificateFile at a PEM encoded certificate. If
+# the certificate is encrypted, then you will be prompted for a
+# pass phrase. Note that a kill -HUP will prompt again. A new
+# certificate can be generated using the genkey(1) command.
+SSLCertificateFile /etc/pki/tls/certs/localhost.crt
+
+# Server Private Key:
+# If the key is not combined with the certificate, use this
+# directive to point at the key file. Keep in mind that if
+# you've both a RSA and a DSA private key you can configure
+# both in parallel (to also allow the use of DSA ciphers, etc.)
+SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
+
+# Server Certificate Chain:
+# Point SSLCertificateChainFile at a file containing the
+# concatenation of PEM encoded CA certificates which form the
+# certificate chain for the server certificate. Alternatively
+# the referenced file can be the same as SSLCertificateFile
+# when the CA certificates are directly appended to the server
+# certificate for convinience.
+#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
+
+# Certificate Authority (CA):
+# Set the CA certificate verification path where to find CA
+# certificates for client authentication or alternatively one
+# huge file containing all of them (file must be PEM encoded)
+#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
+
+# Client Authentication (Type):
+# Client certificate verification type and depth. Types are
+# none, optional, require and optional_no_ca. Depth is a
+# number which specifies how deeply to verify the certificate
+# issuer chain before deciding the certificate is not valid.
+#SSLVerifyClient require
+#SSLVerifyDepth 10
+
+# Access Control:
+# With SSLRequire you can do per-directory access control based
+# on arbitrary complex boolean expressions containing server
+# variable checks and other lookup directives. The syntax is a
+# mixture between C and Perl. See the mod_ssl documentation
+# for more details.
+#<Location />
+#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
+# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+#</Location>
+
+# SSL Engine Options:
+# Set various options for the SSL engine.
+# o FakeBasicAuth:
+# Translate the client X.509 into a Basic Authorisation. This means that
+# the standard Auth/DBMAuth methods can be used for access control. The
+# user name is the `one line' version of the client's X.509 certificate.
+# Note that no password is obtained from the user. Every entry in the user
+# file needs this password: `xxj31ZMTZzkVA'.
+# o ExportCertData:
+# This exports two additional environment variables: SSL_CLIENT_CERT and
+# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+# server (always existing) and the client (only existing when client
+# authentication is used). This can be used to import the certificates
+# into CGI scripts.
+# o StdEnvVars:
+# This exports the standard SSL/TLS related `SSL_*' environment variables.
+# Per default this exportation is switched off for performance reasons,
+# because the extraction step is an expensive operation and is usually
+# useless for serving static content. So one usually enables the
+# exportation for CGI and SSI requests only.
+# o StrictRequire:
+# This denies access when "SSLRequireSSL" or "SSLRequire" applied even
+# under a "Satisfy any" situation, i.e. when it applies access is denied
+# and no other module can change it.
+# o OptRenegotiate:
+# This enables optimized SSL connection renegotiation handling when SSL
+# directives are used in per-directory context.
+#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+<Files ~ "\.(cgi|shtml|phtml|php3?)$">
+ SSLOptions +StdEnvVars
+</Files>
+<Directory "/var/www/cgi-bin">
+ SSLOptions +StdEnvVars
+</Directory>
+
+# SSL Protocol Adjustments:
+# The safe and default but still SSL/TLS standard compliant shutdown
+# approach is that mod_ssl sends the close notify alert but doesn't wait for
+# the close notify alert from client. When you need a different shutdown
+# approach you can use one of the following variables:
+# o ssl-unclean-shutdown:
+# This forces an unclean shutdown when the connection is closed, i.e. no
+# SSL close notify alert is send or allowed to received. This violates
+# the SSL/TLS standard but is needed for some brain-dead browsers. Use
+# this when you receive I/O errors because of the standard approach where
+# mod_ssl sends the close notify alert.
+# o ssl-accurate-shutdown:
+# This forces an accurate shutdown when the connection is closed, i.e. a
+# SSL close notify alert is send and mod_ssl waits for the close notify
+# alert of the client. This is 100% SSL/TLS standard compliant, but in
+# practice often causes hanging connections with brain-dead browsers. Use
+# this only for browsers where you know that their SSL implementation
+# works correctly.
+# Notice: Most problems of broken clients are also related to the HTTP
+# keep-alive facility, so you usually additionally want to disable
+# keep-alive for those clients, too. Use variable "nokeepalive" for this.
+# Similarly, one has to force some clients to use HTTP/1.0 to workaround
+# their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+# "force-response-1.0" for this.
+BrowserMatch "MSIE [2-5]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+
+# Per-Server Logging:
+# The home of a custom SSL log file. Use this when you want a
+# compact non-error SSL logfile on a virtual host basis.
+CustomLog |/usr/bin/cat \
+ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+
+</VirtualHost>
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.d/userdir.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/userdir.conf
new file mode 100644
index 0000000..b5d7a49
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/userdir.conf
@@ -0,0 +1,36 @@
+#
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received.
+#
+# The path to the end user account 'public_html' directory must be
+# accessible to the webserver userid. This usually means that ~userid
+# must have permissions of 711, ~userid/public_html must have permissions
+# of 755, and documents contained therein must be world-readable.
+# Otherwise, the client will only receive a "403 Forbidden" message.
+#
+<IfModule mod_userdir.c>
+ #
+ # UserDir is disabled by default since it can confirm the presence
+ # of a username on the system (depending on home directory
+ # permissions).
+ #
+ UserDir disabled
+
+ #
+ # To enable requests to /~user/ to serve the user's public_html
+ # directory, remove the "UserDir disabled" line above, and uncomment
+ # the following line instead:
+ #
+ #UserDir public_html
+</IfModule>
+
+#
+# Control access to UserDir directories. The following is an example
+# for a site where these directories are restricted to read-only.
+#
+<Directory "/home/*/public_html">
+ AllowOverride FileInfo AuthConfig Limit Indexes
+ Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+ Require method GET POST OPTIONS
+</Directory>
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.d/welcome.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/welcome.conf
new file mode 100644
index 0000000..34b4b72
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.d/welcome.conf
@@ -0,0 +1,18 @@
+#
+# This configuration file enables the default "Welcome" page if there
+# is no default index page present for the root URL. To disable the
+# Welcome page, comment out all the lines below.
+#
+# NOTE: if this file is removed, it will be restored on upgrades.
+#
+<LocationMatch "^/+$">
+ Options -Indexes
+ ErrorDocument 403 /.noindex.html
+</LocationMatch>
+
+<Directory /opt/rh/httpd24/root/usr/share/httpd/noindex>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+Alias /.noindex.html /opt/rh/httpd24/root/usr/share/httpd/noindex/index.html
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-base.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-base.conf
new file mode 100644
index 0000000..c109de6
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-base.conf
@@ -0,0 +1,67 @@
+#
+# This file loads most of the modules included with the Apache HTTP
+# Server itself.
+#
+
+LoadModule access_compat_module modules/mod_access_compat.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule allowmethods_module modules/mod_allowmethods.so
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authn_dbd_module modules/mod_authn_dbd.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_socache_module modules/mod_authn_socache.so
+LoadModule authz_core_module modules/mod_authz_core.so
+LoadModule authz_dbd_module modules/mod_authz_dbd.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule cache_disk_module modules/mod_cache_disk.so
+LoadModule cache_socache_module modules/mod_cache_socache.so
+LoadModule data_module modules/mod_data.so
+LoadModule dbd_module modules/mod_dbd.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule dumpio_module modules/mod_dumpio.so
+LoadModule echo_module modules/mod_echo.so
+LoadModule env_module modules/mod_env.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule filter_module modules/mod_filter.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule http2_module modules/mod_http2.so
+LoadModule include_module modules/mod_include.so
+LoadModule info_module modules/mod_info.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule macro_module modules/mod_macro.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule remoteip_module modules/mod_remoteip.so
+LoadModule reqtimeout_module modules/mod_reqtimeout.so
+LoadModule request_module modules/mod_request.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
+LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
+LoadModule socache_dbm_module modules/mod_socache_dbm.so
+LoadModule socache_memcache_module modules/mod_socache_memcache.so
+LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
+LoadModule status_module modules/mod_status.so
+LoadModule substitute_module modules/mod_substitute.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule unique_id_module modules/mod_unique_id.so
+LoadModule unixd_module modules/mod_unixd.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule version_module modules/mod_version.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-dav.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-dav.conf
new file mode 100644
index 0000000..e6af8de
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-dav.conf
@@ -0,0 +1,3 @@
+LoadModule dav_module modules/mod_dav.so
+LoadModule dav_fs_module modules/mod_dav_fs.so
+LoadModule dav_lock_module modules/mod_dav_lock.so
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-lua.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-lua.conf
new file mode 100644
index 0000000..9e0d0db
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-lua.conf
@@ -0,0 +1 @@
+LoadModule lua_module modules/mod_lua.so
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-mpm.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-mpm.conf
new file mode 100644
index 0000000..7bfd1d4
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-mpm.conf
@@ -0,0 +1,19 @@
+# Select the MPM module which should be used by uncommenting exactly
+# one of the following LoadModule lines:
+
+# prefork MPM: Implements a non-threaded, pre-forking web server
+# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
+LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+
+# worker MPM: Multi-Processing Module implementing a hybrid
+# multi-threaded multi-process web server
+# See: http://httpd.apache.org/docs/2.4/mod/worker.html
+#
+#LoadModule mpm_worker_module modules/mod_mpm_worker.so
+
+# event MPM: A variant of the worker MPM with the goal of consuming
+# threads only for connections with active processing
+# See: http://httpd.apache.org/docs/2.4/mod/event.html
+#
+#LoadModule mpm_event_module modules/mod_mpm_event.so
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-optional.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-optional.conf
new file mode 100644
index 0000000..70bda5e
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-optional.conf
@@ -0,0 +1,20 @@
+#
+# This file lists modules included with the Apache HTTP Server
+# which are not enabled by default.
+#
+
+#LoadModule asis_module modules/mod_asis.so
+#LoadModule buffer_module modules/mod_buffer.so
+#LoadModule file_cache_module modules/mod_file_cache.so
+#LoadModule watchdog_module modules/mod_watchdog.so
+#LoadModule heartbeat_module modules/mod_heartbeat.so
+#LoadModule heartmonitor_module modules/mod_heartmonitor.so
+#LoadModule usertrack_module modules/mod_usertrack.so
+#LoadModule dialup_module modules/mod_dialup.so
+#LoadModule charset_lite_module modules/mod_charset_lite.so
+#LoadModule log_debug_module modules/mod_log_debug.so
+#LoadModule log_forensic_module modules/mod_log_forensic.so
+#LoadModule ratelimit_module modules/mod_ratelimit.so
+#LoadModule reflector_module modules/mod_reflector.so
+#LoadModule sed_module modules/mod_sed.so
+#LoadModule speling_module modules/mod_speling.so
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-proxy.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-proxy.conf
new file mode 100644
index 0000000..cc0bca0
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-proxy.conf
@@ -0,0 +1,16 @@
+# This file configures all the proxy modules:
+LoadModule proxy_module modules/mod_proxy.so
+LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
+LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
+LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
+LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
+LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
+LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+LoadModule proxy_connect_module modules/mod_proxy_connect.so
+LoadModule proxy_express_module modules/mod_proxy_express.so
+LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
+LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
+LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
+LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-ssl.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-ssl.conf
new file mode 100644
index 0000000..53235cd
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-ssl.conf
@@ -0,0 +1 @@
+LoadModule ssl_module modules/mod_ssl.so
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-systemd.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-systemd.conf
new file mode 100644
index 0000000..b208c97
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/00-systemd.conf
@@ -0,0 +1,2 @@
+# This file configures systemd module:
+LoadModule systemd_module modules/mod_systemd.so
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/01-cgi.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/01-cgi.conf
new file mode 100644
index 0000000..5b8b936
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf.modules.d/01-cgi.conf
@@ -0,0 +1,14 @@
+# This configuration file loads a CGI module appropriate to the MPM
+# which has been configured in 00-mpm.conf. mod_cgid should be used
+# with a threaded MPM; mod_cgi with the prefork MPM.
+
+<IfModule mpm_worker_module>
+ LoadModule cgid_module modules/mod_cgid.so
+</IfModule>
+<IfModule mpm_event_module>
+ LoadModule cgid_module modules/mod_cgid.so
+</IfModule>
+<IfModule mpm_prefork_module>
+ LoadModule cgi_module modules/mod_cgi.so
+</IfModule>
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf/httpd.conf b/setup/projects/katrin/files/etc/apache2-kaas/conf/httpd.conf
new file mode 100644
index 0000000..88fcb97
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf/httpd.conf
@@ -0,0 +1,353 @@
+#
+# This is the main Apache HTTP server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so 'log/access_log'
+# with ServerRoot set to '/www' will be interpreted by the
+# server as '/www/log/access_log', where as '/log/access_log' will be
+# interpreted as '/log/access_log'.
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path. If you point
+# ServerRoot at a non-local disk, be sure to specify a local disk on the
+# Mutex directive, if file-based mutexes are used. If you wish to share the
+# same ServerRoot for multiple httpd daemons, you will need to change at
+# least PidFile.
+#
+ServerRoot "/opt/rh/httpd24/root/etc/httpd"
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+#Listen 12.34.56.78:80
+Listen 0.0.0.0:8080
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+Include conf.modules.d/*.conf
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User default
+Group root
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition. These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+#ServerName www.example.com:80
+
+#
+# Deny access to the entirety of your server's filesystem. You must
+# explicitly permit access to web content directories in other
+# <Directory> blocks below.
+#
+<Directory />
+ AllowOverride none
+ Require all denied
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/opt/rh/httpd24/root/var/www/html"
+
+#
+# Relax access to content within /opt/rh/httpd24/root/var/www.
+#
+<Directory "/opt/rh/httpd24/root/var/www">
+ AllowOverride None
+ # Allow open access:
+ Require all granted
+</Directory>
+
+# Further relax access to the default document root:
+<Directory "/opt/rh/httpd24/root/var/www/html">
+ #
+ # Possible values for the Options directive are "None", "All",
+ # or any combination of:
+ # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+ #
+ # Note that "MultiViews" must be named *explicitly* --- "Options All"
+ # doesn't give it to you.
+ #
+ # The Options directive is both complicated and important. Please see
+ # http://httpd.apache.org/docs/2.4/mod/core.html#options
+ # for more information.
+ #
+ Options Indexes FollowSymLinks
+
+ #
+ # AllowOverride controls what directives may be placed in .htaccess files.
+ # It can be "All", "None", or any combination of the keywords:
+ # Options FileInfo AuthConfig Limit
+ #
+ AllowOverride All
+
+ #
+ # Controls who can get stuff from this server.
+ #
+ Require all granted
+</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+ DirectoryIndex index.html
+</IfModule>
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ".ht*">
+ Require all denied
+</Files>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog |/usr/bin/cat
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+<IfModule log_config_module>
+ #
+ # The following directives define some format nicknames for use with
+ # a CustomLog directive (see below).
+ #
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+ <IfModule logio_module>
+ # You need to enable mod_logio.c to use %I and %O
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+ </IfModule>
+
+ #
+ # The location and format of the access logfile (Common Logfile Format).
+ # If you do not define any access logfiles within a <VirtualHost>
+ # container, they will be logged here. Contrariwise, if you *do*
+ # define per-<VirtualHost> access logfiles, transactions will be
+ # logged therein and *not* in this file.
+ #
+ #CustomLog "logs/access_log" common
+
+ #
+ # If you prefer a logfile with access, agent, and referer information
+ # (Combined Logfile Format) you can use the following directive.
+ #
+ CustomLog |/usr/bin/cat combined
+</IfModule>
+
+<IfModule alias_module>
+ #
+ # Redirect: Allows you to tell clients about documents that used to
+ # exist in your server's namespace, but do not anymore. The client
+ # will make a new request for the document at its new location.
+ # Example:
+ # Redirect permanent /foo http://www.example.com/bar
+
+ #
+ # Alias: Maps web paths into filesystem paths and is used to
+ # access content that does not live under the DocumentRoot.
+ # Example:
+ # Alias /webpath /full/filesystem/path
+ #
+ # If you include a trailing / on /webpath then the server will
+ # require it to be present in the URL. You will also likely
+ # need to provide a <Directory> section to allow access to
+ # the filesystem path.
+
+ #
+ # ScriptAlias: This controls which directories contain server scripts.
+ # ScriptAliases are essentially the same as Aliases, except that
+ # documents in the target directory are treated as applications and
+ # run by the server when requested rather than as documents sent to the
+ # client. The same rules about trailing "/" apply to ScriptAlias
+ # directives as to Alias.
+ #
+ ScriptAlias /cgi-bin/ "/opt/rh/httpd24/root/var/www/cgi-bin/"
+
+</IfModule>
+
+#
+# "/opt/rh/httpd24/root/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/opt/rh/httpd24/root/var/www/cgi-bin">
+ AllowOverride None
+ Options None
+ Require all granted
+</Directory>
+
+<IfModule mime_module>
+ #
+ # TypesConfig points to the file containing the list of mappings from
+ # filename extension to MIME-type.
+ #
+ TypesConfig /etc/mime.types
+
+ #
+ # AddType allows you to add to or override the MIME configuration
+ # file specified in TypesConfig for specific file types.
+ #
+ #AddType application/x-gzip .tgz
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ #
+ #AddEncoding x-compress .Z
+ #AddEncoding x-gzip .gz .tgz
+ #
+ # If the AddEncoding directives above are commented-out, then you
+ # probably should define those extensions to indicate media types:
+ #
+ AddType application/x-compress .Z
+ AddType application/x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers":
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action directive (see below)
+ #
+ # To use CGI scripts outside of ScriptAliased directories:
+ # (You will also need to add "ExecCGI" to the "Options" directive.)
+ #
+ #AddHandler cgi-script .cgi
+
+ # For type maps (negotiated resources):
+ #AddHandler type-map var
+
+ #
+ # Filters allow you to process content before it is sent to the client.
+ #
+ # To parse .shtml files for server-side includes (SSI):
+ # (You will also need to add "Includes" to the "Options" directive.)
+ #
+ AddType text/html .shtml
+ AddOutputFilter INCLUDES .shtml
+</IfModule>
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default. To use the
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+<IfModule mime_magic_module>
+ #
+ # The mod_mime_magic module allows the server to use various hints from the
+ # contents of the file itself to determine its type. The MIMEMagicFile
+ # directive tells the module where the hint definitions are located.
+ #
+ MIMEMagicFile conf/magic
+</IfModule>
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# EnableMMAP and EnableSendfile: On systems that support it,
+# memory-mapping or the sendfile syscall may be used to deliver
+# files. This usually improves server performance, but must
+# be turned off when serving from networked-mounted
+# filesystems or if support for these functions is otherwise
+# broken on your system.
+# Defaults if commented: EnableMMAP On, EnableSendfile Off
+#
+#EnableMMAP off
+EnableSendfile on
+
+# Supplemental configuration
+#
+# Load config files in the "/etc/httpd/conf.d" directory, if any.
+IncludeOptional conf.d/*.conf
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/conf/magic b/setup/projects/katrin/files/etc/apache2-kaas/conf/magic
new file mode 100644
index 0000000..7c56119
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/conf/magic
@@ -0,0 +1,385 @@
+# Magic data for mod_mime_magic Apache module (originally for file(1) command)
+# The module is described in /manual/mod/mod_mime_magic.html
+#
+# The format is 4-5 columns:
+# Column #1: byte number to begin checking from, ">" indicates continuation
+# Column #2: type of data to match
+# Column #3: contents of data to match
+# Column #4: MIME type of result
+# Column #5: MIME encoding of result (optional)
+
+#------------------------------------------------------------------------------
+# Localstuff: file(1) magic for locally observed files
+# Add any locally observed files here.
+
+#------------------------------------------------------------------------------
+# end local stuff
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# Java
+
+0 short 0xcafe
+>2 short 0xbabe application/java
+
+#------------------------------------------------------------------------------
+# audio: file(1) magic for sound formats
+#
+# from Jan Nicolai Langfeldt <janl@ifi.uio.no>,
+#
+
+# Sun/NeXT audio data
+0 string .snd
+>12 belong 1 audio/basic
+>12 belong 2 audio/basic
+>12 belong 3 audio/basic
+>12 belong 4 audio/basic
+>12 belong 5 audio/basic
+>12 belong 6 audio/basic
+>12 belong 7 audio/basic
+
+>12 belong 23 audio/x-adpcm
+
+# DEC systems (e.g. DECstation 5000) use a variant of the Sun/NeXT format
+# that uses little-endian encoding and has a different magic number
+# (0x0064732E in little-endian encoding).
+0 lelong 0x0064732E
+>12 lelong 1 audio/x-dec-basic
+>12 lelong 2 audio/x-dec-basic
+>12 lelong 3 audio/x-dec-basic
+>12 lelong 4 audio/x-dec-basic
+>12 lelong 5 audio/x-dec-basic
+>12 lelong 6 audio/x-dec-basic
+>12 lelong 7 audio/x-dec-basic
+# compressed (G.721 ADPCM)
+>12 lelong 23 audio/x-dec-adpcm
+
+# Bytes 0-3 of AIFF, AIFF-C, & 8SVX audio files are "FORM"
+# AIFF audio data
+8 string AIFF audio/x-aiff
+# AIFF-C audio data
+8 string AIFC audio/x-aiff
+# IFF/8SVX audio data
+8 string 8SVX audio/x-aiff
+
+# Creative Labs AUDIO stuff
+# Standard MIDI data
+0 string MThd audio/unknown
+#>9 byte >0 (format %d)
+#>11 byte >1 using %d channels
+# Creative Music (CMF) data
+0 string CTMF audio/unknown
+# SoundBlaster instrument data
+0 string SBI audio/unknown
+# Creative Labs voice data
+0 string Creative\ Voice\ File audio/unknown
+## is this next line right? it came this way...
+#>19 byte 0x1A
+#>23 byte >0 - version %d
+#>22 byte >0 \b.%d
+
+# [GRR 950115: is this also Creative Labs? Guessing that first line
+# should be string instead of unknown-endian long...]
+#0 long 0x4e54524b MultiTrack sound data
+#0 string NTRK MultiTrack sound data
+#>4 long x - version %ld
+
+# Microsoft WAVE format (*.wav)
+# [GRR 950115: probably all of the shorts and longs should be leshort/lelong]
+# Microsoft RIFF
+0 string RIFF audio/unknown
+# - WAVE format
+>8 string WAVE audio/x-wav
+# MPEG audio.
+0 beshort&0xfff0 0xfff0 audio/mpeg
+# C64 SID Music files, from Linus Walleij <triad@df.lth.se>
+0 string PSID audio/prs.sid
+
+#------------------------------------------------------------------------------
+# c-lang: file(1) magic for C programs or various scripts
+#
+
+# XPM icons (Greg Roelofs, newt@uchicago.edu)
+# ideally should go into "images", but entries below would tag XPM as C source
+0 string /*\ XPM image/x-xbm 7bit
+
+# this first will upset you if you're a PL/1 shop... (are there any left?)
+# in which case rm it; ascmagic will catch real C programs
+# C or REXX program text
+0 string /* text/plain
+# C++ program text
+0 string // text/plain
+
+#------------------------------------------------------------------------------
+# compress: file(1) magic for pure-compression formats (no archives)
+#
+# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, whap, etc.
+#
+# Formats for various forms of compressed data
+# Formats for "compress" proper have been moved into "compress.c",
+# because it tries to uncompress it to figure out what's inside.
+
+# standard unix compress
+0 string \037\235 application/octet-stream x-compress
+
+# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver)
+0 string \037\213 application/octet-stream x-gzip
+
+# According to gzip.h, this is the correct byte order for packed data.
+0 string \037\036 application/octet-stream
+#
+# This magic number is byte-order-independent.
+#
+0 short 017437 application/octet-stream
+
+# XXX - why *two* entries for "compacted data", one of which is
+# byte-order independent, and one of which is byte-order dependent?
+#
+# compacted data
+0 short 0x1fff application/octet-stream
+0 string \377\037 application/octet-stream
+# huf output
+0 short 0145405 application/octet-stream
+
+# Squeeze and Crunch...
+# These numbers were gleaned from the Unix versions of the programs to
+# handle these formats. Note that I can only uncrunch, not crunch, and
+# I didn't have a crunched file handy, so the crunch number is untested.
+# Keith Waclena <keith@cerberus.uchicago.edu>
+#0 leshort 0x76FF squeezed data (CP/M, DOS)
+#0 leshort 0x76FE crunched data (CP/M, DOS)
+
+# Freeze
+#0 string \037\237 Frozen file 2.1
+#0 string \037\236 Frozen file 1.0 (or gzip 0.5)
+
+# lzh?
+#0 string \037\240 LZH compressed data
+
+#------------------------------------------------------------------------------
+# frame: file(1) magic for FrameMaker files
+#
+# This stuff came on a FrameMaker demo tape, most of which is
+# copyright, but this file is "published" as witness the following:
+#
+0 string \<MakerFile application/x-frame
+0 string \<MIFFile application/x-frame
+0 string \<MakerDictionary application/x-frame
+0 string \<MakerScreenFon application/x-frame
+0 string \<MML application/x-frame
+0 string \<Book application/x-frame
+0 string \<Maker application/x-frame
+
+#------------------------------------------------------------------------------
+# html: file(1) magic for HTML (HyperText Markup Language) docs
+#
+# from Daniel Quinlan <quinlan@yggdrasil.com>
+# and Anna Shergold <anna@inext.co.uk>
+#
+0 string \<!DOCTYPE\ HTML text/html
+0 string \<!doctype\ html text/html
+0 string \<HEAD text/html
+0 string \<head text/html
+0 string \<TITLE text/html
+0 string \<title text/html
+0 string \<html text/html
+0 string \<HTML text/html
+0 string \<!-- text/html
+0 string \<h1 text/html
+0 string \<H1 text/html
+
+# XML eXtensible Markup Language, from Linus Walleij <triad@df.lth.se>
+0 string \<?xml text/xml
+
+#------------------------------------------------------------------------------
+# images: file(1) magic for image formats (see also "c-lang" for XPM bitmaps)
+#
+# originally from jef@helios.ee.lbl.gov (Jef Poskanzer),
+# additions by janl@ifi.uio.no as well as others. Jan also suggested
+# merging several one- and two-line files into here.
+#
+# XXX - byte order for GIF and TIFF fields?
+# [GRR: TIFF allows both byte orders; GIF is probably little-endian]
+#
+
+# [GRR: what the hell is this doing in here?]
+#0 string xbtoa btoa'd file
+
+# PBMPLUS
+# PBM file
+0 string P1 image/x-portable-bitmap 7bit
+# PGM file
+0 string P2 image/x-portable-greymap 7bit
+# PPM file
+0 string P3 image/x-portable-pixmap 7bit
+# PBM "rawbits" file
+0 string P4 image/x-portable-bitmap
+# PGM "rawbits" file
+0 string P5 image/x-portable-greymap
+# PPM "rawbits" file
+0 string P6 image/x-portable-pixmap
+
+# NIFF (Navy Interchange File Format, a modification of TIFF)
+# [GRR: this *must* go before TIFF]
+0 string IIN1 image/x-niff
+
+# TIFF and friends
+# TIFF file, big-endian
+0 string MM image/tiff
+# TIFF file, little-endian
+0 string II image/tiff
+
+# possible GIF replacements; none yet released!
+# (Greg Roelofs, newt@uchicago.edu)
+#
+# GRR 950115: this was mine ("Zip GIF"):
+# ZIF image (GIF+deflate alpha)
+0 string GIF94z image/unknown
+#
+# GRR 950115: this is Jeremy Wohl's Free Graphics Format (better):
+# FGF image (GIF+deflate beta)
+0 string FGF95a image/unknown
+#
+# GRR 950115: this is Thomas Boutell's Portable Bitmap Format proposal
+# (best; not yet implemented):
+# PBF image (deflate compression)
+0 string PBF image/unknown
+
+# GIF
+0 string GIF image/gif
+
+# JPEG images
+0 beshort 0xffd8 image/jpeg
+
+# PC bitmaps (OS/2, Windoze BMP files) (Greg Roelofs, newt@uchicago.edu)
+0 string BM image/bmp
+#>14 byte 12 (OS/2 1.x format)
+#>14 byte 64 (OS/2 2.x format)
+#>14 byte 40 (Windows 3.x format)
+#0 string IC icon
+#0 string PI pointer
+#0 string CI color icon
+#0 string CP color pointer
+#0 string BA bitmap array
+
+0 string \x89PNG image/png
+0 string FWS application/x-shockwave-flash
+0 string CWS application/x-shockwave-flash
+
+#------------------------------------------------------------------------------
+# lisp: file(1) magic for lisp programs
+#
+# various lisp types, from Daniel Quinlan (quinlan@yggdrasil.com)
+0 string ;; text/plain 8bit
+# Emacs 18 - this is always correct, but not very magical.
+0 string \012( application/x-elc
+# Emacs 19
+0 string ;ELC\023\000\000\000 application/x-elc
+
+#------------------------------------------------------------------------------
+# mail.news: file(1) magic for mail and news
+#
+# There are tests to ascmagic.c to cope with mail and news.
+0 string Relay-Version: message/rfc822 7bit
+0 string #!\ rnews message/rfc822 7bit
+0 string N#!\ rnews message/rfc822 7bit
+0 string Forward\ to message/rfc822 7bit
+0 string Pipe\ to message/rfc822 7bit
+0 string Return-Path: message/rfc822 7bit
+0 string Path: message/news 8bit
+0 string Xref: message/news 8bit
+0 string From: message/rfc822 7bit
+0 string Article message/news 8bit
+#------------------------------------------------------------------------------
+# msword: file(1) magic for MS Word files
+#
+# Contributor claims:
+# Reversed-engineered MS Word magic numbers
+#
+
+0 string \376\067\0\043 application/msword
+0 string \333\245-\0\0\0 application/msword
+
+# disable this one because it applies also to other
+# Office/OLE documents for which msword is not correct. See PR#2608.
+#0 string \320\317\021\340\241\261 application/msword
+
+
+
+#------------------------------------------------------------------------------
+# printer: file(1) magic for printer-formatted files
+#
+
+# PostScript
+0 string %! application/postscript
+0 string \004%! application/postscript
+
+# Acrobat
+# (due to clamen@cs.cmu.edu)
+0 string %PDF- application/pdf
+
+#------------------------------------------------------------------------------
+# sc: file(1) magic for "sc" spreadsheet
+#
+38 string Spreadsheet application/x-sc
+
+#------------------------------------------------------------------------------
+# tex: file(1) magic for TeX files
+#
+# XXX - needs byte-endian stuff (big-endian and little-endian DVI?)
+#
+# From <conklin@talisman.kaleida.com>
+
+# Although we may know the offset of certain text fields in TeX DVI
+# and font files, we can't use them reliably because they are not
+# zero terminated. [but we do anyway, christos]
+0 string \367\002 application/x-dvi
+#0 string \367\203 TeX generic font data
+#0 string \367\131 TeX packed font data
+#0 string \367\312 TeX virtual font data
+#0 string This\ is\ TeX, TeX transcript text
+#0 string This\ is\ METAFONT, METAFONT transcript text
+
+# There is no way to detect TeX Font Metric (*.tfm) files without
+# breaking them apart and reading the data. The following patterns
+# match most *.tfm files generated by METAFONT or afm2tfm.
+#2 string \000\021 TeX font metric data
+#2 string \000\022 TeX font metric data
+#>34 string >\0 (%s)
+
+# Texinfo and GNU Info, from Daniel Quinlan (quinlan@yggdrasil.com)
+#0 string \\input\ texinfo Texinfo source text
+#0 string This\ is\ Info\ file GNU Info text
+
+# correct TeX magic for Linux (and maybe more)
+# from Peter Tobias (tobias@server.et-inf.fho-emden.de)
+#
+0 leshort 0x02f7 application/x-dvi
+
+# RTF - Rich Text Format
+0 string {\\rtf application/rtf
+
+#------------------------------------------------------------------------------
+# animation: file(1) magic for animation/movie formats
+#
+# animation formats, originally from vax@ccwf.cc.utexas.edu (VaX#n8)
+# MPEG file
+0 string \000\000\001\263 video/mpeg
+#
+# The contributor claims:
+# I couldn't find a real magic number for these, however, this
+# -appears- to work. Note that it might catch other files, too,
+# so BE CAREFUL!
+#
+# Note that title and author appear in the two 20-byte chunks
+# at decimal offsets 2 and 22, respectively, but they are XOR'ed with
+# 255 (hex FF)! DL format SUCKS BIG ROCKS.
+#
+# DL file version 1 , medium format (160x100, 4 images/screen)
+0 byte 1 video/unknown
+0 byte 2 video/unknown
+# Quicktime video, from Linus Walleij <triad@df.lth.se>
+# from Apple quicktime file format documentation.
+4 string moov video/quicktime
+4 string mdat video/quicktime
+
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/logs b/setup/projects/katrin/files/etc/apache2-kaas/logs
new file mode 120000
index 0000000..2a478fd
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/logs
@@ -0,0 +1 @@
+/var/log/httpd24 \ No newline at end of file
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/modules b/setup/projects/katrin/files/etc/apache2-kaas/modules
new file mode 120000
index 0000000..a4c456b
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/modules
@@ -0,0 +1 @@
+/opt/rh/httpd24/root/usr/lib64/httpd/modules \ No newline at end of file
diff --git a/setup/projects/katrin/files/etc/apache2-kaas/run b/setup/projects/katrin/files/etc/apache2-kaas/run
new file mode 120000
index 0000000..c1a28cf
--- /dev/null
+++ b/setup/projects/katrin/files/etc/apache2-kaas/run
@@ -0,0 +1 @@
+/opt/rh/httpd24/root/var/run/httpd \ No newline at end of file
diff --git a/setup/projects/katrin/files/www/kaas/index.html b/setup/projects/katrin/files/www/kaas/index.html
new file mode 100644
index 0000000..906ee19
--- /dev/null
+++ b/setup/projects/katrin/files/www/kaas/index.html
@@ -0,0 +1 @@
+<html><body>KAAS</body></html>
diff --git a/setup/projects/katrin/keys/kaas.crt b/setup/projects/katrin/keys/kaas.crt
new file mode 100644
index 0000000..82ef723
--- /dev/null
+++ b/setup/projects/katrin/keys/kaas.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAoGgAwIBAgIJAOnpyunJRkjVMA0GCSqGSIb3DQEBBQUAMGMxCzAJBgNV
+BAYTAkRFMQswCQYDVQQIDAJCVzESMBAGA1UEBwwJS2FybHNydWhlMQwwCgYDVQQK
+DANLSVQxDDAKBgNVBAsMA0lQRTEXMBUGA1UEAwwOa2F0cmluLmtpdC5lZHUwHhcN
+MTQxMjE5MDEwMTEyWhcNMjQxMjE2MDEwMTEyWjBjMQswCQYDVQQGEwJERTELMAkG
+A1UECAwCQlcxEjAQBgNVBAcMCUthcmxzcnVoZTEMMAoGA1UECgwDS0lUMQwwCgYD
+VQQLDANJUEUxFzAVBgNVBAMMDmthdHJpbi5raXQuZWR1MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAyJ9+nKbhK4AaVyVH/jmAxPFC/o2shejmFL9jIE4I
+ryrdnirepxcgvd2xcpTYeOb5TMKKFtJmqeW3jPOB3jAEyLzvuy1aYwd/DNx4A9VU
+GO2shdqjPMaBOk4KjsjZnt+8toWJeABYsJ4nATpbM0ijkX6RqQoRboiaKWlvo10n
+qMfGmQjMR+lC5uhF5hWhHwD+qPigEFGYis73dgFDhydfl4pzPXBySv4hM4zHvHHH
+DO0QipGIxwmMrw4U/y4snN1hDCPFDJN3WehK4lt7tD8Ea1VwikCLh2eZ+v94BQC3
+060hHIC4lEhtTaDsNXrGIwzqVP9TPuOVEOgEAjxyN12D0wIDAQABo1AwTjAdBgNV
+HQ4EFgQUGTmlNR3S73QucufU1P+8TehunFQwHwYDVR0jBBgwFoAUGTmlNR3S73Qu
+cufU1P+8TehunFQwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAfwuL
+ayz7Mg1YzX3RUISmN0rJYFS9u57qaWkGK5LX5s/6T9Ppzjd3sPcFwryycumcNJ3x
+G9iIuTX1n1/uPdwdulgGRtsq3vl1zLgI/at0UIZJxnQPxr73n8o5o9W5FFVRsJTs
+WN2t7DurOQi0nLiIG+qmHHrRmFpSsgeegM720VCS9Wf434r0XZVMNl1ngIk4ppo6
+/ecuRTxpv+iOM4j/QqFwXNZQwjGv3o1UZELJ9RMDVY7zGyL/77cu6Iz6aLVy3QrE
+qMexD5/zZTnrKc4dWmuQSDqgMJeLdyebxZnYT8LLLr/QtUMmm1iLCw1MuY4tmPIp
+j5rXZ3Oda5tHYrnPsA==
+-----END CERTIFICATE-----
diff --git a/setup/projects/katrin/keys/kaas.key b/setup/projects/katrin/keys/kaas.key
new file mode 100644
index 0000000..3d766c8
--- /dev/null
+++ b/setup/projects/katrin/keys/kaas.key
@@ -0,0 +1,90 @@
+$ANSIBLE_VAULT;1.1;AES256
+38323634333239303134316164343132636432356331393634343164663065353733323732656339
+6363343738363234626565343665326365343366363166370a623263626134646332393231656566
+37366136353864366562633832316338353233653930333430383235643337623433393464613765
+3734626432316164300a656139383462653761306435346433346637616565393132396137376661
+64643835393132633831386638613764613164663036356233663861653138613465663434643161
+36333666323862636665396261333532313833393038326339343136363239356235313463333661
+61316664366437333064336531333538333734356238323561626163313031383833613233386438
+64616337323230626463643535393831666363373864393432633539323732393266356232636663
+63303263393337643831376537386666373737656364663162663164353961323264373462366636
+38346163396139636131323134613337613164623533353163616539643333623264336434333662
+33386538646239336639303230653335626434633131336135393831656666326130383034656664
+65313766623466663138333062343061393532353630363532656139373939643362613265626461
+31666166393433646135353936373836636435613432646435643264653338306532656361316537
+62316164393638356635633931316537326262343561663165643837396365653461356432666433
+32326262336164376663343363353134373563653933616531653936333265383762613534363832
+36393765383032383762383961623462306334323463353739663362363336343130633935383064
+35396531343032656335623239373565376633313665313132656162626535656133633063396131
+31333936623738653435633562623061393961343736323539373464303735376266353232393639
+61353661663934313333363935346164316664616632396434353436646437313861303763326430
+34363335653564373963376162393836353234306534306334666263633261366434663265333134
+63633431303530616637633731366539613538313839653864336436633230303730653935366661
+62303765383834663230303334373865346630643739363336366537343465346361313530643436
+35653533313565663638363432656239366261316261613437353933643365623766353838386430
+39386539636332373732356334656365646362336539623934353337623264663866323866323966
+62633932316136623866393461333866396333373934333461323533323866303533333737366261
+33383131303932663231646238343661363565613466333463303262343831653839323162613134
+64633465343932643465653934646533366266656437616337643537383932623238633230346462
+39396263393431663631383931303063666539336432663730623338366439343739316539663364
+38626233333561313836616634306437653662323265633832343632336633396634326364323531
+38633836343063653037623666396534303032366136333737663562633763323831663265343466
+65643361643436613533386139336238633032616235363035396532646637383338383639393861
+65346661616534313764313738363131336235333662353735333466656635393233336332616435
+39326338323436646337313935373535396165386338626563363863633139353038373434613466
+35613565313734346361643664366533666663396664326164396534303638333831666631323063
+33343032636331643464633237363561653236656663346232663465663936633335643765666435
+62306536313464363333656437313264323065663436373464356338623264313464623937313934
+32623234393163653732376663333263633031626335353033613937393661336338383463626534
+30373261663732373535643831626565666136336666396130636434373034316132353238656234
+37646133383164356566306665393432376561383435653463363239343136303133373433346231
+38623833643863633433306466376639633066623733333435316233326539303239666232616264
+62306436613931303032653734633737613066653235623930386261626565643436653632336639
+36313066663933366562366236633965323534336361646131383432393634646564306532656162
+39303430643534333338663962346266663532623064303133366662313661626139373236636664
+63326435623838613039386134303663323439373639616634633266353334653737666434383037
+34306638306264393434653630373661373564613935303766363039666333303161373533316134
+36343632626265306239656361383939353736343139373437373162303437623236666137633666
+62626364353164373237306330313464623363643466343439653465353938663831323634363634
+37386635396261306366376630326534613337356235613863313632326435356461353730343339
+34393636316333373435326236363238656332616333393663653465326434396262313466336365
+38336635363762313530616666666335653865376363623965333064366462373030333735333630
+62653965666630613061646265376130626263313032323038626430383233666563646639373339
+30313032393237623634666464383635396431393866303530383235633265313161383563363532
+66336261336638616335356262303436633765363336616535633734313037383136313635313366
+33303963383135343064613637353432666461353661643834376666386633663964663565386465
+39616634343835323362613362376662326463633139653163313437636238386430623234663936
+63623566393434303937343461366361363661653364626265366630333036623735323435306332
+35666265383130313438353965353239343135663937613362323530323734626234633037326135
+32336266373734623534353239373238333333626537666433636261653333626137653335656331
+30326563666664316537316633643661626239366536333134376662643735386634396430633132
+39636266656131363063343731643366376664623062656262396235663636386564346364373533
+63633961656539386630643639383162303661656134363334373166303233346263646335393535
+37373131633834316239326265326266386230383430653564663138636334323736313363303561
+32353932366637316433333538353032396339366538636261613963613865396231646437313339
+63376635656466346165626361336161333638366166356431336361343761613431303161626462
+36613266393633643333386238656161393337326637353464646264356139326466353763393465
+33383564323333313861336565323762386539303737306362613930646330653636396466303238
+38636365343234663436363334303439666366366462633537393362623133376430616136376235
+33616561353764643236636633633561633230303338613136343537353236316666376537393836
+35383336626662353562383034653532303663613033316534623832333633633737613266343665
+34393235623231336533613331643566303237623238663762393331373636623065643666393137
+61383264356564663165326266626263303363376634303238323861633533396137666163343162
+64636633333033373138313133346539333634373265396231653665323062396432383435393864
+32633763646230343639646637626434353336346265643439653863366335363935343934623334
+32636534366435383863353065393731613361343336633364303061303432366230393431393939
+33666632656135343263373934326262643936383337343137353434633434636535623835346439
+30653437376538373961306439343966343039303262396339343866313937383231616465336332
+64663434643466336665376462356561353266313730336435623832643230376434636536356163
+34613964343132356233623966316462643737613234373466643164353133303837653237306536
+62616661373466383232353861653734363562343337343333353763656562616535373536306461
+66303131616163623835363366653737643933383938383735353635646234613064316533346330
+63633732326434653939323534366637333932313637326536316430326338666263343163363735
+35333435353238396236316132393838663430313137346362313865386135646234346530346261
+63373062303637336662373763393239646133633933613066643263326130396134343332633464
+32613061383665666266353264653732663765353832656364396235313339626565656133653735
+63663230316533666462396436396465363333363862356330656565633466363439363338383339
+37386462623035393931313938653064376239393863643831633431333633373938363132333030
+61623539636430316431616162383963663061353164313735306365353965336233663239656336
+30346531383561356439323062333263646536646232643263353533653563653634633962343933
+36356164306132386530373437396263393461373036333938343763386664653462
diff --git a/setup/projects/katrin/templates/00-katrin-restricted.yml.j2.excl b/setup/projects/katrin/templates/00-katrin-restricted.yml.j2.excl
new file mode 100644
index 0000000..d155267
--- /dev/null
+++ b/setup/projects/katrin/templates/00-katrin-restricted.yml.j2.excl
@@ -0,0 +1,43 @@
+---
+allowHostDirVolumePlugin: false
+allowHostIPC: false
+allowHostNetwork: false
+allowHostPID: false
+allowHostPorts: false
+allowPrivilegedContainer: false
+allowedCapabilities: null
+apiVersion: v1
+defaultAddCapabilities: null
+fsGroup:
+ type: MustRunAs
+groups:
+- system:authenticated
+kind: SecurityContextConstraints
+metadata:
+ annotations:
+ kubernetes.io/description: restricted denies access to all host features and requires
+ pods to be run with a UID, and SELinux context that are allocated to the namespace. This
+ is the most restrictive SCC.
+ creationTimestamp: null
+ name: katrin-restricted
+priority: null
+readOnlyRootFilesystem: false
+requiredDropCapabilities:
+- KILL
+- MKNOD
+- SYS_CHROOT
+- SETUID
+- SETGID
+runAsUser:
+ type: MustRunAsRange
+seLinuxContext:
+ type: MustRunAs
+supplementalGroups:
+ type: RunAsAny
+volumes:
+- glusterfs
+- configMap
+- downwardAPI
+- emptyDir
+- persistentVolumeClaim
+- secret
diff --git a/setup/projects/katrin/templates/katrin.yml.j2.bk b/setup/projects/katrin/templates/katrin.yml.j2.bk
new file mode 100644
index 0000000..5d032b3
--- /dev/null
+++ b/setup/projects/katrin/templates/katrin.yml.j2.bk
@@ -0,0 +1,135 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: kaas
+ annotations:
+ descriptions: "KATRIN Routing Service"
+objects:
+ - apiVersion: v1
+ kind: Service
+ metadata:
+ name: kaas
+ spec:
+ selector:
+ name: kaas
+ ports:
+ - name: http
+ port: 80
+ targetPort: 8080
+ - name: https
+ port: 443
+ targetPort: 8443
+ - apiVersion: v1
+ kind: Route
+ metadata:
+ name: kaas
+ spec:
+ host: {{ kaas_project_config.katrin_node }}
+ to:
+ kind: Service
+ name: kaas
+ port:
+ targetPort: http
+ tls:
+ termination: edge
+ insecureEdgeTerminationPolicy: Allow
+ certificate: |-
+ -----BEGIN CERTIFICATE-----
+ MIIDmTCCAoGgAwIBAgIJAOnpyunJRkjVMA0GCSqGSIb3DQEBBQUAMGMxCzAJBgNV
+ BAYTAkRFMQswCQYDVQQIDAJCVzESMBAGA1UEBwwJS2FybHNydWhlMQwwCgYDVQQK
+ DANLSVQxDDAKBgNVBAsMA0lQRTEXMBUGA1UEAwwOa2F0cmluLmtpdC5lZHUwHhcN
+ MTQxMjE5MDEwMTEyWhcNMjQxMjE2MDEwMTEyWjBjMQswCQYDVQQGEwJERTELMAkG
+ A1UECAwCQlcxEjAQBgNVBAcMCUthcmxzcnVoZTEMMAoGA1UECgwDS0lUMQwwCgYD
+ VQQLDANJUEUxFzAVBgNVBAMMDmthdHJpbi5raXQuZWR1MIIBIjANBgkqhkiG9w0B
+ AQEFAAOCAQ8AMIIBCgKCAQEAyJ9+nKbhK4AaVyVH/jmAxPFC/o2shejmFL9jIE4I
+ ryrdnirepxcgvd2xcpTYeOb5TMKKFtJmqeW3jPOB3jAEyLzvuy1aYwd/DNx4A9VU
+ GO2shdqjPMaBOk4KjsjZnt+8toWJeABYsJ4nATpbM0ijkX6RqQoRboiaKWlvo10n
+ qMfGmQjMR+lC5uhF5hWhHwD+qPigEFGYis73dgFDhydfl4pzPXBySv4hM4zHvHHH
+ DO0QipGIxwmMrw4U/y4snN1hDCPFDJN3WehK4lt7tD8Ea1VwikCLh2eZ+v94BQC3
+ 060hHIC4lEhtTaDsNXrGIwzqVP9TPuOVEOgEAjxyN12D0wIDAQABo1AwTjAdBgNV
+ HQ4EFgQUGTmlNR3S73QucufU1P+8TehunFQwHwYDVR0jBBgwFoAUGTmlNR3S73Qu
+ cufU1P+8TehunFQwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAfwuL
+ ayz7Mg1YzX3RUISmN0rJYFS9u57qaWkGK5LX5s/6T9Ppzjd3sPcFwryycumcNJ3x
+ G9iIuTX1n1/uPdwdulgGRtsq3vl1zLgI/at0UIZJxnQPxr73n8o5o9W5FFVRsJTs
+ WN2t7DurOQi0nLiIG+qmHHrRmFpSsgeegM720VCS9Wf434r0XZVMNl1ngIk4ppo6
+ /ecuRTxpv+iOM4j/QqFwXNZQwjGv3o1UZELJ9RMDVY7zGyL/77cu6Iz6aLVy3QrE
+ qMexD5/zZTnrKc4dWmuQSDqgMJeLdyebxZnYT8LLLr/QtUMmm1iLCw1MuY4tmPIp
+ j5rXZ3Oda5tHYrnPsA==
+ -----END CERTIFICATE-----
+ key: |-
+ -----BEGIN PRIVATE KEY-----
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIn36cpuErgBpX
+ JUf+OYDE8UL+jayF6OYUv2MgTgivKt2eKt6nFyC93bFylNh45vlMwooW0map5beM
+ 84HeMATIvO+7LVpjB38M3HgD1VQY7ayF2qM8xoE6TgqOyNme37y2hYl4AFiwnicB
+ OlszSKORfpGpChFuiJopaW+jXSeox8aZCMxH6ULm6EXmFaEfAP6o+KAQUZiKzvd2
+ AUOHJ1+XinM9cHJK/iEzjMe8cccM7RCKkYjHCYyvDhT/Liyc3WEMI8UMk3dZ6Eri
+ W3u0PwRrVXCKQIuHZ5n6/3gFALfTrSEcgLiUSG1NoOw1esYjDOpU/1M+45UQ6AQC
+ PHI3XYPTAgMBAAECggEAFFXubIyR2Gn0wY6a3I8RmWTnKIxNx4kTAVlg/95JDRBo
+ RGcOCJvUispU+UtTIfYvoPM7MhMDqwcI8vWf3Vi6s2pLVorDVbRl0XTriV/vVVOK
+ IEtILpnkcXeFpHGBdZQyOcIRbCOE2eo+A+bZZbpgMhhFRYAqwiyAi+APG90ObxIb
+ AqTEeTyztqyrKfnTdr50owL2KT7adS6XuSUNX681IJc+szbQ7piXN57Kdxd2PydM
+ JnSZAOBpQHkbiOEDUseeDjYRT23loeMIS7nWTwo1Y1LwsEKL5S7C0fKBfZV9xARw
+ TntGuM87HzbAk4535We8qW3t/5EqpzurgK7u9/PEEQKBgQDjy8CjDdobGK9+VUDg
+ iHbANbzEB4LrpVJiE+esr0iLXOoMdfTPwpd4XpbPPOjx/A9+6VfpdGt1EdZwLMpy
+ qryPW0iumsri3iPSVBS79mN6WmwYhNOcOTWlmbs4pEhubht9aNBi7rZ7QZgV3PLN
+ 7YBZHzxfyxTcIBCAzzoF7zaUeQKBgQDhdneOijWAYx0AMKTBzJw52KO/gloTDl9M
+ mOhvUIuYxkUE/mDE5EqI6k9VkbAqUvlD3z2S7yNY+h2hldO+u3w8GPo+bTCMyNDB
+ 0tQGCZnbKl8mfmItUlTyJ/MmNbanmYI2VmhDTMh6S8d8qKW9txXfDEXrzY2p7z/X
+ gRF3Ow9PqwKBgGw7CMHv+Ora5bbehr6n19QnNBLnhrqzh9r1niOb/JnKgaF+Ad0c
+ lZ8pQfog9ITUwAAKmixflha/bOVLQr0Mhh6Ovo/HGBKGfPqX3GoZ/NXLVISpx2j4
+ fZa63gthctCVHBaP0ELRLH6PgdURb4OMDmlJwAO7l6Om0HCDBQyAxavxAoGAZPUJ
+ QBh/MIgxGj6t5+HZKsXpPP3/m3zaC5CEtCOa/sP5b+0AI+odvgU9lRFxkuIon828
+ 4qiWaWdGEW7nrAaD8N02YPG/xaq+X6wqKLHv5QWqKbB6AdVWGEDvTfLLYW0Js48p
+ jMk7FBgOsbFK1hK/hmsWfCpE/w0Ux0kSKxOVHZUCgYEA41rhW18+KdxJyQTZaQRV
+ 0KQr8/30L116XYYTYrkILa6504nXMr7xSHuMxaPNl20b/sBz8a8VuKJt2CLZQ0Q3
+ oW3GAG2Fk+mvrauLriiJ2KgZkS5IJweJKHbIk1GQrucNArNojk9unrqN8wpa3Ywo
+ 9GafqnfUGu+FVd1CKolicSA=
+ -----END PRIVATE KEY-----
+ - apiVersion: v1
+ kind: DeploymentConfig
+ metadata:
+ name: kaas
+ spec:
+ replicas: 1
+ selector:
+ name: kaas
+ template:
+ metadata:
+ name: kaas
+ labels:
+ name: kaas
+ strategy:
+ type: Rolling
+ triggers:
+ - type: ConfigChange
+ spec:
+ nodeSelector:
+ master: "1"
+ containers:
+ - name: kaas
+ image: centos/httpd-24-centos7
+ imagePullPolicy: Always
+ ports:
+ - containerPort: 8080
+ - containerPort: 8443
+ volumeMounts:
+ - name: config
+ subPath: etc/apache2-kaas
+ mountPath: /etc/httpd
+ - name: config
+ subPath: log/apache2-kaas
+ mountPath: /var/log/httpd24
+ - name: config
+ subPath: htdocs/kaas
+ mountPath: /opt/rh/httpd24/root/var/www/html
+ livenessProbe:
+ timeoutSeconds: 1
+ initialDelaySeconds: 3
+ httpGet:
+ path: /index.html
+ port: 8080
+ volumes:
+ - name: config
+ persistentVolumeClaim:
+ claimName: openshift
diff --git a/setup/projects/katrin/vars/globals.yml b/setup/projects/katrin/vars/globals.yml
new file mode 100644
index 0000000..50776ff
--- /dev/null
+++ b/setup/projects/katrin/vars/globals.yml
@@ -0,0 +1,2 @@
+#katrin_node: katrin.kit.edu
+katrin_node: "katrin.{{ openshift_master_default_subdomain }}"
diff --git a/setup/projects/katrin/vars/katrin.yml b/setup/projects/katrin/vars/katrin.yml
new file mode 100644
index 0000000..c825654
--- /dev/null
+++ b/setup/projects/katrin/vars/katrin.yml
@@ -0,0 +1,7 @@
+#katrin_openshift_volumes:
+#adei_openshift_volumes:
+
+#volumes: "{{ ands_openshift_volumes | combine (katrin_openshift_volumes, adei_openshift_volumes) }}"
+#files: "{{ ands_openshift_files | union([]) }}"
+#file_owner: katrin
+#file_group: katrin \ No newline at end of file
diff --git a/setup/projects/katrin/vars/pods.yml b/setup/projects/katrin/vars/pods.yml
new file mode 100644
index 0000000..3bfcfd7
--- /dev/null
+++ b/setup/projects/katrin/vars/pods.yml
@@ -0,0 +1,22 @@
+# First port is exposed
+pods:
+ kaas:
+ service: { host: "{{ katrin_node }}", ports: [ 80/8080, 443/8043 ] }
+ sched: { replicas: 1, selector: { master: 1 } }
+ selector: { master: 1 }
+ images:
+ - image: "centos/httpd-24-centos7"
+ mappings:
+ - { name: "etc", path: "apache2-kaas", mount: "/etc/httpd24" }
+ - { name: "www", path: "kaas", mount: "/opt/rh/httpd24/root/var/www/html" }
+ - { name: "log", path: "apache2-kaas", mount: "/var/log/httpd24" }
+ probes:
+ - { port: 8080, path: '/index.html' }
+
+#oc:
+# - template: "[0-3]*"
+# - template: "[4-6]*"
+# - resource: "route/apache"
+# oc: "expose svc/kaas --name apache --hostname=apache.{{ openshift_master_default_subdomain }}"
+# - template: "*"
+ \ No newline at end of file
diff --git a/setup/users/htpasswd b/setup/users/htpasswd
new file mode 100644
index 0000000..cf0d67e
--- /dev/null
+++ b/setup/users/htpasswd
@@ -0,0 +1,3 @@
+pdv:$apr1$ACvj6uUa$Nm1Vq8hZq3RzTtaYpAHv01
+csa:$apr1$IqEwdnzy$UAdd8ZSFnXommBbj29w3c0
+katrin:$apr1$/hxgbxC4$/MxeHtIYvAJcIQFR5Jz0E0
diff --git a/setup/users/users.yml b/setup/users/users.yml
new file mode 120000
index 0000000..b201d8a
--- /dev/null
+++ b/setup/users/users.yml
@@ -0,0 +1 @@
+../configs/openshift.yml \ No newline at end of file
diff --git a/vm/vagrant-router/Vagrantfile b/vm/vagrant-router/Vagrantfile
new file mode 100644
index 0000000..6e39ae0
--- /dev/null
+++ b/vm/vagrant-router/Vagrantfile
@@ -0,0 +1,35 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure("2") do |config|
+ config.vm.define "ipekatrinrouter" do |node|
+ node.vm.box = "centos/7"
+ node.vm.hostname = "ipekatrinrouter"
+ node.vm.network "public_network", bridge: "br0", ip: "141.52.64.15", netmask: "255.255.254.0"
+ node.vm.network "public_network", bridge: "br0", ip: "141.52.64.17", netmask: "255.255.254.0"
+ node.vm.network "public_network", bridge: "br0", ip: "192.168.26.254"
+
+ node.vm.provision "shell", run: "always", inline: "( ip addr show | grep 64.15 ) || ifcfg eth1 141.52.64.15/23"
+ node.vm.provision "shell", run: "always", inline: "( ip addr show | grep 64.17 ) || ifcfg eth2 141.52.64.17/23"
+ node.vm.provision "shell", run: "always", inline: "( ip addr show | grep 192.168.26 ) || ifcfg eth3 192.168.26.254"
+ node.vm.provision "shell", run: "always", inline: "chmod +r /etc/sysconfig/network-scripts/ifcfg-eth*"
+ node.vm.provision "shell", run: "always", inline: "chcon --reference /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth*"
+
+ node.vm.provision "shell" do |s|
+ ssh_pub_key = File.readlines("/Image/My/Private/ssh/authorized_keys").first.strip
+ s.inline = <<-SHELL
+ mkdir -p /root/.ssh/
+ echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
+ SHELL
+ end
+
+ node.vm.provider "virtualbox" do |vb|
+ vb.memory = "1024"
+ vb.customize [
+ "modifyvm", :id,
+ "--audio", "none",
+ ]
+ end
+ end
+end
+
diff --git a/vm/vagrant-router/inventory.erb b/vm/vagrant-router/inventory.erb
new file mode 100644
index 0000000..c5a23d6
--- /dev/null
+++ b/vm/vagrant-router/inventory.erb
@@ -0,0 +1,2 @@
+[router]
+192.168.26.254
diff --git a/vm/vagrant-router/rebuild.sh b/vm/vagrant-router/rebuild.sh
new file mode 100755
index 0000000..cb6ed58
--- /dev/null
+++ b/vm/vagrant-router/rebuild.sh
@@ -0,0 +1,5 @@
+#vagrant destroy -f
+#vagrant up --parallel
+
+export ANSIBLE_HOST_KEY_CHECKING=False
+ansible-playbook -i inventory.erb ./router.yml
diff --git a/vm/vagrant-router/router.yml b/vm/vagrant-router/router.yml
new file mode 100644
index 0000000..68b914e
--- /dev/null
+++ b/vm/vagrant-router/router.yml
@@ -0,0 +1,16 @@
+ - name: Configure router
+ hosts: router
+ remote_user: root
+
+ tasks:
+ - name: IP Forwarding
+ sysctl: name="net.ipv4.ip_forward" value="1" sysctl_set="yes" reload="yes"
+
+ - name: DNAT / eth1
+ iptables: table="nat" chain="PREROUTING" in_interface="eth1" jump="DNAT" to_destination="192.168.26.1"
+
+ - name: DNAT / eth2
+ iptables: table="nat" chain="PREROUTING" in_interface="eth2" jump="DNAT" to_destination="192.168.26.1"
+
+ - name: SNAT
+ iptables: table="nat" chain="POSTROUTING" out_interface="eth3" jump="SNAT" to_source="192.168.26.254"