In a glaring oversight the changes made via targetd for nfs exports was lost
on system reboot. This patch fixes that by taking every export that is listed
via `exportfs -v` and writes each entry to /etc/exports.d.
At the moment for updates the code just removes every file that is has
created and re-creates a new file for each entry. Not the most performant
implementation, but it minimizes risk to updating an existing export and not
getting the change written out correctly. In big config testing we may find
that this simple approach is actually faster than opening and checking each file
for correctness and then updating/deleting etc. as needed.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
targetd/nfs.py | 43 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 39 insertions(+), 4 deletions(-)
diff --git a/targetd/nfs.py b/targetd/nfs.py
index 6daf99e..3b157db 100644
--- a/targetd/nfs.py
+++ b/targetd/nfs.py
@@ -13,6 +13,15 @@
from subprocess import Popen, PIPE
import re
+import hashlib
+import os
+import os.path
+
+
+def md5(t):
+ h = hashlib.md5()
+ h.update(t)
+ return h.hexdigest()
def invoke(cmd, raise_exception=True):
@@ -189,12 +198,21 @@ class Export(object):
return "%s%s(%s)" % (self.path.ljust(50), self.host,
self.options_string())
+ def to_export_file(self, file_name):
+ content = "%s %s(%s)\n" % (self.path, self.host,
self.options_string())
+
+ with open(file_name, 'w') as ef:
+ ef.write(content)
+
class Nfs(object):
"""
Python module for configuring NFS exports
"""
- cmd = 'exportfs'
+ CMD = 'exportfs'
+ FILE_PREFIX = 'targetd_'
+
+ EXPORT_FS_CONFIG_DIR = '/etc/exports.d'
def __init__(self):
pass
@@ -204,12 +222,25 @@ class Nfs(object):
return "sys", "krb5", "krb5i", "krb5p"
@staticmethod
+ def _save_exports():
+ #Remove all existing exports that we created
+ for root, dirs, files in os.walk(Nfs.EXPORT_FS_CONFIG_DIR):
+ for f in files:
+ if f[0:len(Nfs.FILE_PREFIX)] == Nfs.FILE_PREFIX:
+ os.remove(os.path.join(root, f))
+
+ #Recreate all existing exports
+ for e in Nfs.exports():
+ fn = "%s%s.exports" % (Nfs.FILE_PREFIX, md5(str(e)))
+ e.to_export_file(os.path.join(Nfs.EXPORT_FS_CONFIG_DIR, fn))
+
+ @staticmethod
def exports():
"""
Return list of exports
"""
rc = []
- ec, out, error = invoke([Nfs.cmd, '-v'])
+ ec, out, error = invoke([Nfs.CMD, '-v'])
rc = Export.parse(out)
return rc
@@ -221,7 +252,7 @@ class Nfs(object):
export = Export(host, path, bit_wise_options, key_value_options)
options = export.options_string()
- cmd = [Nfs.cmd]
+ cmd = [Nfs.CMD]
if len(options):
cmd.extend(['-o', options])
@@ -230,6 +261,7 @@ class Nfs(object):
ec, out, err = invoke(cmd, False)
if ec == 0:
+ Nfs._save_exports()
return None
elif ec == 22:
raise ValueError("Invalid option: %s" % err)
@@ -240,5 +272,8 @@ class Nfs(object):
@staticmethod
def export_remove(export):
- ec, out, err = invoke([Nfs.cmd, '-u', '%s:%s' %
+ ec, out, err = invoke([Nfs.CMD, '-u', '%s:%s' %
(export.host, export.path)])
+
+ if ec == 0:
+ Nfs._save_exports()
--
1.8.2.1