From f3c41dd13a0a86382b80d564e9de0d6b06fb1dbf Mon Sep 17 00:00:00 2001
From: "Suren A. Chilingaryan" <csa@suren.me>
Date: Sun, 11 Mar 2018 19:56:38 +0100
Subject: Various fixes before moving to hardware installation

---
 roles/ands_backup/defaults/main.yml           |  9 ++++
 roles/ands_backup/tasks/main.yml              | 29 +++++++++++
 roles/ands_backup/templates/backup.cron.j2    |  4 ++
 roles/ands_backup/templates/backup.sh.j2      | 72 +++++++++++++++++++++++++++
 roles/ands_common/README                      | 11 ++++
 roles/ands_common/default/main.yml            |  1 +
 roles/ands_common/tasks/main.yml              | 47 +++++++++++++++++
 roles/ands_facts/defaults/main.yml            |  8 ++-
 roles/ands_facts/tasks/main.yml               |  8 +--
 roles/ands_facts/tasks/network.yml            | 16 ++++--
 roles/ands_facts/tasks/storage.yml            |  8 +--
 roles/ands_kaas/templates/50-kaas-pods.yml.j2 | 16 +++---
 roles/ands_network/tasks/common.yml           | 21 +++-----
 roles/ands_network/tasks/ganesha.yml          | 12 +++++
 roles/ands_network/tasks/install_post.yml     |  2 +-
 roles/ands_network/tasks/maintain.yml         |  6 ++-
 roles/common/README                           | 11 ----
 roles/common/default/main.yml                 |  1 -
 roles/common/tasks/main.yml                   | 46 -----------------
 roles/docker/defaults/main.yml                |  3 ++
 roles/docker/tasks/main.yml                   | 16 +++++-
 roles/glusterfs/tasks/cfg/vols3.yml           |  1 +
 roles/glusterfs/tasks/data/vols2.yml          |  1 +
 roles/glusterfs/tasks/data/vols3.yml          |  1 +
 roles/glusterfs/tasks/db/vols3.yml            |  1 +
 roles/glusterfs/tasks/la/vols3.yml            |  1 +
 roles/ntp                                     |  1 +
 27 files changed, 257 insertions(+), 96 deletions(-)
 create mode 100644 roles/ands_backup/defaults/main.yml
 create mode 100644 roles/ands_backup/tasks/main.yml
 create mode 100644 roles/ands_backup/templates/backup.cron.j2
 create mode 100755 roles/ands_backup/templates/backup.sh.j2
 create mode 100644 roles/ands_common/README
 create mode 100644 roles/ands_common/default/main.yml
 create mode 100644 roles/ands_common/tasks/main.yml
 create mode 100644 roles/ands_network/tasks/ganesha.yml
 delete mode 100644 roles/common/README
 delete mode 100644 roles/common/default/main.yml
 delete mode 100644 roles/common/tasks/main.yml
 create mode 120000 roles/ntp

(limited to 'roles')

