#!/usr/bin/perl use POSIX ":sys_wait_h"; use Time::HiRes qw(usleep); use File::Basename; my $eosowner = "daemon"; print "###########################\n"; print "# v1.0.0\n"; print "###########################\n"; sub usage() { printf STDERR "usage: eosfstregister [-i] [-r] [--force] [--port ] [] [:] [:] [-h|--help]\n"; printf STDERR " -r : allows to register file systems mounted on the root partition\n"; printf STDERR " -i : ignore if one of the filesystems has already a filesystem id stored and continue\n"; printf STDERR " --force : delete old filesystem files and force registration of the new filesystem\n"; printf STDERR " --port : the FST port\n"; printf STDERR " hint: if ends with '/' subdirectories are scanned in this directory, \n"; printf STDERR " if does not end with '/' directories starting with are scanned ( e.g. /data* )\n"; printf STDERR " if ='spare' all filesystems will be registered without scheduling group and you can move them in to production via 'fs mv spare '\n"; } #my $fst=`service eos status fst >& /dev/null`; # #if (!$fst) { # printf STDERR "warning: stopping your fst service first ...\n"; # my $fststop=`service eos stop fst>& /dev/null`; #} my $hostname = `hostname -f`; chomp $hostname; ################################################# # Process optional flag arguments ################################################# my $ignoreerrors = 0; my $allowroot = 0; my $force = 0; my $fstport = 1095; for (my $arg = 0; $arg < $#ARGV + 1; $arg++) { if (($ARGV[$arg] =~ /^-h/) || ($ARGV[$arg] =~ /^--h/)) { usage(); exit(-1); } if (($ARGV[$arg] =~ /--port/)) { $fstport = $ARGV[$arg + 1]; if (!($fstport =~ /^\d+$/)) { printf STDERR "error: provided port=$fstport is not valid\n"; exit(-1); } splice(@ARGV, $arg, 2); } if (($ARGV[$arg] =~ /-i/)) { $ignoreerrors = 1; splice(@ARGV, $arg, 1); } if (($ARGV[$arg] =~ /--force/)) { $force = 1; splice(@ARGV, $arg, 1); } if (($ARGV[$arg] =~ /-r/)) { $allowroot = 1; splice(@ARGV, $arg, 1); } #print "$ARGV[$arg]\n"; } ################################################# # Process MGM URL and mount point arguments ################################################# my $mgmurl = shift @ARGV; my $mountprefix; if ($mgmurl =~ /^\//) { my $redirector = `test -r /etc/sysconfig/eos && . /etc/sysconfig/eos && echo \$EOS_MGM_URL`; chomp $redirector; if ($redirector eq "") { $redirector = `test -r /etc/sysconfig/eos_env && source /etc/sysconfig/eos_env && echo \$EOS_MGM_URL`; chomp $redirector; if ($redirector ne "") { if ($redirector !~ /^root:\/\/*/) { $redirector = "root://" . $redirector; } } else { printf STDERR "error: cannot automatically determine to which MGM I should connect - set it via EOS_MGM_URL in /etc/sysconfig/eos or CDB_CLUSTER variable in /etc/quattor_install_info!\n"; } } # automatic host configuration $mountprefix = $mgmurl; $mgmurl = $redirector; } else { $mgmurl = "root://" . $mgmurl; $mountprefix = shift @ARGV; } chomp $mgmurl; chomp $mountprefix; if ($mgmurl eq "") { printf STDERR "error: you have to provide a manager name [:]\n"; usage(); exit(-1); } if ($mountprefix eq "") { printf STDERR "error: you have to provide a mountprefix as the first argument!\n"; usage(); exit(-1); } #print "Listing mount prefix <$mountprefix> ...\n"; ##################################################### # Validate space:nfilesystems pairs # and count number of filesystems to assign ##################################################### my $policy; my $npfsdefined = 0; my @spacearray; do { $policy = (shift @ARGV or ""); $policy =~ /(\w*):(\d*)/; my $space = $1; my $nspace = $2; if (($policy ne "") && (($space eq "") || ($nspace eq ""))) { printf STDERR "error: policy definition seems illegal!\n"; usage(); exit(-3); } $npfsdefined += int($nspace); for (my $i = 0; $i < $nspace; $i++) { if ($space eq "spare") { push @spacearray, "$space"; } else { push @spacearray, "$space.$i"; } } } while ($policy ne ""); ##################################################### # Grep all entries matching mount-prefix. # # Scenarios: # 1. mountprefix ends with '/': E.g. /data01/ # - mountprefix stays as it is # # 2. mountprefix points to a pattern: E.g. /data01 # - establish basedir: / # - establish search pattern: data01 # - add a filesystem for each directory # which matches / # E.g.: /data01 /data011 /data012 ##################################################### my @filesystems; my $pattern = ""; if (!($mountprefix =~ /\/$/)) { $pattern = basename($mountprefix); $mountprefix = dirname($mountprefix); } if (($mountprefix ne "/") && ($mountprefix =~ /\/$/)) { chop $mountprefix; } open IN, "ls -1 $mountprefix| "; while () { chomp $_; if ("$_" eq "lost+found") { next; } if (!-d "$mountprefix/$_") { next; } if ($_ =~ /^\./) { next; } if (($pattern ne "") && (!($_ =~ /^$pattern/))) { next; } #print "Registering: $mountprefix/$_\n"; if ($mountprefix eq "/") { push @filesystems, "/$_"; } else { push @filesystems, "$mountprefix/$_"; } } if ($#filesystems < 0) { printf STDERR "error: I didn't see any directory inside your mount prefix [ $#filesystems ]!\n"; exit(-2); } # Number of filesystems must equal policy definitions # (the sum of nfilesystems from space:nfilesystems pairs) my $nfilesystems = $#filesystems + 1; if ("$nfilesystems" ne "$npfsdefined") { printf STDERR "error: Your policy definitions don't match the number of file systems I have found [ #filesystem = $nfilesystems #fspolicies = $npfsdefined ]\n"; usage(); exit(-1); } ##################################################### # Register filesystems which matched the mount-prefix ##################################################### my $cnt = 0; foreach (@filesystems) { my ($root_dev, $root_ino, $root_mode, $root_nlink, $root_uid, $root_gid, $root_rdev, $root_size, $root_atime, $root_mtime, $root_ctime, $root_blksize, $root_blocks) = stat("/"); my ($reg_dev, $reg_ino, $reg_mode, $reg_nlink, $reg_uid, $reg_gid, $reg_rdev, $reg_size, $reg_atime, $reg_mtime, $reg_ctime, $reg_blksize, $reg_blocks) = stat("$_"); if (!$allowroot) { if ("$root_dev" eq "$reg_dev") { printf STDERR "error: filesystem $_ is on the root partition ... use '-r' if you really want to register it\n"; next; } } my $uuid = ""; my $fsid = 0; print $_; if ($force) { unlink "$_/.eosfsuuid"; unlink "$_/.eosfsid"; } if (!-e "$_/.eosfsuuid") { $uuid = `uuidgen`; chomp $uuid; system("echo $uuid > $_/.eosfsuuid; chown $eosowner.$eosowner $_/.eosfsuuid"); } else { $uuid = `cat $_/.eosfsuuid`; chomp $uuid; } if (!-e "$_/.eosfsid") { $fsid = "undef"; } else { $fsid = `cat $_/.eosfsid`; chomp $fsid; } if ($fsid ne "undef") { printf STDERR "error: filesystem $_ is already labeled with fsid=$fsid - remove the file $_/.eosfsid if you want to register with new fsid\n"; if (!$ignoreerrors) { exit(-4); } } printf " : uuid=$uuid fsid=$fsid\n"; my $cmd = 0; if (!($cmd = fork())) { system("unset EOS_MGM_URL; env XrdSecPROTOCOL=sss eos -b $mgmurl fs add $uuid $hostname:$fstport $_ $spacearray[$cnt] rw"); system("unset EOS_MGM_URL; env XrdSecPROTOCOL=sss eos -b $mgmurl fs boot $uuid"); exit(0); } for (my $i = 0; $i < 40; $i++) { waitpid(-1, WNOHANG); if (kill 0, $cmd) { usleep(250000); } } $cnt++; }