#!/usr/bin/python2.6 # -*- coding: utf-8 -*- # # Univention Configuration Registry # add and remove nfs shares from the LDAP directory to /etc/fstab # # Copyright 2004-2011 Univention GmbH # # http://www.univention.de/ # # All rights reserved. # # The source code of this program is made available # under the terms of the GNU Affero General Public License version 3 # (GNU AGPL V3) as published by the Free Software Foundation. # # Binary versions of this program provided by Univention to you as # well as other copyrighted, protected or trademarked materials like # Logos, graphics, fonts, specific documentations and configurations, # cryptographic keys etc. are subject to a license agreement between # you and Univention and not subject to the GNU AGPL V3. # # In the case you use this program under the terms of the GNU AGPL V3, # the program is provided in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License with the Debian GNU/Linux or Univention distribution in file # /usr/share/common-licenses/AGPL-3; if not, see # . import os import univention.config_registry import ldap import sys import subprocess configRegistry=univention.config_registry.ConfigRegistry() configRegistry.load() ldap_hostdn = configRegistry.get('ldap/hostdn') MAGIC_LDAP = '#LDAP Entry DN:' def exit(result, message = None): """Exit with optional error message.""" script = os.path.basename(sys.argv[0]) if message: print '%s: %s' % (script, message) sys.exit(result) def query_policy(dn): """Get NFS shares from LDAP as per policy for dn.""" nfsmount = set() try: p = subprocess.Popen(('univention_policy_result', '-D', ldap_hostdn, '-y', '/etc/machine.secret', '-s', ldap_hostdn), stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: raise OSError(stderr) except OSError, e: exit(1, "FAIL: failed to execute `univention_policy_result %s'" % dn) for line in stdout.splitlines(): line = line.strip() k, v = line.split('=', 1) if k == 'univentionNFSMounts': v, = shlex.split(v) nfsmount.add(v) return nfsmount def main(): if not configRegistry.get('ldap/hostdn'): exit( 0 ) nfsmounts = query_policy( configRegistry['ldap/hostdn'] ) ldap_server = configRegistry['ldap/server/name'] lo = ldap.initialize("ldap://%s" % ldap_server) lo.simple_bind_s("","") # remove all nfs mounts from the fstab fstabOld = "/etc/fstab" fstabNew = "/etc/fstab.new.%d" % os.getpid() sources = set() mount_points = set() try: f_old = open(fstabOld, 'r') f_new = open(fstabNew, 'w') for line in f_old: if not MAGIC_LDAP in line: f_new.write(line) if line.startswith('#'): continue fields = line.strip().split() # source_spec mount_point fs options freq passno sp = fields[0] sources.add(sp) try: mp = fields[1] if not mp.startswith('#'): mount_points.add(mp) except IndexError: pass f_old.close() except IOError, e: exit(1, 'Failed to rewrite %s: %s' % (fstabOld, e)) fqdn = "%(hostname)s.%(domainname)s" % configRegistry to_mount = set() for nfsmount in nfsmounts: fields = nfsmount.split(' ') # dn_univentionShareNFS mount_point dn = fields[0] if not dn: continue result = lo.search_s(dn, ldap.SCOPE_SUBTREE, 'objectclass=*', attrlist=['univentionShareHost', 'univentionSharePath']) try: attributes = result[0][1] share_host = attributes['univentionShareHost'][0] share_path = attributes['univentionSharePath'][0] except LookupError: continue # skip share if from self if share_host == fqdn: continue mp = fields[-1] or share_path # skip share if target already in fstab if mp in mount_points: continue nfs_path_fqdn = "%s:%s" % (share_host, share_path) # skip share if the source is already in the fstab if nfs_path_fqdn in sources: continue # get the ip of the share_host hostname, domain = share_host.split('.', 1) result = lo.search_s(configRegistry['ldap/base'], ldap.SCOPE_SUBTREE, '(&(relativeDomainName=%s)(zoneName=%s))' % (hostname, domain), attrlist=['aRecord']) try: attributes = result[0][1] nfs_path_ip = "%s:%s" % (attributes['aRecord'][0], share_path) except LookupError: nfs_path_ip = nfs_path_fqdn # skip share if the source is already in the fstab if nfs_path_ip in sources: continue f_new.write("%s\t%s\tnfs\tdefaults\t0\t0\t%s %s\n" % (nfs_path_ip, mp, MAGIC_LDAP, dn)) to_mount.add(mp) f_new.close() try: os.rename(fstabNew, fstabOld) except OSError, e: exit(1, 'Failed to rename %s: %s' % (fstabOld, e)) try: fp = open('/etc/mtab', 'r') for line in fp: fields = line.split(' ') # source_spec mount_point fs options freq passno to_mount.discard(fields[1]) fp.close() except IOError, e: exit(1, 'Failed to read /etc/mtab: %s' % e) for mp in sorted(to_mount): try: if not os.path.exists(mp): os.makedirs(mp) p = subprocess.Popen(['mount', mp]) except OSError, e: exit(1, 'Failed to mount %s: %s' % (mp, e)) if __name__ == '__main__': main()