diff --git a/roles/ands_backup/defaults/main.yml b/roles/ands_backup/defaults/main.yml
new file mode 100644
index 0000000..33d1ff1
--- /dev/null
+++ b/roles/ands_backup/defaults/main.yml
@@ -0,0 +1,9 @@
+ands_script_path: "/opt/scripts"
+
+ands_backup_frequency: "17 */4 * * *"
+ands_backup_volume: "{{ ands_paths.provision }}"
+ands_backup_path: "{{ ands_backup_volume }}/backup"
+ands_backup_clean_minutes: "720"
+ands_borg_path: "{{ ands_backup_volume }}/borg"
+ands_borg_args: "-C zlib,6 -x"
+ands_borg_prune: "--keep-daily=7 --keep-weekly=4 --keep-monthly=6 --keep-within 1w"
diff --git a/roles/ands_backup/tasks/main.yml b/roles/ands_backup/tasks/main.yml
new file mode 100644
index 0000000..16a8ec3
--- /dev/null
+++ b/roles/ands_backup/tasks/main.yml
@@ -0,0 +1,29 @@
+- name: Install required packages
+  package: name={{item}} state=present
+  with_items:
+    - borgbackup
+    - heketi-client
+
+- name: Create scripts directory
+  file: path="{{ ands_script_path }}" state=directory
+
+- name: Populate backup script
+  template: src=backup.sh.j2 dest="{{ ands_script_path }}/ands_backup.sh" owner=root group=root mode=0755
+
+- name: Populate cron job
+  template: src=backup.cron.j2 dest="/etc/cron.d/9ands_backup" owner=root group=root mode=0644
+
+
+- name: Check if backup volume is mounted
+  command: mountpoint -q "{{ ands_backup_volume }}"
+
+
+- block:
+  - name: Check if borg is already initialized
+    stat: path="{{ ands_borg_path }}/config"
+    register: borg_stat_res
+
+  - name: Initialize borg repository
+    shell: "borg init {{ ands_borg_path }} --encryption=none"
+    when: not borg_stat_res.stat.exists
+  run_once: true
diff --git a/roles/ands_backup/templates/backup.cron.j2 b/roles/ands_backup/templates/backup.cron.j2
new file mode 100644
index 0000000..5c017b8
--- /dev/null
+++ b/roles/ands_backup/templates/backup.cron.j2
@@ -0,0 +1,4 @@
+SHELL=/bin/bash
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+MAILTO=root
+{{ ands_backup_frequency }} root /bin/bash {{ ands_script_path }}/ands_backup.sh
diff --git a/roles/ands_backup/templates/backup.sh.j2 b/roles/ands_backup/templates/backup.sh.j2
new file mode 100755
index 0000000..74fff85
--- /dev/null
+++ b/roles/ands_backup/templates/backup.sh.j2
@@ -0,0 +1,72 @@
+#! /bin/bash
+
+date=$(date -u "+%Y%m%d_%H%M%S")
+hostname=$(hostname)
+
+volume_path="{{ ands_backup_volume }}"
+host_path="{{ ands_backup_path }}/${hostname}"
+backup_path="${host_path}/${date}"
+borg_path="{{ ands_borg_path }}"
+
+borg_args="{{ ands_borg_args }}"
+borg_prune_args="{{ ands_borg_prune }}"
+
+etcdctl3 () { 
+    ETCDCTL_API=3 /usr/bin/etcdctl --cert /etc/etcd/peer.crt --key /etc/etcd/peer.key --cacert /etc/etcd/ca.crt --endpoints "https://${hostname}:2379" ${@}
+}
+
+
+check=$(df | awk '{ print $6 }' | grep -P "^${volume_path}$")
+[ $? -ne 0 -o -z "$check" ] && { echo "The volume $volume_path is not mounted. Skipping..." ; exit 1 ; }
+
+[ -d "$backup_path" ] && { echo "Something wrong, path $backup_path already exists..." ; exit 1 ; }
+
+# Check the provision volume is mounted
+mkdir -p "$backup_path" || { echo "Can't create ${backup_path}" ; exit 1 ; }
+
+{% if 'masters' in group_names %}
+# etcd
+mkdir -p "$backup_path/etcd" || { echo "Can't create ${backup_path}/etcd" ; exit 1 ; }
+etcdctl3 --endpoints="192.168.213.1:2379" snapshot save "$backup_path/etcd/snapshot.db" > /dev/null
+
+# heketi
+mkdir -p "$backup_path/heketi" || { echo "Can't create ${backup_path}/heketi" ; exit 1 ; }
+heketi-cli -s  http://heketi-storage.glusterfs.svc.cluster.local:8080 --user admin --secret "$(oc get secret heketi-storage-admin-secret -n glusterfs -o jsonpath='{.data.key}' | base64 -d)" topology info --json > "$backup_path/heketi/topology.json"
+{% endif %}
+
+
+{% if 'ands_storage_servers' in group_names %}
+# Gluster
+#mkdir -p "$backup_path/gluster" || { echo "Can't create ${backup_path}/gluster" ; exit 1 ; }
+#(
+#    cd /var/lib/
+#    tar cjf $backup_path/gluster/var_lib_glusterd.tar.bz2 glusterd
+#)
+{% endif %}
+
+# etc
+#mkdir -p "$backup_path/etc" || { echo "Can't create ${backup_path}/etc" ; exit 1 ; }
+#(
+#    cd /
+#    tar cjf $backup_path/etc/etc.tar.bz2 etc --exclude=selinux --exclude=udev --exclude=bash_completion.d --exclude=etc/pki --exclude=etc/services --exclude=postfix --exclude=mc 
+#)
+
+if [ -d "$borg_path" ]; then
+    borg_glusterd="/var/lib/glusterd"
+    borg_etc="/etc -e */etc/selinux -e */etc/udev -e */etc/bash_completion.d -e */etc/pki -e */etc/services -e */etc/postfix -e */etc/mc"
+
+{% if 'masters' in group_names %}
+    borg_list="* ${borg_glusterd} ${borg_etc}"
+{% elif 'ands_storage_servers' in group_names %}
+    borg_list="${borg_glusterd} ${borg_etc}"
+{% else %}
+    borg_list="${borg_etc}"
+{% endif %}
+
+    ( 
+	cd ${backup_path}
+	borg create ${borg_args} "$borg_path::${hostname}-${date}" $borg_list
+	borg prune ${borg_prune_args} --prefix "${hostname}-" "$borg_path"
+    )
+    find "$host_path" -maxdepth 1 -type d -mmin +{{ands_backup_clean_minutes}} -print0 | xargs -0 rm -rf
+fi
diff --git a/roles/ands_common/README b/roles/ands_common/README
new file mode 100644
index 0000000..c8bd679
--- /dev/null
+++ b/roles/ands_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/ands_common/default/main.yml b/roles/ands_common/default/main.yml
new file mode 100644
index 0000000..d355d15
--- /dev/null
+++ b/roles/ands_common/default/main.yml
@@ -0,0 +1 @@
+os_update: "{{ ands_update | default(false) }}"
\ No newline at end of file
diff --git a/roles/ands_common/tasks/main.yml b/roles/ands_common/tasks/main.yml
new file mode 100644
index 0000000..e9196ad
--- /dev/null
+++ b/roles/ands_common/tasks/main.yml
@@ -0,0 +1,47 @@
+- name: Ensure all required repositories are configured
+  package: name={{item}} state=present
+  with_items:
+    - epel-release
+    - centos-release-openshift-origin
+
+- name: Add our repository with updates and overrides
+  yum_repository: name="{{ item.name }}" description= "{{ item.description | default('Ands repository') }}" baseurl="{{ item.url }}" enabled="yes" gpgcheck="no" cost="{{ item.cost | default(1) }}"
+  with_items: "{{ ands_repositories | default([]) }}"
+
+- name: Ensure GlusterFS repositories are present
+  yum: name="centos-release-gluster{{ glusterfs_version }}" state=present
+
+# Seems we need iptables-services at least temporary...
+- name: Ensure all required packages are installed
+  package: name={{item}} state=present
+  register: result
+  with_items:
+    - mc
+    - bzr
+    - git
+    - yamllint
+    - pyOpenSSL
+    - python-passlib
+    - python2-ruamel-yaml
+    - python2-jmespath
+    - python-ipaddress
+    - iptables-services
+    - PyYAML
+    - python-rhsm-certificates
+    - glusterfs-fuse
+    - telnet
+    - yum-plugin-versionlock
+
+# We always update on first install and if requested
+- name: Update CentOS
+  yum: name=* state=latest update_cache=yes
+  when: (result | changed) or (os_update | default(false))
+
+#- name: Add NodeJS required by a few used Ansible extensions
+#  package: name={{item}} state=present
+#  with_items:
+#    - nodejs
+
+- name: Ensure all extra packages are installed
+  package: name={{item}} state=present
+  with_items: "{{ extra_packages | default([]) }}"
diff --git a/roles/ands_facts/defaults/main.yml b/roles/ands_facts/defaults/main.yml
index fc3fcfd..c74984e 100644
--- a/roles/ands_facts/defaults/main.yml
+++ b/roles/ands_facts/defaults/main.yml
@@ -3,6 +3,11 @@ ands_none: "{{ None }}"
 ands_configure_heketi: false
 ands_data_device_default_threshold: 10
 
