|
31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
32 |
# <http://www.gnu.org/licenses/>. |
32 |
# <http://www.gnu.org/licenses/>. |
33 |
|
33 |
|
|
|
34 |
from __future__ import print_function |
35 |
from argparse import ArgumentParser |
34 |
import os |
36 |
import os |
35 |
import univention.config_registry |
37 |
import univention.config_registry |
36 |
import ldap |
38 |
import ldap |
Lines 38-49
import univention.uldap
|
Link Here
|
---|
|
38 |
import sys |
40 |
import sys |
39 |
import subprocess |
41 |
import subprocess |
40 |
import shlex |
42 |
import shlex |
41 |
import getopt |
43 |
from io import StringIO |
42 |
|
44 |
|
43 |
configRegistry = univention.config_registry.ConfigRegistry() |
45 |
configRegistry = univention.config_registry.ConfigRegistry() |
44 |
configRegistry.load() |
46 |
configRegistry.load() |
45 |
verbose = False |
47 |
verbose = False |
46 |
simulate = False |
|
|
47 |
|
48 |
|
48 |
ldap_hostdn = configRegistry.get('ldap/hostdn') |
49 |
ldap_hostdn = configRegistry.get('ldap/hostdn') |
49 |
|
50 |
|
Lines 53-66
MAGIC_LDAP = '#LDAP Entry DN:'
|
Link Here
|
---|
|
53 |
def debug(msg, out=sys.stderr): |
54 |
def debug(msg, out=sys.stderr): |
54 |
"""Print verbose information 'msg' to 'out'.""" |
55 |
"""Print verbose information 'msg' to 'out'.""" |
55 |
if verbose: |
56 |
if verbose: |
56 |
print >>out, msg, |
57 |
print(msg, end=' ', file=out) |
57 |
|
58 |
|
58 |
|
59 |
|
59 |
def exit(result, message=None): |
60 |
def exit(result, message=None): |
60 |
"""Exit with optional error message.""" |
61 |
"""Exit with optional error message.""" |
61 |
script = os.path.basename(sys.argv[0]) |
62 |
script = os.path.basename(sys.argv[0]) |
62 |
if message: |
63 |
if message: |
63 |
print >>sys.stderr, '%s: %s' % (script, message) |
64 |
print('%s: %s' % (script, message), file=sys.stderr) |
64 |
sys.exit(result) |
65 |
sys.exit(result) |
65 |
|
66 |
|
66 |
|
67 |
|
|
69 |
nfsmount = set() |
70 |
nfsmount = set() |
70 |
debug('Retrieving policy for %s...\n' % dn) |
71 |
debug('Retrieving policy for %s...\n' % dn) |
71 |
try: |
72 |
try: |
72 |
p = subprocess.Popen(['univention_policy_result', '-D', ldap_hostdn, '-y', '/etc/machine.secret', '-s', dn], shell=False, stdout=subprocess.PIPE) |
73 |
p = subprocess.Popen(['univention_policy_result', '-D', ldap_hostdn, '-y', '/etc/machine.secret', '-s', dn], stdout=subprocess.PIPE) |
73 |
stdout, stderr = p.communicate() |
74 |
stdout, stderr = p.communicate() |
74 |
except OSError: |
75 |
except OSError: |
75 |
exit(1, "FAIL: failed to execute `univention_policy_result %s'" % dn) |
76 |
exit(1, "FAIL: failed to execute `univention_policy_result %s'" % dn) |
|
84 |
return nfsmount |
85 |
return nfsmount |
85 |
|
86 |
|
86 |
|
87 |
|
87 |
def usage(out=sys.stdout): |
|
|
88 |
"""Output usage message.""" |
89 |
print >>out, 'syntax: nfsmounts [-h] [-v]' |
90 |
print >>out, ' -h, --help print this help' |
91 |
print >>out, ' -s, --simulate simulate update and just show actions' |
92 |
print >>out, ' -v, --verbose print verbose information' |
93 |
print >>out, '' |
94 |
|
95 |
|
96 |
def main(): |
88 |
def main(): |
97 |
# parse command line |
89 |
# parse command line |
98 |
try: |
90 |
parser = ArgumentParser() |
99 |
opts, pargs = getopt.getopt(sys.argv[1:], 'hsv', ['help', 'simulate', 'verbose']) |
91 |
parser.add_argument('--simulate', '-s', action='store_true', help='simulate update and just show actions') |
100 |
except: |
92 |
parser.add_argument('--verbose', '-v', action='store_true', help='print verbose information') |
101 |
usage(sys.stderr) |
93 |
args = parser.parse_args() |
102 |
sys.exit(2) |
94 |
|
103 |
|
95 |
if args.verbose: |
104 |
# get command line data |
|
|
105 |
for option, value in opts: |
106 |
if option == '-h' or option == '--help': |
107 |
usage() |
108 |
sys.exit(0) |
109 |
elif option == '-s' or option == '--simulate': |
110 |
global simulate |
111 |
simulate = True |
112 |
elif option == '-v' or option == '--verbose': |
113 |
global verbose |
96 |
global verbose |
114 |
verbose = True |
97 |
verbose = True |
115 |
|
98 |
|
116 |
hostdn = configRegistry.get('ldap/hostdn') |
99 |
hostdn = configRegistry.get('ldap/hostdn') |
117 |
if not hostdn: |
100 |
if not hostdn: |
118 |
print >>sys.stderr, "Error: ldap/hostdn is not set." |
101 |
print("Error: ldap/hostdn is not set.", file=sys.stderr) |
119 |
exit(1) |
102 |
exit(1) |
120 |
debug("Hostdn is %s\n" % hostdn) |
103 |
debug("Hostdn is %s\n" % hostdn) |
121 |
|
104 |
|
|
129 |
sources = set() |
112 |
sources = set() |
130 |
mount_points = set() |
113 |
mount_points = set() |
131 |
try: |
114 |
try: |
132 |
f_old = open('/etc/fstab', 'r') |
115 |
with open('/etc/fstab', 'r') as f_old: |
133 |
if simulate: |
116 |
if args.simulate: |
134 |
# f_new = os.fdopen(os.dup(sys.stderr.fileno()), "w") |
117 |
# f_new = os.fdopen(os.dup(sys.stderr.fileno()), "w") |
135 |
from StringIO import StringIO |
118 |
f_new = StringIO() |
136 |
f_new = StringIO() |
|
|
137 |
else: |
138 |
f_new = open(fstabNew, 'w') |
139 |
for line in f_old: |
140 |
if MAGIC_LDAP not in line: |
141 |
f_new.write(line) |
142 |
debug("= %s" % line) |
143 |
else: |
119 |
else: |
144 |
debug("- %s" % line) |
120 |
f_new = open(fstabNew, 'w') |
145 |
if line.startswith('#'): |
121 |
|
146 |
continue |
122 |
for line in f_old: |
147 |
|
123 |
if MAGIC_LDAP not in line: |
148 |
line = line.rstrip('\n') |
124 |
f_new.write(line) |
149 |
fields = line.split(' ') # source_spec mount_point fs options freq passno |
125 |
debug("= %s" % line) |
150 |
|
126 |
else: |
151 |
sp = fields[0] |
127 |
debug("- %s" % line) |
152 |
sources.add(sp) |
128 |
|
153 |
|
129 |
if line.startswith('#'): |
154 |
try: |
130 |
continue |
155 |
mp = fields[1] |
131 |
|
156 |
if not mp.startswith('#'): |
132 |
line = line.rstrip('\n') |
157 |
mount_points.add(mp) |
133 |
fields = line.split(' ') # source_spec mount_point fs options freq passno |
158 |
except IndexError: |
134 |
|
159 |
pass |
135 |
sp = fields[0] |
160 |
|
136 |
sources.add(sp) |
161 |
f_old.close() |
137 |
|
|
|
138 |
try: |
139 |
mp = fields[1] |
140 |
if not mp.startswith('#'): |
141 |
mount_points.add(mp) |
142 |
except IndexError: |
143 |
pass |
162 |
except IOError as e: |
144 |
except IOError as e: |
163 |
exit(1, e) |
145 |
exit(1, e) |
164 |
|
146 |
|
|
189 |
debug('not found, skipping\n') |
171 |
debug('not found, skipping\n') |
190 |
continue |
172 |
continue |
191 |
|
173 |
|
192 |
# skip share if from self |
|
|
193 |
if share_host == fqdn: |
194 |
debug('is self, skipping\n') |
195 |
continue |
196 |
|
197 |
mp = fields[-1] or share_path |
174 |
mp = fields[-1] or share_path |
198 |
# skip share if target already in fstab |
175 |
# skip share if target already in fstab |
199 |
if mp in mount_points: |
176 |
if mp in mount_points: |
200 |
debug('already mounted on %s, skipping\n' % mp) |
177 |
debug('already mounted on %s, skipping\n' % mp) |
201 |
continue |
178 |
continue |
202 |
|
179 |
|
|
|
180 |
# skip share if from self |
181 |
if share_host == fqdn and share_path == mp: |
182 |
debug('is self, skipping\n') |
183 |
continue |
184 |
|
203 |
nfs_path_fqdn = "%s:%s" % (share_host, share_path) |
185 |
nfs_path_fqdn = "%s:%s" % (share_host, share_path) |
204 |
# skip share if the source is already in the fstab |
186 |
# skip share if the source is already in the fstab |
205 |
if nfs_path_fqdn in sources: |
187 |
if nfs_path_fqdn in sources: |
|
227 |
|
209 |
|
228 |
f_new.close() |
210 |
f_new.close() |
229 |
debug('Switching /etc/fstab...\n') |
211 |
debug('Switching /etc/fstab...\n') |
230 |
if not simulate: |
212 |
if not args.simulate: |
231 |
if os.path.isfile(fstabNew) and os.path.getsize(fstabNew) > 0: |
213 |
if os.path.isfile(fstabNew) and os.path.getsize(fstabNew) > 0: |
232 |
os.rename(fstabNew, '/etc/fstab') |
214 |
os.rename(fstabNew, '/etc/fstab') |
233 |
|
215 |
|
234 |
fp = open('/etc/mtab', 'r') |
216 |
with open('/etc/mtab', 'r') as fp: |
235 |
for line in fp: |
217 |
for line in fp: |
236 |
line = line.rstrip('\n') |
218 |
line = line.rstrip('\n') |
237 |
fields = line.split(' ') # source_spec mount_point fs options freq passno |
219 |
fields = line.split(' ') # source_spec mount_point fs options freq passno |
238 |
to_mount.discard(fields[1]) |
220 |
to_mount.discard(fields[1]) |
239 |
|
221 |
|
240 |
for mp in sorted(to_mount): |
222 |
for mp in sorted(to_mount): |
241 |
if not os.path.exists(mp): |
223 |
if not os.path.exists(mp): |
242 |
os.makedirs(mp) |
224 |
os.makedirs(mp) |
243 |
debug('Mounting %s...\n' % mp) |
225 |
debug('Mounting %s...\n' % mp) |
244 |
if not simulate: |
226 |
if not args.simulate: |
245 |
p = subprocess.Popen(['mount', mp]) |
227 |
subprocess.Popen(['mount', mp]) |
246 |
|
228 |
|
247 |
|
229 |
|
248 |
if __name__ == '__main__': |
230 |
if __name__ == '__main__': |