From 0c18c742c60e5c4acd609d682caae7f7ce8840cd Mon Sep 17 00:00:00 2001
From: Andrew Butcher <abutcher@redhat.com>
Date: Wed, 18 Nov 2015 14:34:47 -0500
Subject: Create nfs host group with registry volume attachment.

---
 inventory/byo/hosts.origin.example                 |  6 +++
 playbooks/aws/openshift-cluster/config.yml         |  1 +
 playbooks/byo/openshift-cluster/config.yml         |  1 +
 .../upgrades/v3_0_minor/upgrade.yml                |  1 +
 .../upgrades/v3_0_to_v3_1/upgrade.yml              |  1 +
 playbooks/common/openshift-cluster/config.yml      |  2 +
 .../common/openshift-cluster/evaluate_groups.yml   | 16 +++++++
 playbooks/common/openshift-master/config.yml       | 10 ++++-
 playbooks/common/openshift-nfs/config.yml          |  5 +++
 playbooks/common/openshift-nfs/filter_plugins      |  1 +
 playbooks/common/openshift-nfs/lookup_plugins      |  1 +
 playbooks/common/openshift-nfs/roles               |  1 +
 playbooks/common/openshift-nfs/service.yml         | 18 ++++++++
 playbooks/gce/openshift-cluster/config.yml         |  1 +
 playbooks/libvirt/openshift-cluster/config.yml     |  1 +
 playbooks/openstack/openshift-cluster/config.yml   |  1 +
 roles/openshift_facts/library/openshift_facts.py   |  8 +++-
 roles/openshift_registry/tasks/main.yml            | 18 +++++++-
 roles/openshift_storage_nfs/README.md              | 52 ++++++++++++++++++++++
 roles/openshift_storage_nfs/defaults/main.yml      |  8 ++++
 roles/openshift_storage_nfs/handlers/main.yml      |  6 +++
 roles/openshift_storage_nfs/meta/main.yml          | 15 +++++++
 roles/openshift_storage_nfs/tasks/main.yml         | 49 ++++++++++++++++++++
 roles/openshift_storage_nfs/templates/exports.j2   |  1 +
 24 files changed, 220 insertions(+), 4 deletions(-)
 create mode 100644 playbooks/common/openshift-nfs/config.yml
 create mode 120000 playbooks/common/openshift-nfs/filter_plugins
 create mode 120000 playbooks/common/openshift-nfs/lookup_plugins
 create mode 120000 playbooks/common/openshift-nfs/roles
 create mode 100644 playbooks/common/openshift-nfs/service.yml
 create mode 100644 roles/openshift_storage_nfs/README.md
 create mode 100644 roles/openshift_storage_nfs/defaults/main.yml
 create mode 100644 roles/openshift_storage_nfs/handlers/main.yml
 create mode 100644 roles/openshift_storage_nfs/meta/main.yml
 create mode 100644 roles/openshift_storage_nfs/tasks/main.yml
 create mode 100644 roles/openshift_storage_nfs/templates/exports.j2

diff --git a/inventory/byo/hosts.origin.example b/inventory/byo/hosts.origin.example
index 6f015c404..e6e519d78 100644
--- a/inventory/byo/hosts.origin.example
+++ b/inventory/byo/hosts.origin.example
@@ -6,6 +6,7 @@ masters
 nodes
 etcd
 lb
+nfs
 
 # Set variables common for all OSEv3 hosts
 [OSEv3:vars]
@@ -167,6 +168,11 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',
 # Configure dnsIP in the node config
 #openshift_dns_ip=172.30.0.1
 
+# NFS Options
+#openshift_nfs_exports_dir=/var/export
+#openshift_nfs_registry_volume=regvol
+#openshift_nfs_export_options='*(rw,sync,all_squash)'
+
 # host group for masters
 [masters]
 ose3-master[1:3]-ansible.test.example.com