+ands_host_id: "{{ ansible_hostname | regex_replace('^[\\w\\d]*\\w(\\d+)(\\.|$)',  '\\1') }}"
+# We need to add it to set_fact if enabled
+#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) }}"
 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 }}"
 
@@ -23,7 +28,8 @@ ands_default_ip: "{{ ansible_default_ipv4.address }}"
 ands_openshift_default_ip: "{{ ands_resolve_public_ip | default(false) | ternary(ands_default_ip, ands_none) }}"
 ands_openshift_default_hostname: "{{ (ands_hostname_template is defined) | ternary(ands_hostname_template ~ ands_host_id, ansible_hostname) }}"
 
-ands_inner_lb: false
+ands_inner_lb: true
+ands_use_inner_lb: false
 ands_inner_lb_id: 254
 ands_inner_lb_hostname: 'ands-lb'
 
diff --git a/roles/ands_facts/tasks/main.yml b/roles/ands_facts/tasks/main.yml
index 6b28683..bd23e13 100644
--- a/roles/ands_facts/tasks/main.yml
+++ b/roles/ands_facts/tasks/main.yml
@@ -1,14 +1,14 @@
 ---
+# Here we set 'openshift_hostname', 'openshift_ip' and other variables
+- name: "Configuring network facts"
+  include_tasks: "network.yml"
 
 # The variables accessed trough 'hostvars' should be set as facts
 # Here we set 'ands_storage_servers' and other variables
 - name: "Configuring storage facts"
   include_tasks: "storage.yml"
 
