summaryrefslogtreecommitdiffstats
path: root/roles
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2018-03-20 15:47:51 +0100
committerSuren A. Chilingaryan <csa@suren.me>2018-03-20 15:47:51 +0100
commite2c7b1305ca8495065dcf40fd2092d7c698dd6ea (patch)
treeabcaa7006a9c4b7a9add9bd0bf8c24f7f8ce048f /roles
parent47f350bc3aa85a8bd406d95faf084df2abf74ae9 (diff)
downloadands-e2c7b1305ca8495065dcf40fd2092d7c698dd6ea.tar.gz
ands-e2c7b1305ca8495065dcf40fd2092d7c698dd6ea.tar.bz2
ands-e2c7b1305ca8495065dcf40fd2092d7c698dd6ea.tar.xz
ands-e2c7b1305ca8495065dcf40fd2092d7c698dd6ea.zip
Local volumes and StatefulSet to provision Master/Slave MySQL and Galera cluster
Diffstat (limited to 'roles')
-rw-r--r--roles/ands_facts/tasks/main.yml8
-rw-r--r--roles/ands_facts/tasks/node.yml5
-rw-r--r--roles/ands_facts/tasks/nodes.yml10
-rw-r--r--roles/ands_facts/tasks/volume.yml8
-rw-r--r--roles/ands_facts/tasks/volumes.yml7
-rw-r--r--roles/ands_facts/tasks/volumes_iterate.yml13
-rw-r--r--roles/ands_kaas/00-local-volumes.yml.j267
-rw-r--r--roles/ands_kaas/tasks/do_apps.yml18
-rw-r--r--roles/ands_kaas/tasks/do_keys.yml6
-rw-r--r--roles/ands_kaas/tasks/do_project.yml77
-rw-r--r--roles/ands_kaas/tasks/do_storage.yml14
-rw-r--r--roles/ands_kaas/tasks/ocitem.yml28
-rw-r--r--roles/ands_kaas/tasks/project.yml17
-rw-r--r--roles/ands_kaas/tasks/template.yml11
-rw-r--r--roles/ands_kaas/templates/00-local-volumes.yml.j250
-rw-r--r--roles/ands_kaas/templates/50-kaas-pods.yml.j2111
-rw-r--r--roles/ands_network/defaults/main.yml2
-rw-r--r--roles/ands_network/files/galera.xml10
-rw-r--r--roles/ands_network/files/netpipe.xml6
-rw-r--r--roles/ands_network/tasks/add_names.yml28
-rw-r--r--roles/ands_network/tasks/common.yml1
-rw-r--r--roles/ands_network/tasks/firewall.yml32
-rw-r--r--roles/ands_network/tasks/firewall_service.yml13
-rw-r--r--roles/ands_network/tasks/nm_configure.yml15
-rw-r--r--roles/ands_network/tasks/nm_configure_connection.yml31
-rw-r--r--roles/openshift_resource/tasks/template.yml9
26 files changed, 477 insertions, 120 deletions
diff --git a/roles/ands_facts/tasks/main.yml b/roles/ands_facts/tasks/main.yml
index ce5dd23..54c800a 100644
--- a/roles/ands_facts/tasks/main.yml
+++ b/roles/ands_facts/tasks/main.yml
@@ -13,7 +13,15 @@
- name: "Configuring storage facts"
include_tasks: "storage.yml"
+- name: "Configuring ands nodes"
+ include_tasks: "nodes.yml"
+
+- name: "Configuring ands volumes"
+ include_tasks: "volumes.yml"
+
- name: "Confirm that ands facts are configured"
set_fact:
ands_none: "{{ ands_none }}"
ands_facts_configured: true
+
+#- debug: msg="{{ ands_volume_hostraid_servers }}"
diff --git a/roles/ands_facts/tasks/node.yml b/roles/ands_facts/tasks/node.yml
new file mode 100644
index 0000000..e30442c
--- /dev/null
+++ b/roles/ands_facts/tasks/node.yml
@@ -0,0 +1,5 @@
+- name: "Associating public host names with ids"
+ set_fact: "ands_host_{{ host_id }}_public_hostname={{ host.value['ands_openshift_public_hostname'] }}"
+
+- name: "Associating openshift fqdn with ids"
+ set_fact: "ands_host_{{ host_id }}_openshift_fqdn={{ host.value['ands_openshift_fqdn'] }}"
diff --git a/roles/ands_facts/tasks/nodes.yml b/roles/ands_facts/tasks/nodes.yml
new file mode 100644
index 0000000..ebe8091
--- /dev/null
+++ b/roles/ands_facts/tasks/nodes.yml
@@ -0,0 +1,10 @@
+- name: Process all nodes
+ include_tasks: "node.yml"
+ run_once: true
+ delegate_to: "{{ groups['masters'][0] }}"
+ with_dict: "{{ hostvars }}"
+ vars:
+ host_id: "{{ host.value['ands_host_id'] }}"
+ host_name: "{{ host.value['ansible_hostname'] }}"
+ loop_control:
+ loop_var: host
diff --git a/roles/ands_facts/tasks/volume.yml b/roles/ands_facts/tasks/volume.yml
new file mode 100644
index 0000000..5ac4af3
--- /dev/null
+++ b/roles/ands_facts/tasks/volume.yml
@@ -0,0 +1,8 @@
+- name: "Associating volumes with domains"
+ set_fact: "ands_volume_{{ name }}_domain={{ domain }}"
+
+- name: "Associating volumes with servers"
+ set_fact: "ands_volume_{{ name }}_servers={{ domain_servers }}"
+
+- name: "Associating volumes with servers"
+ set_fact: "ands_volume_{{ name }}_server_ids={{ domain_server_ids }}"
diff --git a/roles/ands_facts/tasks/volumes.yml b/roles/ands_facts/tasks/volumes.yml
new file mode 100644
index 0000000..616202c
--- /dev/null
+++ b/roles/ands_facts/tasks/volumes.yml
@@ -0,0 +1,7 @@
+- name: Process all storage domains
+ include_tasks: "volumes_iterate.yml"
+ run_once: true
+ delegate_to: "{{ groups[domain.servers][0] }}"
+ with_items: "{{ ands_local_storage_domains | default([]) | union(ands_storage_domains) }}"
+ loop_control:
+ loop_var: domain
diff --git a/roles/ands_facts/tasks/volumes_iterate.yml b/roles/ands_facts/tasks/volumes_iterate.yml
new file mode 100644
index 0000000..979e12f
--- /dev/null
+++ b/roles/ands_facts/tasks/volumes_iterate.yml
@@ -0,0 +1,13 @@
+---
+- name: Iterate volumes
+ include_tasks: "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 }}"
+ domain_server_ids: "{{ groups[domain.servers] | map('extract', hostvars, 'ands_host_id') | list }}"
+ when: volume.value.mount is defined
+ loop_control:
+ loop_var: volume
diff --git a/roles/ands_kaas/00-local-volumes.yml.j2 b/roles/ands_kaas/00-local-volumes.yml.j2
new file mode 100644
index 0000000..8d1a1c8
--- /dev/null
+++ b/roles/ands_kaas/00-local-volumes.yml.j2
@@ -0,0 +1,67 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: {{ kaas_project }}-local-volumes
+ annotations:
+ descriptions: "{{ kaas_project }} local volumes"
+objects:
+{% for name, vol in kaas_project_local_volumes.iteritems() %}
+{% set voltypes = kaas_storage_domains | json_query("[*].volumes." + vol.volume + ".type") %}
+{% set voltype = voltypes[0] | default('host') %}
+{% set mntpaths = kaas_storage_domains | json_query("[*].volumes." + vol.volume + ".mount") %}
+{% set mntpath = mntpaths[0] | default('') %}
+{% set oc_name = vol.name | default(name) | regex_replace('_','-') %}
+{% set cfgpath = vol.path | default("") %}
+{% set path = cfgpath if cfgpath[:1] == "/" else "/" + kaas_project + "/" + cfgpath %}
+{% if oc_name | regex_search("^" + kaas_project) %}
+{% set pvprefix = oc_name %}
+{% else %}
+{% set pvprefix = (kaas_project + "-" + oc_name) | regex_replace('_','-') %}
+{% endif %}
+{% set i = 0 %}
+{% for id in vol.nodes | default(hostvars[inventory_hostname]['ands_volume_' + vol.volume + '_server_ids']) %}
+{% set srvid = (id | string) %}
+{% set server_name = hostvars[inventory_hostname]['ands_host_' + srvid + '_public_hostname'] %}
+{% set openshift_name = hostvars[inventory_hostname]['ands_host_' + srvid + '_openshift_fqdn'] %}
+{% set pvname = pvprefix + '-' + server_name %}
+{% set pvcname = oc_name + '-' + (i|string) %}
+ - apiVersion: v1
+ kind: PersistentVolume
+ metadata:
+ name: {{ pvname }}
+ annotations:
+ "volume.alpha.kubernetes.io/node-affinity": '{
+ "requiredDuringSchedulingIgnoredDuringExecution": {
+ "nodeSelectorTerms": [
+ { "matchExpressions": [ { "key": "kubernetes.io/hostname", "operator": "In", "values": ["{{ openshift_name }}"] } ]}
+ ]
+ }
+ }'
+ spec:
+ storageClassName: kaas-local-storage
+ persistentVolumeReclaimPolicy: Retain
+ local:
+ path: "{{ mntpath }}{{ path }}"
+ readOnly: {{ not (vol.write | default(false)) }}
+ accessModes:
+ - ReadWriteOnce
+ capacity:
+ storage: {{ vol.capacity | default(kaas_default_volume_capacity) }}
+ claimRef:
+ name: {{ pvcname }}
+ namespace: {{ kaas_project }}
+ - apiVersion: v1
+ kind: PersistentVolumeClaim
+ metadata:
+ name: {{ pvcname }}
+ spec:
+ volumeName: {{ pvname }}
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ vol.capacity | default(kaas_default_volume_capacity) }}
+{% set i = i + 1 %}
+{% endfor %}
+{% endfor %}
diff --git a/roles/ands_kaas/tasks/do_apps.yml b/roles/ands_kaas/tasks/do_apps.yml
index 6738b7f..39283b4 100644
--- a/roles/ands_kaas/tasks/do_apps.yml
+++ b/roles/ands_kaas/tasks/do_apps.yml
@@ -1,16 +1,20 @@
- name: "Process KaaS apps"
include_tasks: "template.yml"
run_once: true
- with_items: "{{ kaas_project_apps }}"
+ with_dict: "{{ kaas_project_apps }}"
loop_control:
- loop_var: appname
+ loop_var: appitem
when:
- - app.provision | default(true)
- - (ands_configure_app == ands_none) or (app.name == ands_configure_app)
+ - appitem.value.provision | default(true)
+ - (ands_configure_app == ands_none) or (appname == ands_configure_app)
+ - appname | match(kaas_app_regexp | default(.*))
vars:
- app: "{{ kaas_project_config[appname] }}"
- name: "{{ app.name | default((app.pods.keys() | list)[0]) }}"
- instantiate: "{{ app.instantiate | default(false) }}"
+ app: "{{ kaas_project_config[appitem.key] }}"
+ appname: "{{ app.name | default(appitem.key) | regex_replace('_','-') }}"
+# appname: "{{ app.name | default((app.pods.keys() | list)[0]) }}"
+ options: "{{ app.options | default({}) }}"
+ delete: "{{ options.delete | default(true) }}"
+ instantiate: "{{ appitem.value.instantiate | default(false) }}"
load: "{{ app.load | default(false) }}"
pods: "{{ app.pods }}"
tmpl_name: "50-kaas-pods.yml.j2"
diff --git a/roles/ands_kaas/tasks/do_keys.yml b/roles/ands_kaas/tasks/do_keys.yml
new file mode 100644
index 0000000..391392e
--- /dev/null
+++ b/roles/ands_kaas/tasks/do_keys.yml
@@ -0,0 +1,6 @@
+- name: Load OpenSSL keys
+ include_tasks: keys.yml
+ run_once: true
+ with_dict: "{{ kaas_project_pods }}"
+ loop_control:
+ loop_var: pod
diff --git a/roles/ands_kaas/tasks/do_project.yml b/roles/ands_kaas/tasks/do_project.yml
index f5b3276..71a54ad 100644
--- a/roles/ands_kaas/tasks/do_project.yml
+++ b/roles/ands_kaas/tasks/do_project.yml
@@ -2,77 +2,24 @@
- name: Ensure OpenShift template directory exists
file: path="{{ kaas_template_path }}" state="directory" mode=0755 owner=root group=root
-- name: Configure KaaS volumes
- include_tasks: volume.yml
- run_once: true
-# delegate_to: "{{ groups.masters[0] }}"
- with_dict: "{{ kaas_project_volumes }}"
- loop_control:
- loop_var: osv
- vars:
- vt_query: "[*].volumes.{{osv.value.volume}}.type"
- voltype: "{{ (kaas_storage_domains | json_query(vt_query)) }}"
- mp_query: "[*].volumes.{{osv.value.volume}}.mount"
- mntpath: "{{ (kaas_storage_domains | json_query(mp_query)) }}"
- rp_query: "[*].volumes.{{osv.value.volume}}.path"
- realpath: "{{ (kaas_storage_domains | json_query(rp_query)) }}"
- osvpath: "{{ osv.value.path | default('') }}"
- prefix: "{{ ( osvpath[:1] == '/' ) | ternary('', '/' ~ kaas_project ~ '/') }}"
- path: "{{ mntpath[0] ~ prefix ~ osvpath }}"
- hostpath: "{{ realpath[0] is defined | ternary((realpath[0] | default('')) ~ prefix ~ osvpath, '') }}"
- name: "{{osv.key}}"
- volume: "{{osv.value}}"
- when: ( mntpath | length ) > 0
-
-- name: Check if static configuration exists
- local_action: stat path="{{ kaas_project_path }}/files/"
- register: result
-
-- name: Search static configuration
- include_tasks: search.yml
- when: result.stat.exists
-
-- name: Configure KaaS files
- include_tasks: file.yml
- run_once: true
-# delegate_to: "{{ groups.masters[0] }}"
- with_items: "{{ kaas_project_config.files | default(kaas_openshift_files) | default([]) }}"
- loop_control:
- loop_var: file
- vars:
- osv: "{{ kaas_project_volumes[file.osv] }}"
- vt_query: "[*].volumes.{{osv.volume}}.type"
- voltype: "{{ (kaas_storage_domains | json_query(vt_query)) }}"
- mp_query: "[*].volumes.{{osv.volume}}.mount"
- mntpath: "{{ (kaas_storage_domains | json_query(mp_query)) }}"
- rp_query: "[*].volumes.{{osv.volume}}.path"
- realpath: "{{ (kaas_storage_domains | json_query(rp_query)) }}"
- pvar: "kaas_{{ file.osv }}_path"
- path: "{{ hostvars[inventory_hostname][pvar] }}/{{ file.path }}"
- hvar: "kaas_{{ file.osv }}_hostpath"
- hostpath: "{{ hostvars[inventory_hostname][hvar] }}/{{ file.path }}"
- when: file.osv in kaas_project_volumes
-
-- name: Load OpenSSL keys
- include_tasks: keys.yml
-# delegate_to: "{{ groups.masters[0] }}"
- run_once: true
- with_dict: "{{ kaas_project_pods }}"
- loop_control:
- loop_var: pod
-
- name: "Run OC script"
include_tasks: ocscript.yml
-# delegate_to: "{{ groups.masters[0] }}"
run_once: true
when: kaas_project_config.oc is defined
-- name: "Configure all templates"
- include_tasks: templates.yml
-# delegate_to: "{{ groups.masters[0] }}"
+- block:
+ - name: Configure storage
+ include_tasks: do_storage.yml
+
+ - name: Configure SSL keys
+ include_tasks: do_keys.yml
+
+ - name: Configure all templates
+ include_tasks: templates.yml
+
+ - name: Install Applications
+ include_tasks: do_apps.yml
run_once: true
when:
- kaas_project_config.oc is undefined
-- name: Install Applications
- include_tasks: do_apps.yml
diff --git a/roles/ands_kaas/tasks/do_storage.yml b/roles/ands_kaas/tasks/do_storage.yml
index ee118fd..e79db56 100644
--- a/roles/ands_kaas/tasks/do_storage.yml
+++ b/roles/ands_kaas/tasks/do_storage.yml
@@ -18,8 +18,18 @@
volume: "{{osv.value}}"
when:
- ( mntpath | length ) > 0
- - (osv.type | default("host")) in [ "host" ]
+ - (kaas_storage_types is not defined) or ((osv.type | default("host")) in kaas_storage_types)
+- name: Check if static configuration exists
+ local_action: stat path="{{ kaas_project_path }}/files/"
+ register: result
+
+# Executed only if complete project is provisioned (not if we just care to provision per-node storage)
+- name: Search static configuration
+ include_tasks: search.yml
+ when:
+ - result.stat.exists
+ - kaas_storage_types is not defined
- name: Configure KaaS files
include_tasks: file.yml
@@ -40,4 +50,4 @@
hostpath: "{{ hostvars[inventory_hostname][hvar] }}/{{ file.path }}"
when:
- file.osv in kaas_project_volumes
- - (osv.type | default("host")) in [ "host" ]
+ - (kaas_storage_types is not defined) or ((osv.type | default("host")) in kaas_storage_types)
diff --git a/roles/ands_kaas/tasks/ocitem.yml b/roles/ands_kaas/tasks/ocitem.yml
index addb249..758cdaf 100644
--- a/roles/ands_kaas/tasks/ocitem.yml
+++ b/roles/ands_kaas/tasks/ocitem.yml
@@ -1,13 +1,35 @@
---
+- name: Storage
+ include_tasks: do_storage.yml
+ run_once: true
+ vars:
+ kaas_storage_regexp: "{{ ocitem.storage }}"
+ when: ocitem.storage is defined
+
+- name: Keys
+ include_tasks: do_keys.yml
+ run_once: true
+ vars:
+ kaas_keys_regexp: "{{ ocitem.keys }}"
+ when: ocitem.keys is defined
+
- name: OpenShift templates
include_tasks: templates.yml
run_once: true
vars:
- kaas_template_glob: "{{ ocitem.template }}"
- when: ocitem.template is defined
+ kaas_template_glob: "{{ ocitem.templates }}"
+ when: ocitem.templates is defined
+
+- name: OpenShift apps
+ include_tasks: do_apps.yml
+ run_once: true
+ vars:
+ kaas_app_regexp: "{{ ocitem.apps }}"
+ when: ocitem.apps is defined
- name: OpenShift commands
include_tasks: oc.yml
-# delegate_to: "{{ groups.masters[0] }}"
run_once: true
when: ocitem.oc is defined
+
+
diff --git a/roles/ands_kaas/tasks/project.yml b/roles/ands_kaas/tasks/project.yml
index ecb2035..26bd0cc 100644
--- a/roles/ands_kaas/tasks/project.yml
+++ b/roles/ands_kaas/tasks/project.yml
@@ -26,7 +26,7 @@
with_dict: "{{ kaas_block_volumes }}"
when: item.value.project == kaas_project
-- name: Get information about block volumes
+- name: Get more information about block volumes
delegate_to: "{{ groups.masters[0] }}"
shell: gluster-block info {{ item.value.volume }}/{{ item.key }} | grep -oP '^EXPORTED NODE.*:\s*\K.*' | tr ' ' '\n'
register: portal_info
@@ -55,11 +55,12 @@
- include_tasks: "do_{{ do_subrole | default('project') }}.yml"
vars:
var_name: "var_{{kaas_project}}_config"
- kaas_project_config: "{{ hostvars[inventory_hostname][var_name] }}"
- kaas_project_volumes: "{{ kaas_project_config.volumes | default(kaas_project_config.extra_volumes | default({}) | combine(kaas_openshift_volumes)) }}"
- kaas_project_pods: "{{ kaas_project_config.pods | default({}) }}"
- kaas_project_apps: "{{ kaas_project_config.apps | default([]) }}"
- kaas_project_gids: "{{ kaas_project_config.gids | default(kaas_openshift_gids) }}"
- kaas_project_uids: "{{ kaas_project_config.uids | default(kaas_openshift_uids) }}"
- kaas_blockvol_info: "{{ block_info }}"
+ kaas_project_config: "{{ hostvars[inventory_hostname][var_name] }}"
+ kaas_project_volumes: "{{ kaas_project_config.volumes | default(kaas_project_config.extra_volumes | default({}) | combine(kaas_openshift_volumes)) }}"
+ kaas_project_local_volumes: "{{ kaas_project_config.local_volumes | default({}) }}"
+ kaas_project_pods: "{{ kaas_project_config.pods | default({}) }}"
+ kaas_project_apps: "{{ kaas_project_config.apps | default([]) }}"
+ kaas_project_gids: "{{ kaas_project_config.gids | default(kaas_openshift_gids) }}"
+ kaas_project_uids: "{{ kaas_project_config.uids | default(kaas_openshift_uids) }}"
+ kaas_blockvol_info: "{{ block_info }}"
\ No newline at end of file
diff --git a/roles/ands_kaas/tasks/template.yml b/roles/ands_kaas/tasks/template.yml
index 418331a..87e45a6 100644
--- a/roles/ands_kaas/tasks/template.yml
+++ b/roles/ands_kaas/tasks/template.yml
@@ -1,9 +1,9 @@
-- name: "Populate template {{ tmpl_name }}"
+- name: "Populate template '{{ tmpl_name }}' in project '{{ kaas_project }}' for application '{{ appname | default('kaas') }}'"
template: src="{{ item }}" dest="{{ kaas_template_path }}/{{ dest_name }}" owner=root group=root mode="0644"
register: result
vars:
default_name: "{{ item | basename | regex_replace('\\.j2','') }}"
- dest_name: "{{ (name is defined) | ternary ( (name | default('')) + '.yml', default_name ) }}"
+ dest_name: "{{ (appname is defined) | ternary ( '90-' + (appname | default('')) + '.yml', default_name ) }}"
with_first_found:
- paths:
- "{{ role_path }}/templates/"
@@ -15,10 +15,13 @@
include_role: name="openshift_resource"
when: instantiate == true
vars:
- template: "{{ tmpl_name | basename | regex_replace('\\.j2','') }}"
+ default_name: "{{ tmpl_name | basename | regex_replace('\\.j2','') }}"
+ dest_name: "{{ (appname is defined) | ternary ( '90-' + (appname | default('')) + '.yml', default_name ) }}"
+ template: "{{ dest_name }}"
template_path: "{{ kaas_template_path }}"
project: "{{ kaas_project }}"
- recreate: "{{ result | changed | ternary (true, false) }}"
+ recreate: "{{ result | changed | ternary (delete | ternary(true, false), false) }}"
+ replace: "{{ result | changed | ternary (delete | ternary(false, true), false) }}"
# alternatively load template
# TODO
diff --git a/roles/ands_kaas/templates/00-local-volumes.yml.j2 b/roles/ands_kaas/templates/00-local-volumes.yml.j2
new file mode 100644
index 0000000..a97ffae
--- /dev/null
+++ b/roles/ands_kaas/templates/00-local-volumes.yml.j2
@@ -0,0 +1,50 @@
+---
+apiVersion: v1
+kind: Template
+metadata:
+ name: {{ kaas_project }}-local-volumes
+ annotations:
+ descriptions: "{{ kaas_project }} local volumes"
+objects:
+{% for name, vol in kaas_project_local_volumes.iteritems() %}
+{% set voltypes = kaas_storage_domains | json_query("[*].volumes." + vol.volume + ".type") %}
+{% set voltype = voltypes[0] | default('host') %}
+{% set mntpaths = kaas_storage_domains | json_query("[*].volumes." + vol.volume + ".mount") %}
+{% set mntpath = mntpaths[0] | default('') %}
+{% set oc_name = vol.name | default(name) | regex_replace('_','-') %}
+{% set cfgpath = vol.path | default("") %}
+{% set path = cfgpath if cfgpath[:1] == "/" else "/" + kaas_project + "/" + cfgpath %}
+{% if oc_name | regex_search("^" + kaas_project) %}
+{% set pvprefix = oc_name %}
+{% else %}
+{% set pvprefix = (kaas_project + "-" + oc_name) | regex_replace('_','-') %}
+{% endif %}
+{% for id in vol.nodes | default(hostvars[inventory_hostname]['ands_volume_' + vol.volume + '_server_ids']) %}
+{% set srvid = (id | string) %}
+{% set server_name = hostvars[inventory_hostname]['ands_host_' + srvid + '_public_hostname'] %}
+{% set openshift_name = hostvars[inventory_hostname]['ands_host_' + srvid + '_openshift_fqdn'] %}
+{% set pvname = pvprefix + '-' + server_name %}
+ - apiVersion: v1
+ kind: PersistentVolume
+ metadata:
+ name: {{ pvname }}
+ annotations:
+ "volume.alpha.kubernetes.io/node-affinity": '{
+ "requiredDuringSchedulingIgnoredDuringExecution": {
+ "nodeSelectorTerms": [
+ { "matchExpressions": [ { "key": "kubernetes.io/hostname", "operator": "In", "values": ["{{ openshift_name }}"] } ]}
+ ]
+ }
+ }'
+ spec:
+ storageClassName: {{ vol.sc | default('kaas-lst-' + pvprefix) }}
+ persistentVolumeReclaimPolicy: Retain
+ local:
+ path: "{{ mntpath }}{{ path }}"
+ readOnly: {{ not (vol.write | default(false)) }}
+ accessModes:
+ - ReadWriteOnce
+ capacity:
+ storage: {{ vol.capacity | default(kaas_default_volume_capacity) }}
+{% endfor %}
+{% endfor %}
diff --git a/roles/ands_kaas/templates/50-kaas-pods.yml.j2 b/roles/ands_kaas/templates/50-kaas-pods.yml.j2
index 761004d..8c7fe85 100644
--- a/roles/ands_kaas/templates/50-kaas-pods.yml.j2
+++ b/roles/ands_kaas/templates/50-kaas-pods.yml.j2
@@ -1,14 +1,20 @@
#jinja2: trim_blocks: "true", lstrip_blocks: "false"
---
+{% set app = app | default('{}') %}
apiVersion: v1
kind: Template
metadata:
- name: {{ name | default(kaas_project) }}-pods
+ name: {{ appname | default(kaas_project) }}-pods
annotations:
- descriptions: {{ kaas_project_config.description | default(name | default(kaas_project) ~ " auto-generated pod template") }}
+ descriptions: {{ kaas_project_config.description | default(appname | default(kaas_project) ~ " auto-generated pod template") }}
+{% set applabels = ( app.labels | default({}) | combine( { 'app': appname }) ) if appname is defined else (app.labels | default({})) %}
+{% if applabels | length > 0 %}
+ labels: {{ applabels | to_json }}
+{% endif %}
objects:
{% for name, pod in pods.iteritems() %}
{% set kind = pod.kind | default('DeploymentConfig') %}
+ {% set podname = pod.name | default(name) | regex_replace('_','-') %}
{% if pod.enabled | default(true) %}
{% set pubkey = "kaas_" ~ name ~ "_pubkey" %}
{% set privkey = "kaas_" ~ name ~ "_privkey" %}
@@ -17,19 +23,27 @@ objects:
{% set pod = pod[pod.variant] %}
{% endif %}
{% set sched = pod.sched | default({}) %}
+ {% set service = pod.service | default({}) %}
+ {% set headless = (service.headles | default(false)) if kind == 'StatefulSet' else false %}
+ {% set network = pod.network | default({}) %}
+ {% set hostnet = network.host | default(false) %}
{% set node_selector = (sched.selector is defined) | ternary(sched.selector, ands_default_node_selector | combine(sched.restrict | default({}))) %}
+ {% set labels = pod.general_labels | default({}) | combine(applabels) %}
{% if pod.service is defined %}
- {% if kind == 'StatefulSet' and pod.service.ports is defined %}
+ {% if headless and pod.service.ports is defined %}
- apiVersion: v1
kind: Service
metadata:
- name: {{ pod.name | default(name) }}-ss
+ name: {{ podname }}-ss
annotations: {{ pod.service.annotations | default({}) | combine({"service.alpha.kubernetes.io/tolerate-unready-endpoints": "true" }) | to_json }}
+ {% if labels | length > 0 %}
+ labels: {{ labels | to_json }}
+ {% endif %}
spec:
clusterIP: None
publishNotReadyAddresses: True
selector:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
ports:
{% for port in pod.service.ports %}
{% set portmap = (port | string).split('/') %}
@@ -41,13 +55,16 @@ objects:
- apiVersion: v1
kind: Service
metadata:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
{% if pod.service.annotations is defined %}
annotations: {{ pod.service.annotations | to_json }}
{% endif %}
+ {% if labels | length > 0 %}
+ labels: {{ labels | to_json }}
+ {% endif %}
spec:
selector:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
{% if pod.service.ip is defined %}
clusterIP: {{ pod.service.ip }}
{% endif %}
@@ -65,12 +82,15 @@ objects:
- apiVersion: v1
kind: Route
metadata:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
+ {% if labels | length > 0 %}
+ labels: {{ labels | to_json }}
+ {% endif %}
spec:
host: {{ pod.service.host }}
to:
kind: Service
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
port:
targetPort: {{ (first_port[1] is defined) | ternary(first_port[1], first_port[0]) }}
{% if (first_port[0] == "80") %}
@@ -95,7 +115,10 @@ objects:
- apiVersion: {{ kaas_openshift_api_versions[kind] | default('v1') }}
kind: {{ kind }}
metadata:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
+ {% if labels | length > 0 %}
+ labels: {{ labels | to_json }}
+ {% endif %}
spec:
replicas: {{ ( sched | default({})).replicas | default(1) }}
revisionHistoryLimit: 2
@@ -111,25 +134,59 @@ objects:
triggers:
- type: ConfigChange
{% if kind == 'StatefulSet' %}
- serviceName: {{ pod.name | default(name) }}-ss
+ {% if headless %}
+ serviceName: {{ podname }}-ss
+ {% else %}
+ serviceName: {{ podname }}
+ {% endif %}
selector:
matchLabels:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
{% else %}
selector:
- name: {{ pod.name | default(name) }}
+ name: {{ podname }}
{% endif %}
+ {% if pod.pvc is defined %}
+ volumeClaimTemplates:
+ {% for name, pvc in pod.pvc.iteritems() %}
+ {% set pvcname = name | regex_replace('_','-') %}
+ {% set pv = kaas_project_local_volumes[pvcname] | default({}) %}
+ {% set oc_name = pv.name | default(pvcname) | regex_replace('_','-') %}
+ {% if oc_name | regex_search("^" + kaas_project) %}
+ {% set pvname = oc_name %}
+ {% else %}
+ {% set pvname = (kaas_project + "-" + oc_name) | regex_replace('_','-') %}
+ {% endif %}
+ - metadata:
+ name: {{ pvcname }}
+ spec:
+ storageClassName: {{ pvc.sc | default(pv.sc | default('kaas-lst-' + pvname)) }}
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ pvc.capacity | default(pv.capacity | default(kaas_default_volume_capacity)) }}
+ {% endfor %}
+ {% endif %}
template:
metadata:
- name: {{ pod.name | default(name) }}
- {% if kind == 'StatefulSet' %}
+ name: {{ podname }}
+ {% if headless %}
annotations: {{ pod.annotations | default({}) | combine({"pod.alpha.kubernetes.io/initialized": "true"}) | to_json }}
{% elif pod.annotations is defined %}
annotations: {{ pod.annotations | to_json }}
{% endif %}
- labels:
- name: {{ pod.name | default(name) }}
+ labels: {{ pod.labels | default({}) | combine(labels) | combine({'name': podname, 'app': (appname | default('kaas'))}) | to_json }}
spec:
+ {% if pod.sa is defined %}
+ serviceAccountName: {{ pod.sa }}
+ {% endif %}
+ hostNetwork: {{ hostnet }}
+ {% if (headless) and (hostnet) %}
+ dnsPolicy: {{ network.dns_policy | default('ClusterFirstWithHostNet') }}
+ {% elif network.dns_policy is defined %}
+ dnsPolicy: {{ network.dns_policy }}
+ {% endif %}
{% if node_selector | length > 0 %}
nodeSelector: {{ node_selector | to_json }}
{% endif %}
@@ -140,10 +197,12 @@ objects:
{% for img in pod.images %}
{% set imgidx = loop.index %}
{% for vol in (img.mappings | default([])) %}
- {% set oc_name = vol.name | default(name) | regex_replace('_','-') %}
+ {% if (vol.name | default(name)) in kaas_project_volumes.keys() %}
+ {% set oc_name = vol.name | default(name) | regex_replace('_','-') %}
- name: vol-{{imgidx}}-{{loop.index}}
persistentVolumeClaim:
claimName: {{ oc_name }}
+ {% endif %}
{% endfor %}
{% for vol in (img.hostpath | default([])) %}
- name: host-{{imgidx}}-{{loop.index}}
@@ -170,7 +229,7 @@ objects:
containers:
{% for img in pod.images %}
{% set imgidx = loop.index %}
- - name: {{ img.name | default(pod.name) | default(name) }}
+ - name: {{ img.name | default(podname) }}
image: {{ img.image }}
imagePullPolicy: {{ img.pull | default('Always') }}
{% if (img.command is defined) %}
@@ -179,13 +238,22 @@ objects:
{% if img.ports is defined %}
ports:
{% for port in img.ports %}
+ {% if hostnet %}
+ {% set portmap = (port | string).split('/') %}
+ - containerPort: {{ (portmap[1] is defined) | ternary(portmap[1], portmap[0]) }}
+ hostPort: {{ portmap[0] }}
+ {% else %}
- containerPort: {{ port }}
+ {% endif %}
{% endfor %}
{% elif pod.service.ports is defined %}
ports:
{% for port in pod.service.ports %}
{% set portmap = (port | string).split('/') %}
- containerPort: {{ (portmap[1] is defined) | ternary(portmap[1], portmap[0]) }}
+ {% if hostnet %}
+ hostPort: {{ portmap[0] }}
+ {% endif %}
{% endfor %}
{% endif %}
{% if kind == 'StatefulSet' %}
@@ -226,7 +294,12 @@ objects:
{% if img.mappings is defined or img.hostpath is defined %}
volumeMounts:
{% for vol in (img.mappings | default([])) %}
+ {% if vol.name in kaas_project_volumes.keys() %}
- name: vol-{{imgidx}}-{{loop.index}}
+ {% elif vol.name in kaas_project_local_volumes.keys() %}
+ {% set pvcname = vol.name | regex_replace('_','-') %}
+ - name: {{ pvcname }}
+ {% endif %}
subPath: {{ vol.path | default("") }}
mountPath: {{ vol.mount }}
{% endfor %}
diff --git a/roles/ands_network/defaults/main.yml b/roles/ands_network/defaults/main.yml
index 139e8b3..0170370 100644
--- a/roles/ands_network/defaults/main.yml
+++ b/roles/ands_network/defaults/main.yml
@@ -1 +1,3 @@
configure_network: "{{ ands_configure_network | default(false) }}"
+firewall_template_path: "{{ ands_paths.provision }}/firewall/{{ ansible_hostname }}"
+firewall_services: [ 'galera', 'netpipe' ] \ No newline at end of file
diff --git a/roles/ands_network/files/galera.xml b/roles/ands_network/files/galera.xml
new file mode 100644
index 0000000..15f908b
--- /dev/null
+++ b/roles/ands_network/files/galera.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<service>
+ <short>MySQL/Galera</short>
+ <description>MySQL/Galera Database Server</description>
+ <port protocol="tcp" port="3306"/>
+ <port protocol="tcp" port="4567"/>
+ <port protocol="udp" port="4567"/>
+ <port protocol="tcp" port="4568"/>
+ <port protocol="tcp" port="4444"/>
+</service>
diff --git a/roles/ands_network/files/netpipe.xml b/roles/ands_network/files/netpipe.xml
new file mode 100644
index 0000000..0e7f355
--- /dev/null
+++ b/roles/ands_network/files/netpipe.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<service>
+ <short>NetPIPE</short>
+ <description>NetPIPE network benchmark</description>
+ <port protocol="tcp" port="5002"/>
+</service>
diff --git a/roles/ands_network/tasks/add_names.yml b/roles/ands_network/tasks/add_names.yml
new file mode 100644
index 0000000..3edde38
--- /dev/null
+++ b/roles/ands_network/tasks/add_names.yml
@@ -0,0 +1,28 @@
+# Currently EXCLUDED
+# Kind of post-install. We can include this in maitain later.
+
+# We should not do it before Gluster peers are probed, otherwise everything will fail.
+# Some peers will have names and others IPs.
+- name: Configure all storage hostnames in /etc/hosts
+ lineinfile: dest="/etc/hosts" line="{{ ip }} {{ fqdn }} {{ hostname }}" regexp="{{ fqdn }}" state="present"
+ when:
+ - hostvars[item]['ands_facts_configured'] is defined
+ vars:
+ ip: "{{ hostvars[item]['ands_storage_ip'] }}"
+ hostname: "{{ hostvars[item]['ands_hostname_storage'] }}"
+ fqdn: "{{ hostvars[item]['ands_hostname_storage'] ~ ands_inner_dot_domain }}"
+ with_inventory_hostnames:
+ - nodes
+ - new_nodes
+
+- name: Configure all public hostnames in /etc/hosts
+ lineinfile: dest="/etc/hosts" line="{{ ip }} {{ fqdn }} {{ hostname }}" regexp="{{ fqdn }}" state="present"
+ when:
+ - hostvars[item]['ands_facts_configured'] is defined
+ vars:
+ ip: "{{ hostvars[item]['ands_openshift_public_ip'] }}"
+ hostname: "{{ hostvars[item]['ands_hostname_public'] }}"
+ fqdn: "{{ hostvars[item]['ands_hostname_public'] ~ ands_inner_dot_domain }}"
+ with_inventory_hostnames:
+ - nodes
+ - new_nodes
diff --git a/roles/ands_network/tasks/common.yml b/roles/ands_network/tasks/common.yml
index f2fda00..940cde7 100644
--- a/roles/ands_network/tasks/common.yml
+++ b/roles/ands_network/tasks/common.yml
@@ -7,7 +7,6 @@
# - nodes
# - new_nodes
-
# This will not work properly unless 'ands_facts' are executed on all nodes.... This is checked by evaluating if 'ands_openshift_fqdn' is defined
- name: Configure all cluster hostnames in /etc/hosts
lineinfile: dest="/etc/hosts" line="{{ ip }} {{ fqdn }} {{ hostname }}" regexp="{{ fqdn }}" state="present"
diff --git a/roles/ands_network/tasks/firewall.yml b/roles/ands_network/tasks/firewall.yml
new file mode 100644
index 0000000..d5ba5f3
--- /dev/null
+++ b/roles/ands_network/tasks/firewall.yml
@@ -0,0 +1,32 @@
+- name: Ensure firewall template directory exists
+ file: path="{{ firewall_template_path }}" state="directory" mode=0644 owner=root group=root
+
+#Just in case we already added but not reloaded yet
+#- name: Reload firewalld rules
+# shell: firewall-cmd --reload
+
+- name: Get list of existing firewalld services
+ shell: "firewall-cmd --get-services | tr ' ' '\n'"
+ changed_when: false
+ register: services
+
+- name: Configure missing firewalld services
+ include_tasks: firewall_service.yml
+ with_items: "{{ firewall_services }}"
+ vars:
+ servicelist: "{{ services.stdout_lines }}"
+ loop_control:
+ loop_var: service
+
+- name: Reload firewalld rules
+ shell: firewall-cmd --reload
+
+- name: Enable MySQL and Galera services if ands_hostnet_db is enabled
+ firewalld: service="{{ item }}" state="enabled" permanent="true" immediate="true"
+ when: ands_hostnet_db | default(false)
+ with_items:
+ - mysql
+ - galera
+
+- name: Reload firewalld rules
+ shell: firewall-cmd --reload
diff --git a/roles/ands_network/tasks/firewall_service.yml b/roles/ands_network/tasks/firewall_service.yml
new file mode 100644
index 0000000..98bc866
--- /dev/null
+++ b/roles/ands_network/tasks/firewall_service.yml
@@ -0,0 +1,13 @@
+- name: "Copy firewalld service '{{ service }}'"
+ copy: src="{{ service }}.xml" dest="{{ firewall_template_path }}/{{ service }}.xml" owner=root group=root mode="0644"
+ register: result
+
+- name: "Delete old version of firewalld service '{{ service }}'"
+ command: "firewall-offline-cmd --remove-service={{ service }}"
+ when:
+ - service in servicelist
+ - result | changed
+
+- name: "Create firewalld service '{{ service }}'"
+ command: "firewall-offline-cmd --new-service-from-file='{{ firewall_template_path }}/{{ service }}.xml' --name={{ service }}"
+ when: (service not in servicelist) or (result | changed)
diff --git a/roles/ands_network/tasks/nm_configure.yml b/roles/ands_network/tasks/nm_configure.yml
index 4482705..57e40ca 100644
--- a/roles/ands_network/tasks/nm_configure.yml
+++ b/roles/ands_network/tasks/nm_configure.yml
@@ -1,4 +1,3 @@
-
- name: install needed network manager libs
yum: name='{{ item }}' state=installed
with_items:
@@ -21,6 +20,16 @@
cidr: "{{ ands_storage_cidr }}"
force: true
+- name: configure bridged openshift nework
+ include_tasks: nm_configure_connection.yml
+ vars:
+ bridge: "{{ ands_bridge }}"
+ name: "openshift"
+ iface: "{{ ands_inner_interface }}"
+ cidr: "{{ ands_openshift_cidr }}"
+ force: true
+ when: ands_enable_cnr | default(false)
+
- name: configure openshift nework
include_tasks: nm_configure_connection.yml
vars:
@@ -28,6 +37,8 @@
iface: "{{ ands_inner_interface }}"
cidr: "{{ ands_openshift_cidr }}"
force: true
+ when: not (ands_enable_cnr | default(false))
+
- name: configure public nework
include_tasks: nm_configure_connection.yml
@@ -37,3 +48,5 @@
cidr: "{{ ands_openshift_public_cidr }}"
alias: true
+- name: Configure firewall
+ include_tasks: firewall.yml
diff --git a/roles/ands_network/tasks/nm_configure_connection.yml b/roles/ands_network/tasks/nm_configure_connection.yml
index 18fc91e..9354fbf 100644
--- a/roles/ands_network/tasks/nm_configure_connection.yml
+++ b/roles/ands_network/tasks/nm_configure_connection.yml
@@ -1,15 +1,16 @@
-- name: "detect nm connection corresponding to interface '{{ iface }}'"
+- name: "detect nm connection corresponding to interface '{{ bridge | default(iface) }}'"
shell: "nmcli d show {{ iface | quote }} | grep CONNECTION | cut -d ':' -f 2- | sed -E -e 's/^[[:space:]]+//' | grep '^[[:alpha:]]'"
register: conres
failed_when: false
changed_when: false
-- name: "check if the requested ip '{{ cidr }}' is present on the interface '{{ iface }}'"
+- name: "check if the requested ip '{{ cidr }}' is present on the interface '{{ biface }}'"
set_fact:
ip_present: "{{ cidr | ipaddr('address') in ips }}"
vars:
- eth: "{{ hostvars[inventory_hostname]['ansible_' + iface] | default({}) }}"
+ biface: "{{ bridge | default(iface) }}"
+ eth: "{{ hostvars[inventory_hostname]['ansible_' + biface] | default({}) }}"
ipv4: "{{ eth['ipv4'] | default({}) }}"
q: "{{ eth | json_query('ipv4_secondaries[*].address') }}"
sec: "{{ ((q == ands_none) or (q == '')) | ternary([], q) }}"
@@ -27,9 +28,24 @@
- not (alias | default(false))
- not ip_present
-- name: "configure storage network interface '{{ iface }}' to '{{ cidr }}'"
+- name: "create bridge '{{ bridge }}' with cidr '{{ cidr }}'"
+ command: "nmcli connection add type bridge ifname {{ bridge | quote }} con-name {{ name }} ip4 {{ cidr }}"
+ when:
+ - bridge is defined
+ - (conres.rc != 0) or (not (delres | skipped))
+ - (conres.rc != 0) or (not (alias | default(false)))
+
+- name: "connect bridge '{{ bridge }}' to interface '{{ iface }}'"
+ command: "nmcli connection add type bridge-slave ifname {{ iface | quote }} master {{ bridge | quote }}"
+ when:
+ - bridge is defined
+ - (conres.rc != 0) or (not (delres | skipped))
+ - (conres.rc != 0) or (not (alias | default(false)))
+
+- name: "configure network interface '{{ iface }}' to '{{ cidr }}'"
command: "nmcli connection add type infiniband ifname {{ iface | quote }} con-name {{ name }} ip4 {{ cidr }}"
when:
+ - bridge is not defined
- (conres.rc != 0) or (not (delres | skipped))
- (conres.rc != 0) or (not (alias | default(false)))
@@ -41,10 +57,11 @@
- conres.rc == 0
- not ip_present
-
-- name: "add ip alias '{{ cidr }}' to network interface '{{ iface }}'"
- command: "nmcli connection up {{ conres.stdout | quote }}"
+- name: "start connection {{ cname }}"
+ command: "nmcli connection up {{ cname | quote }}"
register: alres
+ vars:
+ cname: "{{ (conres.stdout == '') | ternary(name, conres.stdout) }}"
when:
- not(alres | skipped)
- alres | succeeded
diff --git a/roles/openshift_resource/tasks/template.yml b/roles/openshift_resource/tasks/template.yml
index 188599f..3469464 100644
--- a/roles/openshift_resource/tasks/template.yml
+++ b/roles/openshift_resource/tasks/template.yml
@@ -21,10 +21,13 @@
with_sequence: start=0 count="{{resources | default([]) | length}}"
when: ((recreate|default(false)) or (results | changed)) and (results.results[item|int].rc == 0)
- - name: "{{ template }}: Populate resources to {{project}}"
- shell: "oc process -n {{project}} -f '{{ template_path }}/{{template}}' {{ template_args | default('') }} | oc create -n {{project}} -f - {{ create_args | default('') }}"
+# Replace often complains on various immutable variables it can't change. We ignore.
+ - name: "{{ template }}: Populate resources to {{project}} ({{ replace | ternary('replace', 'create') }})"
+ shell: "oc process -n {{project}} -f '{{ template_path }}/{{template}}' {{ template_args | default('') }} | oc {{ replace | ternary('replace', 'create') }} -n {{project}} -f - {{ create_args | default('') }}"
+ register: status
+ failed_when: (status.rc != 0) and not (replace | default(false))
when:
- - (recreate|default(false)) or (results | changed)
+ - (recreate | default(false)) or (replace | default(false)) or (results | changed)
- resources | length > 0
run_once: true