diff --git a/playbooks/aws/openshift-cluster/config.yml b/playbooks/aws/openshift-cluster/config.yml
index 50fe42d6c..f46988432 100644
--- a/playbooks/aws/openshift-cluster/config.yml
+++ b/playbooks/aws/openshift-cluster/config.yml
@@ -15,6 +15,7 @@
     g_etcd_hosts:   "{{ (groups['tag_host-type_etcd']|default([]))   | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_lb_hosts:     "{{ (groups['tag_host-type_lb']|default([]))     | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_master_hosts: "{{ (groups['tag_host-type_master']|default([])) | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
+    g_nfs_hosts:   "{{ (groups['tag_host-type_nfs']|default([]))   | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_node_hosts:   "{{ (groups['tag_host-type_node']|default([]))   | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_ssh_user: "{{ hostvars.localhost.g_ssh_user_tmp }}"
     g_sudo: "{{ hostvars.localhost.g_sudo_tmp }}"
diff --git a/playbooks/byo/openshift-cluster/config.yml b/playbooks/byo/openshift-cluster/config.yml
index ba8fe0a52..eecf95994 100644
--- a/playbooks/byo/openshift-cluster/config.yml
+++ b/playbooks/byo/openshift-cluster/config.yml
@@ -3,6 +3,7 @@
   vars:
     g_etcd_hosts: "{{ groups.etcd | default([]) }}"
     g_master_hosts: "{{ groups.masters | default([]) }}"
+    g_nfs_hosts: "{{ groups.nfs | default([]) }}"
     g_node_hosts: "{{ groups.nodes | default([]) }}"
     g_lb_hosts: "{{ groups.lb | default([]) }}"
     openshift_cluster_id: "{{ cluster_id | default('default') }}"
diff --git a/playbooks/byo/openshift-cluster/upgrades/v3_0_minor/upgrade.yml b/playbooks/byo/openshift-cluster/upgrades/v3_0_minor/upgrade.yml
index 56e79e8c2..c3358eb4b 100644
--- a/playbooks/byo/openshift-cluster/upgrades/v3_0_minor/upgrade.yml
+++ b/playbooks/byo/openshift-cluster/upgrades/v3_0_minor/upgrade.yml
@@ -3,6 +3,7 @@
   vars:
     g_etcd_hosts: "{{ groups.etcd | default([]) }}"
     g_master_hosts: "{{ groups.masters | default([]) }}"
+    g_nfs_hosts: "{{ groups.nfs | default([]) }}"
     g_node_hosts: "{{ groups.nodes | default([]) }}"
     g_lb_hosts: "{{ groups.lb | default([]) }}"
     openshift_cluster_id: "{{ cluster_id | default('default') }}"
diff --git a/playbooks/byo/openshift-cluster/upgrades/v3_0_to_v3_1/upgrade.yml b/playbooks/byo/openshift-cluster/upgrades/v3_0_to_v3_1/upgrade.yml
index b4b4f3ec0..960c00087 100644
--- a/playbooks/byo/openshift-cluster/upgrades/v3_0_to_v3_1/upgrade.yml
+++ b/playbooks/byo/openshift-cluster/upgrades/v3_0_to_v3_1/upgrade.yml
@@ -3,6 +3,7 @@
   vars:
     g_etcd_hosts: "{{ groups.etcd | default([]) }}"
     g_master_hosts: "{{ groups.masters | default([]) }}"
+    g_nfs_hosts: "{{ groups.nfs | default([]) }}"
     g_node_hosts: "{{ groups.nodes | default([]) }}"
     g_lb_hosts: "{{ groups.lb | default([]) }}"
     openshift_cluster_id: "{{ cluster_id | default('default') }}"
diff --git a/playbooks/common/openshift-cluster/config.yml b/playbooks/common/openshift-cluster/config.yml
index 482fa8441..a2a2629a7 100644
--- a/playbooks/common/openshift-cluster/config.yml
+++ b/playbooks/common/openshift-cluster/config.yml
@@ -3,6 +3,8 @@
 
 - include: ../openshift-etcd/config.yml
 
+- include: ../openshift-nfs/config.yml
+
 - include: ../openshift-master/config.yml
 
 - include: ../openshift-node/config.yml
diff --git a/playbooks/common/openshift-cluster/evaluate_groups.yml b/playbooks/common/openshift-cluster/evaluate_groups.yml
index 6343a2567..db7105ed5 100644
--- a/playbooks/common/openshift-cluster/evaluate_groups.yml
+++ b/playbooks/common/openshift-cluster/evaluate_groups.yml
@@ -21,6 +21,14 @@
       msg: This playbook requires g_lb_hosts to be set
     when: g_lb_hosts is not defined
 
+  - fail:
+      msg: This playbook requires g_nfs_hosts to be set
+    when: g_nfs_hosts is not defined
+
+  - fail:
+      msg: The nfs group must be limited to one host
+    when: (groups[g_nfs_hosts] | default([])) | length > 1
+
   - name: Evaluate oo_etcd_to_config
     add_host:
       name: "{{ item }}"
@@ -81,3 +89,11 @@
       ansible_ssh_user: "{{ g_ssh_user | default(omit) }}"
       ansible_sudo: "{{ g_sudo | default(omit) }}"
     with_items: "{{ g_lb_hosts | default([]) }}"
+
+  - name: Evaluate oo_nfs_to_config
+    add_host:
+      name: "{{ item }}"
+      groups: oo_nfs_to_config
+      ansible_ssh_user: "{{ g_ssh_user | default(omit) }}"
+      ansible_sudo: "{{ g_sudo | default(omit) }}"
+    with_items: "{{ g_nfs_hosts | default([]) }}"
diff --git a/playbooks/common/openshift-master/config.yml b/playbooks/common/openshift-master/config.yml
index dd638487a..eff4337cb 100644
--- a/playbooks/common/openshift-master/config.yml
+++ b/playbooks/common/openshift-master/config.yml
@@ -394,7 +394,15 @@
 
 - name: Create services
   hosts: oo_first_master
+  vars:
+    attach_registry_volume: "{{ groups.oo_nfs_to_config | length > 0 }}"
+  pre_tasks:
+  - set_fact:
+      nfs_host: "{{ groups.oo_nfs_to_config.0 }}"
+      registry_volume_path: "{{ hostvars[groups.oo_nfs_to_config.0].openshift.nfs.exports_dir + '/' + hostvars[groups.oo_nfs_to_config.0].openshift.nfs.registry_volume }}"
+    when: attach_registry_volume | bool
   roles:
   - role: openshift_router
     when: openshift.master.infra_nodes is defined
-  #- role: openshift_registry
+  - role: openshift_registry
+    when: openshift.master.infra_nodes is defined and attach_registry_volume | bool
diff --git a/playbooks/common/openshift-nfs/config.yml b/playbooks/common/openshift-nfs/config.yml
new file mode 100644
index 000000000..e3f5c17ca
--- /dev/null
+++ b/playbooks/common/openshift-nfs/config.yml
@@ -0,0 +1,5 @@
+---
+- name: Configure nfs hosts
+  hosts: oo_nfs_to_config
+  roles:
+  - role: openshift_storage_nfs
diff --git a/playbooks/common/openshift-nfs/filter_plugins b/playbooks/common/openshift-nfs/filter_plugins
new file mode 120000
index 000000000..99a95e4ca
--- /dev/null
+++ b/playbooks/common/openshift-nfs/filter_plugins
@@ -0,0 +1 @@
+../../../filter_plugins
\ No newline at end of file
diff --git a/playbooks/common/openshift-nfs/lookup_plugins b/playbooks/common/openshift-nfs/lookup_plugins
new file mode 120000
index 000000000..ac79701db
--- /dev/null
+++ b/playbooks/common/openshift-nfs/lookup_plugins
@@ -0,0 +1 @@
+../../../lookup_plugins
\ No newline at end of file
diff --git a/playbooks/common/openshift-nfs/roles b/playbooks/common/openshift-nfs/roles
new file mode 120000
index 000000000..e2b799b9d
--- /dev/null
+++ b/playbooks/common/openshift-nfs/roles
@@ -0,0 +1 @@
+../../../roles/
\ No newline at end of file
diff --git a/playbooks/common/openshift-nfs/service.yml b/playbooks/common/openshift-nfs/service.yml
new file mode 100644
index 000000000..20c8ca248
--- /dev/null
+++ b/playbooks/common/openshift-nfs/service.yml
@@ -0,0 +1,18 @@
+---
+- name: Populate g_service_nfs host group if needed
+  hosts: localhost
+  gather_facts: no
+  tasks:
+  - fail: msg="new_cluster_state is required to be injected in this playbook"
+    when: new_cluster_state is not defined
+
+  - name: Evaluate g_service_nfs
+    add_host: name={{ item }} groups=g_service_nfs
+    with_items: oo_host_group_exp | default([])
+
+- name: Change state on nfs instance(s)
+  hosts: g_service_nfs
+  connection: ssh
+  gather_facts: no
+  tasks:
+    - service: name=nfs-server state="{{ new_cluster_state }}"
diff --git a/playbooks/gce/openshift-cluster/config.yml b/playbooks/gce/openshift-cluster/config.yml
index 5bf98c2d5..4a76e406a 100644
--- a/playbooks/gce/openshift-cluster/config.yml
+++ b/playbooks/gce/openshift-cluster/config.yml
@@ -20,6 +20,7 @@
     g_etcd_hosts:   "{{ (groups['tag_host-type-etcd']|default([]))   | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_lb_hosts:     "{{ (groups['tag_host-type-lb']|default([]))     | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_master_hosts: "{{ (groups['tag_host-type-master']|default([])) | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
+    g_nfs_hosts:   "{{ (groups['tag_host-type-nfs']|default([]))   | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_node_hosts:   "{{ (groups['tag_host-type-node']|default([]))   | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_ssh_user: "{{ hostvars.localhost.g_ssh_user_tmp }}"
     g_sudo: "{{ hostvars.localhost.g_sudo_tmp }}"
diff --git a/playbooks/libvirt/openshift-cluster/config.yml b/playbooks/libvirt/openshift-cluster/config.yml
index b84bde084..dcaec3924 100644
--- a/playbooks/libvirt/openshift-cluster/config.yml
+++ b/playbooks/libvirt/openshift-cluster/config.yml
@@ -19,6 +19,7 @@
     g_etcd_hosts:   "{{ (groups['tag_host-type-etcd']|default([]))   | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_lb_hosts:     "{{ (groups['tag_host-type-lb']|default([]))     | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_master_hosts: "{{ (groups['tag_host-type-master']|default([])) | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
+    g_nfs_hosts:   "{{ (groups['tag_host-type-node']|default([]))   | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_node_hosts:   "{{ (groups['tag_host-type-node']|default([]))   | intersect((groups['tag_env-' ~ cluster_id]|default([]))) }}"
     g_ssh_user: "{{ hostvars.localhost.g_ssh_user_tmp }}"
     g_sudo: "{{ hostvars.localhost.g_sudo_tmp }}"
diff --git a/playbooks/openstack/openshift-cluster/config.yml b/playbooks/openstack/openshift-cluster/config.yml
index da7b5cc49..07a9d9488 100644
--- a/playbooks/openstack/openshift-cluster/config.yml
+++ b/playbooks/openstack/openshift-cluster/config.yml
@@ -14,6 +14,7 @@
     g_etcd_hosts:   "{{ (groups['tag_host-type_etcd']|default([]))   | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_lb_hosts:     "{{ (groups['tag_host-type_lb']|default([]))     | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_master_hosts: "{{ (groups['tag_host-type_master']|default([])) | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
+    g_nfs_hosts:   "{{ (groups['tag_host-type_nfs']|default([]))   | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_node_hosts:   "{{ (groups['tag_host-type_node']|default([]))   | intersect((groups['tag_env_' ~ cluster_id]|default([]))) }}"
     g_ssh_user: "{{ hostvars.localhost.g_ssh_user_tmp }}"
     g_sudo: "{{ hostvars.localhost.g_sudo_tmp }}"
diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py
index e557853b1..e52c2cbed 100755
--- a/roles/openshift_facts/library/openshift_facts.py
+++ b/roles/openshift_facts/library/openshift_facts.py
@@ -985,7 +985,7 @@ class OpenShiftFacts(object):
         Raises:
             OpenShiftFactsUnsupportedRoleError:
     """
-    known_roles = ['common', 'master', 'node', 'master_sdn', 'node_sdn', 'etcd']
+    known_roles = ['common', 'master', 'node', 'master_sdn', 'node_sdn', 'etcd', 'nfs']
 
     def __init__(self, role, filename, local_facts, additive_facts_to_overwrite=False):
         self.changed = False
@@ -1078,6 +1078,12 @@ class OpenShiftFacts(object):
             node = dict(labels={}, annotations={}, portal_net='172.30.0.0/16',
                         iptables_sync_period='5s', set_node_ip=False)
             defaults['node'] = node
+
+        if 'nfs' in roles:
+            nfs = dict(exports_dir='/var/export', registry_volume='regvol',
+                       export_options='*(rw,sync,all_squash)')
+            defaults['nfs'] = nfs
+
         return defaults
 
     def guess_host_provider(self):
diff --git a/roles/openshift_registry/tasks/main.yml b/roles/openshift_registry/tasks/main.yml
index 749eea5c0..2804e8f2e 100644
--- a/roles/openshift_registry/tasks/main.yml
+++ b/roles/openshift_registry/tasks/main.yml
@@ -1,6 +1,4 @@
 ---
-# This role is unused until we add options for configuring the backend storage
-
 - set_fact: _oreg_images="--images='{{ openshift.master.registry_url }}'"
 
 - set_fact: _oreg_selector="--selector='{{ openshift.master.registry_selector }}'"
@@ -12,3 +10,19 @@
     --credentials={{ openshift_master_config_dir }}/openshift-registry.kubeconfig {{ _oreg_images }}
   register: _oreg_results
   changed_when: "'service exists' not in _oreg_results.stdout"
+
+- name: Determine if nfs volume is already attached
+  command: "{{ openshift.common.client_binary }} get -o template dc/docker-registry --template=\\{\\{.spec.template.spec.volumes\\}\\}"
+  register: registry_volumes_output
+  when: attach_registry_volume | bool
+
+- set_fact:
+    volume_already_attached: "{{ 'server:' + nfs_host in registry_volumes_output.stdout and 'path:' + registry_volume_path in registry_volumes_output.stdout }}"
+  when: attach_registry_volume | bool
+
+- name: Add nfs volume to dc/docker-registry
+  command: >
+    {{ openshift.common.client_binary }} volume dc/docker-registry
+    --add --overwrite --name=registry-storage --mount-path=/registry
+    --source='{"nfs": {"server": "{{ nfs_host }}", "path": "{{ registry_volume_path }}"}}'
+  when: attach_registry_volume | bool and not volume_already_attached | bool
diff --git a/roles/openshift_storage_nfs/README.md b/roles/openshift_storage_nfs/README.md
new file mode 100644
index 000000000..548e146cb
--- /dev/null
+++ b/roles/openshift_storage_nfs/README.md
@@ -0,0 +1,52 @@
+OpenShift NFS Server
+====================
+
+OpenShift NFS Server Installation
+
+Requirements
+------------
+
+This role is intended to be applied to the [nfs] host group which is
+separate from OpenShift infrastructure components.
+
+Requires access to the 'nfs-utils' package.
+
+Role Variables
+--------------
+
+From this role:
+| Name                          | Default value         |                                                  |
+|-------------------------------|-----------------------|--------------------------------------------------|
+| openshift_nfs_exports_dir     | /var/export           | Root export directory.                           |
+| openshift_nfs_registry_volume | regvol                | Registry volume within openshift_nfs_exports_dir |
+| openshift_nfs_export_options  | *(rw,sync,all_squash) | NFS options for configured exports.              |
+
+
+From openshift_common:
+| Name                          | Default Value  |                                        |
+|-------------------------------|----------------|----------------------------------------|
+| openshift_debug_level         | 2              | Global openshift debug log verbosity   |
+
+
+Dependencies
+------------
+
+
+
+Example Playbook
+----------------
+
+- name: Configure nfs hosts
+  hosts: oo_nfs_to_config
+  roles:
+  - role: openshift_storage_nfs
+
+License
+-------
+
+Apache License, Version 2.0
+
+Author Information
+------------------
+
+Andrew Butcher (abutcher@redhat.com)
diff --git a/roles/openshift_storage_nfs/defaults/main.yml b/roles/openshift_storage_nfs/defaults/main.yml
new file mode 100644
index 000000000..e25062c00
--- /dev/null
+++ b/roles/openshift_storage_nfs/defaults/main.yml
@@ -0,0 +1,8 @@
+---
+exports_dir: /var/export
+registry_volume: regvol
+export_options: '*(rw,sync,all_squash)'
+os_firewall_use_firewalld: False
+os_firewall_allow:
+- service: nfs
+  port: "2049/tcp"
diff --git a/roles/openshift_storage_nfs/handlers/main.yml b/roles/openshift_storage_nfs/handlers/main.yml
new file mode 100644
index 000000000..a1377a203
--- /dev/null
+++ b/roles/openshift_storage_nfs/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+- name: restart nfs-server
+  service:
+    name: nfs-server
+    state: restarted
+  when: not (nfs_service_status_changed | default(false))
diff --git a/roles/openshift_storage_nfs/meta/main.yml b/roles/openshift_storage_nfs/meta/main.yml
new file mode 100644
index 000000000..2975daf52
--- /dev/null
+++ b/roles/openshift_storage_nfs/meta/main.yml
@@ -0,0 +1,15 @@
+---
+galaxy_info:
+  author: Andrew Butcher
+  description: OpenShift NFS Server
+  company: Red Hat, Inc.
+  license: Apache License, Version 2.0
+  min_ansible_version: 1.9
+  platforms:
+  - name: EL
+    versions:
+    - 7
+dependencies:
+- { role: os_firewall }
+- { role: openshift_common }
+- { role: openshift_repos }
diff --git a/roles/openshift_storage_nfs/tasks/main.yml b/roles/openshift_storage_nfs/tasks/main.yml
new file mode 100644
index 000000000..64b121ade
--- /dev/null
+++ b/roles/openshift_storage_nfs/tasks/main.yml
@@ -0,0 +1,49 @@
+---
+- name: Set nfs facts
+  openshift_facts:
+    role: nfs
+    local_facts:
+      exports_dir: "{{ openshift_nfs_exports_dir | default(None) }}"
+      export_options: "{{ openshift_nfs_export_options | default(None) }}"
+      registry_volume: "{{ openshift_nfs_registry_volume | default(None) }}"
+
+- name: Install nfs-utils
+  yum:
+    pkg: nfs-utils
+    state: present
+
+- name: Ensure exports directory exists
+  file:
+    path: "{{ openshift.nfs.exports_dir }}"
+    state: directory
+
+- name: Ensure export directories exist
+  file:
+    path: "{{ openshift.nfs.exports_dir }}/{{ item }}"
+    state: directory
+    mode: 0777
+    owner: nfsnobody
+    group: nfsnobody
+  with_items:
+  - "{{ openshift.nfs.registry_volume }}"
+
+- name: Configure exports
+  template:
+    dest: /etc/exports
+    src: exports.j2
+  notify:
+  - restart nfs-server
+
+- name: Enable and start services
+  service:
+    name: "{{ item }}"
+    state: started
+    enabled: yes
+  register: start_result
+  with_items:
+  - nfs-server
+
+- set_fact:
+    nfs_service_status_changed: "{{ True in (start_result.results
+                                    | map(attribute='changed')
+                                    | list) }}"
diff --git a/roles/openshift_storage_nfs/templates/exports.j2 b/roles/openshift_storage_nfs/templates/exports.j2
new file mode 100644
index 000000000..702473040
--- /dev/null
+++ b/roles/openshift_storage_nfs/templates/exports.j2
@@ -0,0 +1 @@
+{{ openshift.nfs.exports_dir }}/{{ openshift.nfs.registry_volume }} {{ openshift.nfs.export_options }}
-- 
cgit v1.2.3