-# Here we set 'openshift_hostname', 'openshift_ip' and other variables
-- name: "Configuring network facts"
-  include_tasks: "network.yml"
-
 - name: "Confirm that ands facts are configured"
   set_fact:
+    ands_none: "{{ ands_none }}"
     ands_facts_configured: true
diff --git a/roles/ands_facts/tasks/network.yml b/roles/ands_facts/tasks/network.yml
index 1d0248f..808d7b6 100644
--- a/roles/ands_facts/tasks/network.yml
+++ b/roles/ands_facts/tasks/network.yml
@@ -1,24 +1,34 @@
+- name: Set some facts
+  set_fact:
+    ands_host_id: "{{ ands_host_id }}"
+
 - name: Set network facts
   set_fact:
     ands_cluster_domain: "{{ ands_cluster_domain }}"
     ands_cluster_dot_domain: ".{{ ands_cluster_domain }}"
     ands_inner_domain: "{{ ands_inner_domain }}"
     ands_inner_dot_domain: "{{ (ands_inner_domain == ands_none) | ternary('', '.' ~ ands_inner_domain) }}"
+    ands_inner_lb: "{{ ands_inner_lb }}"
+    ands_use_inner_lb: "{{ ands_use_inner_lb }}"
     ands_inner_lb_ip: "{{ ands_openshift_network | ipaddr(ands_inner_lb_id) | ipaddr('address') }}"
     ands_inner_lb_hostname: "{{ ands_inner_lb_hostname }}"
     ands_openshift_ip: "{{ ands_openshift_network | ipaddr(ands_host_id) | ipaddr('address') }}"
-    ands_openshift_hostname: "{{ ands_openshift_hostname | default(ands_openshift_set_hostname | ternary(ands_openshift_default_hostname, ands_none)) }}"
+    ands_openshift_hostname: "{{ ands_openshift_hostname | default(ands_openshift_default_hostname) }}"
     ands_openshift_public_ip: "{{ (ands_openshift_public_network is defined) | ternary( ands_openshift_public_network | ipaddr(ands_host_id) | ipaddr('address'), ands_openshift_default_ip) }}"
-    ands_openshift_public_hostname: "{{ ands_openshift_public_hostname | default(ands_openshift_set_public_hostname | ternary(ands_openshift_default_hostname, ands_none)) }}"
+    ands_openshift_public_hostname: "{{ ands_openshift_public_hostname | default(ands_openshift_default_hostname) }}"
     ands_storage_ip: "{{ ands_storage_network | default(ands_openshift_network) | ipaddr(ands_host_id) | ipaddr('address') }}"
     ands_hostname_storage: "ands_storage{{ ands_host_id }}"
     ands_hostname_openshift: "ands_openshift{{ ands_host_id }}"
