1 | #!/usr/bin/perl |
---|
2 | # |
---|
3 | # 2011/06/21 gabriel |
---|
4 | |
---|
5 | use strict; |
---|
6 | use warnings; |
---|
7 | |
---|
8 | use YAML; |
---|
9 | use IO::All; |
---|
10 | use File::Basename; |
---|
11 | use File::Finder; |
---|
12 | use Net::LDAP; |
---|
13 | use List::Util qw(shuffle); |
---|
14 | |
---|
15 | my %CMD_DB = ( |
---|
16 | help => \&cmd_help, |
---|
17 | version => \&cmd_version, |
---|
18 | generate => \&cmd_generate, |
---|
19 | update => \&cmd_update, |
---|
20 | init => \&cmd_init_db, |
---|
21 | 'exclude-list' => \&cmd_exclude_list, |
---|
22 | ); |
---|
23 | |
---|
24 | my ($LDAP_H, $LDAP_BASE); |
---|
25 | my $LIMIT_TIMESTAMP = time() - (8 * 24 * 3600); # 8 days |
---|
26 | |
---|
27 | my $cmd = shift @ARGV || 'help'; |
---|
28 | if (defined $CMD_DB{$cmd}) { |
---|
29 | $CMD_DB{$cmd}->(@ARGV); |
---|
30 | } |
---|
31 | else { |
---|
32 | print {*STDERR} "backuppc-silzigan: command $cmd not found\n\n"; |
---|
33 | $CMD_DB{help}->(); |
---|
34 | exit 1; |
---|
35 | } |
---|
36 | |
---|
37 | exit; |
---|
38 | |
---|
39 | sub open_ldap { |
---|
40 | # AuthLDAPUrl "ldap://ldapserver.mylab.fr/ou=Users,dc=mylab,dc=fr?uid?sub" |
---|
41 | # AuthLDAPBindDN "cn=ldapconnect,ou=System,dc=mylab,dc=fr" |
---|
42 | # AuthLDAPBindPassword "Rhalala128" |
---|
43 | |
---|
44 | my ($masterLDAP, $masterDN, $masterPw); |
---|
45 | |
---|
46 | for my $config_line (io('/etc/apache2/conf.d/backuppc.conf')->chomp->slurp) { |
---|
47 | ($masterLDAP, $LDAP_BASE) = ($1, $2) if $config_line =~ m{ ^\s* AuthLDAPUrl [^/]+ // ([^/]+) / (ou=[^?]+) }xms; |
---|
48 | $masterDN = $1 if $config_line =~ m{ ^\s* AuthLDAPBindDN \s+ " ([^"]+) " }xms; |
---|
49 | $masterPw = $1 if $config_line =~ m{ ^\s* AuthLDAPBindPassword \s+ " ([^"]+) " }xms; |
---|
50 | } |
---|
51 | |
---|
52 | $LDAP_H = Net::LDAP->new( "$masterLDAP" ) or die "$@"; |
---|
53 | my $mesg = $LDAP_H->bind("$masterDN", password => "$masterPw"); |
---|
54 | |
---|
55 | return; |
---|
56 | } |
---|
57 | |
---|
58 | sub close_ldap { |
---|
59 | $LDAP_H->unbind(); |
---|
60 | return; |
---|
61 | } |
---|
62 | |
---|
63 | sub cmd_update { |
---|
64 | my $search_config_file = File::Finder->type('f')->name('*.yaml'); |
---|
65 | for my $config_file (File::Finder->eval($search_config_file)->in('/etc/backuppc')) { |
---|
66 | cmd_generate("$config_file"); |
---|
67 | } |
---|
68 | |
---|
69 | update_hosts(); |
---|
70 | } |
---|
71 | |
---|
72 | sub cmd_generate { |
---|
73 | my $config_file = shift; |
---|
74 | |
---|
75 | my $CONFIG = YAML::LoadFile($config_file); |
---|
76 | |
---|
77 | $CONFIG->{default}{namespace} ||= basename($config_file, '.yaml'); |
---|
78 | $CONFIG->{default}{path} ||= "/etc/backuppc/auto/$CONFIG->{default}{namespace}"; |
---|
79 | $CONFIG->{default}{hosts} ||= "$CONFIG->{default}{path}/hosts"; |
---|
80 | $CONFIG->{default}{exclude} ||= "/usr/lib/kont/etc/backuppc/exclude.txt"; |
---|
81 | |
---|
82 | if (not -d "/etc/backuppc/auto/$CONFIG->{default}{namespace}") { |
---|
83 | io("/etc/backuppc/auto/$CONFIG->{default}{namespace}")->mkpath({mode => 0755}); |
---|
84 | } |
---|
85 | |
---|
86 | print '' > io($CONFIG->{default}{hosts}); |
---|
87 | |
---|
88 | open_ldap(); |
---|
89 | LOOP_ON_COMPUTER: |
---|
90 | for my $computer ( keys %{$CONFIG->{computers}}) { |
---|
91 | my $login = $CONFIG->{computers}{$computer}{login} || 'root'; |
---|
92 | |
---|
93 | LOOP_ON_USER: |
---|
94 | for my $user ( keys %{$CONFIG->{computers}{$computer}{users}}) { |
---|
95 | my $pathshare = $CONFIG->{computers}{$computer}{share} |
---|
96 | || $CONFIG->{default}{share} |
---|
97 | || "/home/users"; |
---|
98 | my $share = $CONFIG->{computers}{$computer}{users}{$user}{share} |
---|
99 | || "$pathshare/$user"; |
---|
100 | my $status = $CONFIG->{computers}{$computer}{users}{$user}{status} |
---|
101 | || $CONFIG->{computers}{$computer}{status} |
---|
102 | || $CONFIG->{default}{status} |
---|
103 | || 'auto'; |
---|
104 | my $admin = $CONFIG->{computers}{$computer}{users}{$user}{admin} |
---|
105 | || $CONFIG->{computers}{$computer}{admin} |
---|
106 | || $CONFIG->{default}{admin} |
---|
107 | || 'root'; |
---|
108 | |
---|
109 | my $exclude = $CONFIG->{computers}{$computer}{users}{$user}{exclude} |
---|
110 | || $CONFIG->{computers}{$computer}{exclude} |
---|
111 | || ''; |
---|
112 | |
---|
113 | my @exclude_list = (); |
---|
114 | if (ref($exclude) eq "ARRAY") { |
---|
115 | push @exclude_list, @{$exclude}; |
---|
116 | } |
---|
117 | else { |
---|
118 | push @exclude_list, $exclude if not $exclude =~ m/^$/; |
---|
119 | } |
---|
120 | push @exclude_list, io($CONFIG->{default}{exclude})->chomp->slurp; |
---|
121 | my $exclude_string = join ",\n", map { " '$_'" } @exclude_list; |
---|
122 | |
---|
123 | if ($status eq "auto") { |
---|
124 | $status = "disable"; |
---|
125 | my $ldb = $LDAP_H->search( |
---|
126 | base => "$LDAP_BASE", |
---|
127 | filter => "(uid=$user)", |
---|
128 | attrs => ['shadowExpire', 'sambaKickoffTime'], |
---|
129 | ); |
---|
130 | if (not $ldb->code ) { |
---|
131 | |
---|
132 | LDAP_RESULT: |
---|
133 | foreach my $entry ($ldb->entries) { |
---|
134 | |
---|
135 | my $user_expire_timestamp = $entry->get_value('sambaKickoffTime') || 0; |
---|
136 | my $user_shadow_expire = $entry->get_value('shadowExpire') || 0; |
---|
137 | |
---|
138 | if ($user_shadow_expire == 0) { |
---|
139 | $status = "enable"; |
---|
140 | last LDAP_RESULT; |
---|
141 | } |
---|
142 | elsif ( |
---|
143 | ( $user_expire_timestamp ne "" ) |
---|
144 | and ( $user_expire_timestamp > $LIMIT_TIMESTAMP ) |
---|
145 | ) { |
---|
146 | $status = "enable"; |
---|
147 | last LDAP_RESULT; |
---|
148 | } |
---|
149 | |
---|
150 | } |
---|
151 | } |
---|
152 | } |
---|
153 | |
---|
154 | write_config($user, $computer, $share, $login, $admin, $status, $CONFIG, $exclude_string); |
---|
155 | |
---|
156 | } |
---|
157 | |
---|
158 | if (exists $CONFIG->{computers}{$computer}{subfolder}) { |
---|
159 | my $home_path = $CONFIG->{computers}{$computer}{subfolder}; |
---|
160 | my @ls = `/bin/ping -W 2 -c 1 $computer > /dev/null 2>&1 && { |
---|
161 | /usr/bin/rsync --dry-run $login\@$computer:$home_path /tmp/backuppc-test/ || echo Error for $login\@$computer | logger -t backuppc-silzigan; |
---|
162 | }`; |
---|
163 | |
---|
164 | $home_path =~ s{/[^/]*$}{}; |
---|
165 | LINE: |
---|
166 | for my $line (@ls) { |
---|
167 | chomp $line; |
---|
168 | next LINE if not $line =~ m/skipping\sdirectory/; |
---|
169 | next LINE if $line =~ m/lost+found/; |
---|
170 | next LINE if $line =~ m/administrator/; |
---|
171 | my ($user) = reverse split /\s+/, $line; |
---|
172 | $user =~ s{/$}{}; |
---|
173 | $user =~ s{.*/}{}; |
---|
174 | next LINE if not $user =~ m/^\w/; |
---|
175 | |
---|
176 | my $share = "$home_path/$user"; |
---|
177 | |
---|
178 | my @exclude_list = (); |
---|
179 | push @exclude_list, io($CONFIG->{default}{exclude})->chomp->slurp; |
---|
180 | my $exclude_string = join ",\n", map { " '$_'" } @exclude_list; |
---|
181 | |
---|
182 | my $admin = $CONFIG->{computers}{$computer}{admin} |
---|
183 | || $CONFIG->{default}{admin} |
---|
184 | || 'root'; |
---|
185 | |
---|
186 | my $status = "disable"; |
---|
187 | my $ldb = $LDAP_H->search( |
---|
188 | base => "$LDAP_BASE", |
---|
189 | filter => "(uid=$user)", |
---|
190 | attrs => ['shadowExpire', 'sambaKickoffTime'], |
---|
191 | ); |
---|
192 | if (not $ldb->code ) { |
---|
193 | |
---|
194 | LDAP_RESULT: |
---|
195 | foreach my $entry ($ldb->entries) { |
---|
196 | |
---|
197 | my $user_expire_timestamp = $entry->get_value('sambaKickoffTime') || 0; |
---|
198 | my $user_shadow_expire = $entry->get_value('shadowExpire') || 0; |
---|
199 | |
---|
200 | if ($user_shadow_expire == 0) { |
---|
201 | $status = "enable"; |
---|
202 | last LDAP_RESULT; |
---|
203 | } |
---|
204 | elsif ( |
---|
205 | ( $user_expire_timestamp ne "" ) |
---|
206 | and ( $user_expire_timestamp > $LIMIT_TIMESTAMP ) |
---|
207 | ) { |
---|
208 | $status = "enable"; |
---|
209 | last LDAP_RESULT; |
---|
210 | } |
---|
211 | |
---|
212 | } |
---|
213 | } |
---|
214 | |
---|
215 | write_config($user, $computer, $share, $login, $admin, $status, $CONFIG, $exclude_string); |
---|
216 | } |
---|
217 | } |
---|
218 | } |
---|
219 | close_ldap(); |
---|
220 | } |
---|
221 | |
---|
222 | sub cmd_exclude_list { |
---|
223 | print io('/usr/lib/kont/etc/backuppc/exclude.txt')->all; |
---|
224 | } |
---|
225 | |
---|
226 | sub write_config { |
---|
227 | my ($user, $computer, $share, $login, $admin, $status, $CONFIG, $exclude) = @_; |
---|
228 | my ($c) = split /\./, $computer; |
---|
229 | my $backup_name = $c . '_'. $user; |
---|
230 | |
---|
231 | return if $status eq 'disable' and not -e "/var/lib/backuppc/pc/$backup_name/backups"; |
---|
232 | |
---|
233 | print "$backup_name 0 $login $admin,$user\n" >> io($CONFIG->{default}{hosts}); |
---|
234 | |
---|
235 | my $share_string = "'$share'"; |
---|
236 | if (ref($share) eq "ARRAY") { |
---|
237 | $share_string = join ', ', map("'$_'", @{$share}); |
---|
238 | } |
---|
239 | |
---|
240 | # my $exclude = join ",\n", map { " '$_'" } io('/usr/lib/kont/etc/backuppc/exclude.txt')->chomp->slurp; |
---|
241 | |
---|
242 | print <<END > io("$CONFIG->{default}{path}/$backup_name.pl"); |
---|
243 | \$Conf{XferMethod} = 'rsync'; |
---|
244 | \$Conf{ClientNameAlias} = '$computer'; |
---|
245 | \$Conf{RsyncShareName} = [ $share_string ]; |
---|
246 | \$Conf{RsyncClientCmd} = '\$sshPath -q -x -l $login \$host \$rsyncPath \$argList+'; |
---|
247 | \$Conf{RsyncClientRestoreCmd} = '\$sshPath -q -x -l $login \$host \$rsyncPath \$argList+'; |
---|
248 | \$Conf{BackupFilesExclude} = { |
---|
249 | '$share' => [ |
---|
250 | $exclude |
---|
251 | ] |
---|
252 | }; |
---|
253 | END |
---|
254 | |
---|
255 | print '$Conf{FullPeriod} = "-2";' >> io("$CONFIG->{default}{path}/$backup_name.pl") if $status eq 'disable'; |
---|
256 | symlink "$CONFIG->{default}{path}/$backup_name.pl", "/etc/backuppc/pc/$backup_name.pl"; |
---|
257 | } |
---|
258 | |
---|
259 | sub update_hosts { |
---|
260 | io->catfile('/etc/backuppc/hosts.main') > io('/etc/backuppc/hosts.order'); |
---|
261 | my @hosts = io('/etc/backuppc/hosts.main')->chomp->slurp; |
---|
262 | |
---|
263 | my $search_host_file = File::Finder->type('f')->name('hosts'); |
---|
264 | for my $host_file (File::Finder->eval($search_host_file)->in('/etc/backuppc/auto')) { |
---|
265 | print "#\n# $host_file\n#\n" >> io('/etc/backuppc/hosts.order'); |
---|
266 | io->catfile("$host_file") >> io('/etc/backuppc/hosts.order'); |
---|
267 | push @hosts, io("$host_file")->chomp->slurp; |
---|
268 | } |
---|
269 | my ($first, @host) = grep(/./, grep(!/^#/, @hosts)); |
---|
270 | print "$first\n" > io('/etc/backuppc/hosts'); |
---|
271 | print "$_\n" >> io('/etc/backuppc/hosts') for shuffle(@host); |
---|
272 | } |
---|
273 | |
---|
274 | sub cmd_init_db { |
---|
275 | my $cfg = { |
---|
276 | computers => { |
---|
277 | 'machine36.hmg.priv' => { |
---|
278 | login => 'root', |
---|
279 | share => '/home/users/%u', |
---|
280 | status => 'auto', |
---|
281 | users => { |
---|
282 | 'dupond' => { |
---|
283 | share => [ '/home/users/dupond', '/var/www/dupond' ], |
---|
284 | status => 'enable', |
---|
285 | }, |
---|
286 | 'durand' => { |
---|
287 | share => '/home/users/durand', |
---|
288 | }, |
---|
289 | }, |
---|
290 | }, |
---|
291 | }, |
---|
292 | }; |
---|
293 | |
---|
294 | YAML::DumpFile("/tmp/template-backuppc.yaml", $cfg); |
---|
295 | } |
---|
296 | |
---|
297 | sub cmd_help { |
---|
298 | print <<'END'; |
---|
299 | backuppc-silzigan - cut into small pieces a computer configuration for backuppc |
---|
300 | |
---|
301 | backuppc-silzigan init |
---|
302 | backuppc-silzigan generate config_file.yaml |
---|
303 | backuppc-silzigan update |
---|
304 | backuppc-silzigan help |
---|
305 | backuppc-silzigan version |
---|
306 | backuppc-silzigan exclude-list |
---|
307 | END |
---|
308 | return; |
---|
309 | } |
---|
310 | |
---|
311 | sub cmd_version { |
---|
312 | print <<'END'; |
---|
313 | backuppc-silzigan - cut into small pieces a computer configuration for backuppc |
---|
314 | Copyright (C) 2011-2013 Gabriel Moreau |
---|
315 | |
---|
316 | $Id: backuppc-silzigan..host.legilnx32 3821 2013-12-20 08:03:14Z g7moreau $ |
---|
317 | END |
---|
318 | return; |
---|
319 | } |
---|