[101] | 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 | } |
---|