+    ands_openshift_set_hostname: "{{ ands_openshift_set_hostname }}"
+    ands_openshift_set_public_hostname: "{{ ands_openshift_set_public_hostname }}"
+    ands_storage_hostname: "{{ ands_storage_hostname }}"
 
 - name: Set more network facts
   set_fact:
     ands_openshift_public_fqdn: "{{ (ands_openshift_public_hostname == ands_none) | ternary(ands_none, ands_openshift_public_hostname ~ ands_cluster_dot_domain ) }}"
     ands_openshift_fqdn: "{{ (ands_openshift_hostname == ands_none) | ternary(ands_none, ands_openshift_hostname ~ ands_inner_dot_domain ) }}"
-    ands_openshift_cluster_fqdn: "{{ ands_inner_lb | ternary(ands_inner_lb_hostname ~ ands_inner_dot_domain, ands_openshift_lb) }}"
+    ands_inner_lb_fqdn: "{{ ands_inner_lb_hostname ~ ands_inner_dot_domain }}"
+    ands_storage_servers: "{{ ands_storage_servers }}"
 
 - name: "Detect inner network interface"
   include_tasks: "find_interface_by_ip.yml"
diff --git a/roles/ands_facts/tasks/storage.yml b/roles/ands_facts/tasks/storage.yml
index cf995a0..888ad70 100644
--- a/roles/ands_facts/tasks/storage.yml
+++ b/roles/ands_facts/tasks/storage.yml
@@ -1,5 +1,9 @@
 - include_vars: dir="vars"
 
+- name: Set facts
+  set_fact:
+    ands_configure_heketi: "{{ ands_configure_heketi }}"
+
 - name: Detect Heketi
   set_fact: ands_storage_domains="{{ ands_storage_domains | union([ands_heketi_domain]) }}"
   when: 
@@ -7,10 +11,6 @@
     - ands_heketi_domain is defined
     - 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 }}"
diff --git a/roles/ands_kaas/templates/50-kaas-pods.yml.j2 b/roles/ands_kaas/templates/50-kaas-pods.yml.j2
index 216dc01..ad1fc58 100644
--- a/roles/ands_kaas/templates/50-kaas-pods.yml.j2
+++ b/roles/ands_kaas/templates/50-kaas-pods.yml.j2
@@ -5,7 +5,7 @@ kind: Template
 metadata:
   name: {{ kaas_project }}-pods
   annotations:
-    descriptions: {{ kaas_project_config.description | default(kaas_project ~ "auto-generated pod template") }}
+    descriptions: {{ kaas_project_config.description | default(kaas_project ~ " auto-generated pod template") }}
 objects:
 {% for name, pod in kaas_project_pods.iteritems() %}
   {% set pubkey = "kaas_" ~ name ~ "_pubkey" %}
@@ -14,6 +14,9 @@ objects:
   {% if pod.variant is defined %}
     {% set pod = pod[pod.variant] %}
   {% endif %}
+  {% set sched = pod.sched | default({}) %}
+  {% set node_selector = (sched.selector is defined) | ternary(sched.selector, ands_default_node_selector | combine(sched.restrict | default({})))  %}
+  
   {% if pod.service is defined %}
   - apiVersion: v1
     kind: Service
@@ -68,10 +71,10 @@ objects:
     metadata:
       name: {{ pod.name | default(name) }}
     spec:
-      replicas: {{ ( pod.sched | default({})).replicas | default(1) }}
+      replicas: {{ ( sched | default({})).replicas | default(1) }}
       revisionHistoryLimit: 2 
       strategy:
-        type: {{ (pod.sched | default({})).strategy | default('Rolling') }}
+        type: {{ (sched | default({})).strategy | default('Rolling') }}
       triggers:
       - type: ConfigChange
       selector:
@@ -82,11 +85,8 @@ objects:
           labels:
             name: {{ pod.name | default(name) }}
         spec:
-    {% if pod.selector is defined %}
-          nodeSelector: 
-      {% for skey, sval in pod.selector.iteritems() %}
-            {{ skey }}: "{{ sval }}"
-      {% endfor %}
+    {% if node_selector | length > 0 %}
+          nodeSelector: {{ node_selector | to_json }}
     {% endif %}
     {% set mappings = (pod.images | json_query('[*].mappings') | length)  %}
     {% if mappings > 0 %}
diff --git a/roles/ands_network/tasks/common.yml b/roles/ands_network/tasks/common.yml
index 384029f..f2fda00 100644
--- a/roles/ands_network/tasks/common.yml
+++ b/roles/ands_network/tasks/common.yml
@@ -22,27 +22,18 @@
     - nodes
     - new_nodes
 
-- name: Configure all storage ips in /etc/hosts
-  lineinfile: dest="/etc/hosts" line="{{ ip }} {{ hostname }}" regexp="{{ hostname }}" state="present"
-  when: 
-    - hostvars[item]['ands_storage_network'] | default(ands_none) != ands_none
-    - hostvars[item]['ands_facts_configured'] is defined
-  vars:
-    ip: "{{ hostvars[item]['ands_storage_ip'] }}"
-    hostname: "{{ hostvars[item]['ands_hostname_storage'] }}"
-  with_inventory_hostnames:
-    - storage_nodes
-    - new_storage_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 or 'new_masters' in group_names)
   register: result
 
-- name: Provision /etc/hosts to ensure that all masters servers are accessing Master API on loopback device
+- name: Provision /etc/hosts with load-balance IP on non master servers
   lineinfile: dest="/etc/hosts" line="{{ ands_inner_lb_ip }} {{ openshift_master_cluster_hostname }}" regexp=".*{{ openshift_master_cluster_hostname }}$" state="present"
-  when: (result | skipped) and (ands_inner_lb | default(false))
+  when: (result | skipped) and (ands_use_inner_lb | default(false))
+
+- name: Provision inner load-balancer hostname in /etc/hosts
+  lineinfile: dest="/etc/hosts" line="{{ ands_inner_lb_ip }} {{ ands_inner_lb_hostname }} {{ ands_inner_lb_fqdn }}" regexp=".*{{ ands_inner_lb_fqdn }}$" state="present"
+  when: openshift_master_cluster_hostname != ands_inner_lb_fqdn
 
 - name: Register openshift_dns_ip in /etc/hosts
   lineinfile: dest="/etc/hosts" line="{{ openshift_dns_ip }} openshift_dns_ip" regexp="openshift_dns_ip$" state="present"
diff --git a/roles/ands_network/tasks/ganesha.yml b/roles/ands_network/tasks/ganesha.yml
new file mode 100644
index 0000000..0f77ca8
--- /dev/null
+++ b/roles/ands_network/tasks/ganesha.yml
@@ -0,0 +1,12 @@
+- name: Configure all storage ips in /etc/hosts
+  lineinfile: dest="/etc/hosts" line="{{ ip }} {{ hostname }}" regexp="{{ hostname }}" state="present"
+  when: 
+    - hostvars[item]['ands_storage_network'] | default(ands_none) != ands_none
+    - hostvars[item]['ands_facts_configured'] is defined
+  vars:
+    ip: "{{ hostvars[item]['ands_storage_ip'] }}"
+    hostname: "{{ hostvars[item]['ands_hostname_storage'] }}"
+  with_inventory_hostnames:
+    - storage_nodes
+    - new_storage_nodes
+
diff --git a/roles/ands_network/tasks/install_post.yml b/roles/ands_network/tasks/install_post.yml
index 0bfef34..3f1e57c 100644
--- a/roles/ands_network/tasks/install_post.yml
+++ b/roles/ands_network/tasks/install_post.yml
@@ -6,4 +6,4 @@
   lineinfile: dest="/etc/hosts" line="{{ ands_inner_lb_ip | default('') }} {{ openshift_master_cluster_hostname }}" regexp=".*{{ openshift_master_cluster_hostname }}$" state="{{ state }}"
   when: ('masters' not in group_names and 'new_masters' not in group_names)
   vars:
-    state: "{{ ands_inner_lb | default(false) | ternary('present', 'absent') }}"
+    state: "{{ ands_use_inner_lb | default(false) | ternary('present', 'absent') }}"
diff --git a/roles/ands_network/tasks/maintain.yml b/roles/ands_network/tasks/maintain.yml
index a7af597..6fba5f2 100644
--- a/roles/ands_network/tasks/maintain.yml
+++ b/roles/ands_network/tasks/maintain.yml
@@ -6,4 +6,8 @@
   lineinfile: dest="/etc/hosts" line="{{ ands_inner_lb_ip | default('') }} {{ openshift_master_cluster_hostname }}" regexp=".*{{ openshift_master_cluster_hostname }}$" state="{{ state }}"
   when: ('masters' not in group_names and 'new_masters' not in group_names)
   vars:
-    state: "{{ ands_inner_lb | default(false) | ternary('present', 'absent') }}"
+    state: "{{ ands_use_inner_lb | default(false) | ternary('present', 'absent') }}"
+
+- name: Provision inner load-balancer hostname in /etc/hosts
+  lineinfile: dest="/etc/hosts" line="{{ ands_inner_lb_ip }} {{ ands_inner_lb_hostname }} {{ ands_inner_lb_fqdn }}" regexp=".*{{ ands_inner_lb_fqdn }}$" state="present"
+  when: openshift_master_cluster_hostname != ands_inner_lb_fqdn
diff --git a/roles/common/README b/roles/common/README
deleted file mode 100644
index c8bd679..0000000
--- a/roles/common/README
+++ /dev/null
@@ -1,11 +0,0 @@
-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/default/main.yml b/roles/common/default/main.yml
deleted file mode 100644
index d355d15..0000000
--- a/roles/common/default/main.yml
+++ /dev/null
@@ -1 +0,0 @@
-os_update: "{{ ands_update | default(false) }}"
\ No newline at end of file
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
deleted file mode 100644
index fdd7246..0000000
--- a/roles/common/tasks/main.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-- name: Ensure all required repositories are configured
-  package: name={{item}} state=present
-  with_items:
-    - epel-release
-    - centos-release-openshift-origin
-
-- name: Add our repository with updates and overrides
-  yum_repository: name="{{ item.name }}" description= "{{ item.description | default('Ands repository') }}" baseurl="{{ item.url }}" enabled="yes" gpgcheck="no" cost="{{ item.cost | default(1) }}"
-  with_items: "{{ ands_repositories | default([]) }}"
-
-- name: Ensure GlusterFS repositories are present
-  yum: name="centos-release-gluster{{ glusterfs_version }}" state=present
-
-# Seems we need iptables-services at least temporary...
-- name: Ensure all required packages are installed
-  package: name={{item}} state=present
-  register: result
-  with_items:
-    - mc
-    - bzr
-    - git
-    - yamllint
-    - pyOpenSSL
-    - python-passlib
-    - python2-ruamel-yaml
-    - python2-jmespath
-    - python-ipaddress
-    - iptables-services
-    - PyYAML
-    - python-rhsm-certificates
-    - glusterfs-fuse
-    - telnet
-
-# We always update on first install and if requested
-- name: Update CentOS
-  yum: name=* state=latest update_cache=yes
-  when: (result | changed) or (os_update | default(false))
-
-#- name: Add NodeJS required by a few used Ansible extensions
-#  package: name={{item}} state=present
-#  with_items:
-#    - nodejs
-
-- name: Ensure all extra packages are installed
-  package: name={{item}} state=present
-  with_items: "{{ extra_packages | default([]) }}"
diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml
index f7b96f5..30b1ff8 100644
--- a/roles/docker/defaults/main.yml
+++ b/roles/docker/defaults/main.yml
@@ -4,3 +4,6 @@ docker_lv: "docker-pool"
 docker_min_size: 100
 docker_max_log_size: "2m"
 docker_max_log_files: "3"
+
+# There are some problems with groups on 1.13
+docker_version: "-1.12*"
diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml
index 0d040a9..c03d897 100644
--- a/roles/docker/tasks/main.yml
+++ b/roles/docker/tasks/main.yml
@@ -1,6 +1,20 @@
 ---
+#- name: Remove docker
+#  yum: name="{{ item }}" state="absent"
+#  with_items: [ docker, docker-client, docker-common ]
+
+- name: Remove versionlock from yum
+  command: yum versionlock delete docker docker-common docker-client
+  register: result
+  failed_when: false
+  changed_when: result | failed
+
 - name: Ensure docker is installed
-  yum: name="docker" state="present"
+  yum: name="docker{{ docker_version | default('') }}" state="{{ docker_version is defined | ternary('latest', 'present') }}"
+
+- name: Add versionlock to yum
+  command: yum versionlock add docker docker-common docker-client
+  when: docker_version is defined
 
 - name: start docker
   service: name="docker" state="started"
diff --git a/roles/glusterfs/tasks/cfg/vols3.yml b/roles/glusterfs/tasks/cfg/vols3.yml
index d094797..d8ed728 100644
--- a/roles/glusterfs/tasks/cfg/vols3.yml
+++ b/roles/glusterfs/tasks/cfg/vols3.yml
@@ -3,6 +3,7 @@
   gluster_volume: 
     state: present
     name: "{{ name }}"
+    host: "{{ ands_storage_hostname }}"
     cluster: "{{ domain_servers | join(',') }}"
     replicas: "{{ domain_servers | length }}"
     bricks: "{{ glusterfs_bricks_path }}/brick-{{ name }}"
diff --git a/roles/glusterfs/tasks/data/vols2.yml b/roles/glusterfs/tasks/data/vols2.yml
index d094797..d8ed728 100644
--- a/roles/glusterfs/tasks/data/vols2.yml
+++ b/roles/glusterfs/tasks/data/vols2.yml
@@ -3,6 +3,7 @@
   gluster_volume: 
     state: present
     name: "{{ name }}"
+    host: "{{ ands_storage_hostname }}"
     cluster: "{{ domain_servers | join(',') }}"
     replicas: "{{ domain_servers | length }}"
     bricks: "{{ glusterfs_bricks_path }}/brick-{{ name }}"
diff --git a/roles/glusterfs/tasks/data/vols3.yml b/roles/glusterfs/tasks/data/vols3.yml
index 866480c..14c3763 100644
--- a/roles/glusterfs/tasks/data/vols3.yml
+++ b/roles/glusterfs/tasks/data/vols3.yml
@@ -3,6 +3,7 @@
   gluster_volume: 
     state: present
     name: "{{ name }}"
+    host: "{{ ands_storage_hostname }}"
     cluster: "{{ domain_servers | join(',') }}"
     replicas: 3
     arbiters: 1
diff --git a/roles/glusterfs/tasks/db/vols3.yml b/roles/glusterfs/tasks/db/vols3.yml
index b1beacb..cbd238d 100644
--- a/roles/glusterfs/tasks/db/vols3.yml
+++ b/roles/glusterfs/tasks/db/vols3.yml
@@ -3,6 +3,7 @@
   gluster_volume: 
     state: present
     name: "{{ name }}"
+    host: "{{ ands_storage_hostname }}"
     cluster: "{{ domain_servers | join(',') }}"
     disperses: "3"
     redundancies: "1"
diff --git a/roles/glusterfs/tasks/la/vols3.yml b/roles/glusterfs/tasks/la/vols3.yml
index 9565bb3..ada8f95 100644
--- a/roles/glusterfs/tasks/la/vols3.yml
+++ b/roles/glusterfs/tasks/la/vols3.yml
@@ -3,6 +3,7 @@
   gluster_volume: 
     state: present
     name: "{{ name }}"
+    host: "{{ ands_storage_hostname }}"
     cluster: "{{ domain_servers | join(',') }}"
     bricks: "{{ glusterfs_bricks_path }}/brick-{{ name }}"
     transport: "{{ glusterfs_transport }}"
diff --git a/roles/ntp b/roles/ntp
new file mode 120000
index 0000000..626609b
--- /dev/null
+++ b/roles/ntp
@@ -0,0 +1 @@
+../anslib/ansible-role-ntp/
\ No newline at end of file
-- 
cgit v1.2.3