#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos720 src/bos/usr/bin/cdat/cdat-init.pl 1.11 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 2010,2011 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)18 1.11 src/bos/usr/bin/cdat/cdat-init.pl, cdat, bos720 7/15/11 04:48:54 use warnings; use strict; use Getopt::Long; use XML::LibXML; use File::Path; # needed for mkpath use Sys::Hostname; use cdat; use messages; # # Constants. # my $SSH_KEYGEN = '/usr/bin/ssh-keygen'; my $MKLV = '/usr/sbin/mklv'; my $CRFS = '/usr/sbin/crfs'; my $MOUNT = '/usr/sbin/mount'; my $DATAPREFIX = '/cdat'; my $XMLFILE = 'cdat.xml'; my $USER = 'cdat'; my $VGNAME = 'rootvg'; my $LVNAME = 'cdat'; my $FSSIZE = '10G'; my $LVFS = 'jfs2'; ###################################################################### # Function: usage # Purpose: Display usage. # Tasks: Print usage and exit. # Input: None # Output: None ###################################################################### sub usage() { printf(STDERR catgets(MSG_CDAT_INIT_USAGE, "Usage: cdat init -h\n". " cdat init [-c [-g VGName] [-s FSSize]] [-d Directory]\n". " [-l LVName] [-u User]\n")); exit(1); } ###################################################################### # Function: main # Purpose: Entry point of the init subcommand. # Tasks: Create repository. # Input: None # Output: None ###################################################################### sub main { my ($rc, $create, $directory, $user, $vgname, $lvname, $fssize); # Parse command line options Getopt::Long::Configure('bundling', 'no_ignore_case'); $rc = GetOptions( 'h' => \&usage, 'c' => \$create, 'd=s' => \$directory, 'u=s' => \$user, 'g=s' => \$vgname, 'l=s' => \$lvname, 's=s' => \$fssize, ); if (!$rc || @ARGV != 0) { usage(); } # options -g and -s can only be used along with -c if ((defined($vgname) || defined($fssize)) && !defined($create)) { usage(); } # if -d not specified, use default $directory = $DATAPREFIX if (!defined($directory)); if (substr($directory, 0, 1) ne "/") { printf(STDERR catgets(MSG_NEEDS_ABSOLUTE_PATH, "-d needs an absolute path.\n")); exit(1); } # if -u not specified, use default $user = $USER if (!defined($user)); printf(catgets(MSG_CHECKING_USER, "Checking user %s..."), $user); # check if a user with that name already exists my ($name, $pass, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire) = getpwnam($user); if (!defined($name)) { # specified user does not already exist, create it printf(catgets(MSG_CREATING_MISSING_USER, "Creating missing user.\n")); system("/usr/sbin/lsrole CdatMaster > /dev/null 2>&1"); if ($? != 0) { # check if the ibm.ps.client.bind authorization exists system("/usr/sbin/lsauth ibm.ps.client.bind > /dev/null 2>&1"); if ($? != 0) { # create the authorization hierarchy if it does not exist system("/usr/bin/mkauth ibm > /dev/null 2>&1"); system("/usr/bin/mkauth ibm.ps > /dev/null 2>&1"); system("/usr/bin/mkauth ibm.ps.client > /dev/null 2>&1"); # create the bind authorization system("/usr/bin/mkauth ibm.ps.client.bind > /dev/null 2>&1"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_AUTH, "Cannot create RBAC authorization %s.\n"), 'ibm.ps.client.bind'); exit(2); } } # create the CdatMaster RBAC role system("/usr/bin/mkrole authorizations=aix.fs.manage.change,aix.ras.pureScale,ibm.ps.client.bind CdatMaster > /dev/null 2>&1"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_ROLE, "Cannot create RBAC role %s.\n"), 'CdatMaster'); exit(2); } # set entries in the kernel security tables system("/usr/sbin/setkst -q -t role,auth > /dev/null 2>&1"); } system("/usr/bin/mkuser roles=CdatMaster default_roles=CdatMaster gecos='Cluster Data Aggregation Tool' '$user'"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_USER, "Cannot create user %s.\n"), $user); exit(2); } # Ask for an initial password such that user can log in system("/usr/bin/passwd '$user'"); # Retrieve UID/GID of newly created user ($name, $pass, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire) = getpwnam($user); } else { printf(catgets(MSG_FOUND, "found\n")); } # # "Refresh" the crontab file (make sure it exists). # system("EDITOR=/usr/bin/cat /usr/bin/crontab -e $user > /dev/null"); # Ignore if it fails as it is not a fatal condition printf(catgets(MSG_CHECKING_FOR_SSH, "Checking for SSH...")); if ( -x "$SSH_KEYGEN" ) { printf(catgets(MSG_FOUND, "found\n")); # Create SSH directory. my $sshdir = "$dir/.ssh"; if (! -d "$sshdir") { # SSH directory does not already exist, create it $rc = mkpath($sshdir, 0, 0700); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CREATE_DIR, "Cannot create directory %s.\n"), $sshdir); exit(2); } # Set directory owner $rc = chown($uid, $gid, $dir); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CHANGE_OWNER, "Cannot change %s owner.\n"), $dir); exit(2); } $rc = chown($uid, $gid, $sshdir); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CHANGE_OWNER, "Cannot change %s owner.\n"), $sshdir); exit(2); } } if (! -e "$sshdir/known_hosts") { my $fh; # Create initially empty known_hosts file open($fh, '>', "$sshdir/known_hosts") and close($fh); } # Always fix the known_hosts file owner chown($uid, $gid, "$sshdir/known_hosts"); # Ignore if it fails as it is not a fatal condition # Generate public/private SSH keys. printf(catgets(MSG_CHECKING_FOR_SSH_KEYS, "Checking for SSH keys...")); my $priv = "$sshdir/id_rsa"; my $pub = "$sshdir/id_rsa.pub"; if (! -e $priv || ! -e $pub) { my $localhost = hostname; system("$SSH_KEYGEN -t rsa -f $priv -N \"\" -C $user\@$localhost > /dev/null 2>&1"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_SSH_KEYS, "Cannot create SSH keys.\n")); exit(2); } # Change owner of the public/private SSH keys $rc = chown($uid, $gid, $priv); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CHANGE_OWNER, "Cannot change %s owner.\n"), $priv); exit(2); } $rc = chown($uid, $gid, $pub); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CHANGE_OWNER, "Cannot change %s owner.\n"), $pub); exit(2); } printf(catgets(MSG_GENERATED, "generated\n")); } else { printf(catgets(MSG_FOUND, "found\n")); } } else { printf(catgets(MSG_NOT_FOUND, "not found\n")); } # # Create data repository directory. # printf(catgets(MSG_CHECKING_DIRECTORY, "Checking directory %s..."), $directory); if (! -d "$directory") { $rc = mkpath($directory, 0, 0700); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CREATE_DIR, "Cannot create directory %s.\n"), $directory); exit(3); } printf(catgets(MSG_CREATED, "created\n")); } else { printf(catgets(MSG_FOUND, "found\n")); } if (defined($create)) { # option -c was specified # if -l not specified, use default $lvname = $LVNAME if (!defined($lvname)); # if -g not specified, use default $vgname = $VGNAME if (!defined($vgname)); # if -s not specified, use default $fssize = $FSSIZE if (!defined($fssize)); printf(catgets(MSG_CREATING_LOGICAL_VOLUME, "Creating logical volume %s in volume group %s..."), $lvname, $vgname); # Create Logical Volume. system("$MKLV -y $lvname -t $LVFS $vgname $fssize"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_LV, "Cannot create logical volume %s in volume group %s.\n"), $lvname, $vgname); exit(4); } # Create filesystem and mountpoint. system("$CRFS -v $LVFS -d $lvname -m $directory -A yes"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_FS, "Cannot create filesystem on %s.\n"), $lvname); exit(4); } # Mount filesystem. system("$MOUNT $directory"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_MOUNT_FS, "Cannot mount filesystem on %s.\n"), $directory); exit(4); } printf(catgets(MSG_DONE, "done\n")); } elsif (defined($lvname)) { # option -c was not specified but -l was specified # Create filesystem and mountpoint. printf(catgets(MSG_CREATING_FS, "Creating filesystem on existing logical volume %s.\n"), $lvname); system("$CRFS -v $LVFS -d $lvname -m $directory -A yes"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_CREATE_FS, "Cannot create filesystem on %s.\n"), $lvname); exit(4); } # Mount filesystem. system("$MOUNT $directory"); if ($? != 0) { printf(STDERR catgets(MSG_CANNOT_MOUNT_FS, "Cannot mount filesystem on %s.\n"), $directory); exit(4); } printf(catgets(MSG_DONE, "Done\n")); } $rc = chown($uid, $gid, $directory); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CHANGE_OWNER, "Cannot change %s owner.\n"), $directory); exit(3); } # always fix permissions chmod(0700, $directory); # # Update the ODM database. # cdat::odm_set_user($user); cdat::odm_set_path($directory); # # Create an initially empty cdat XML file. # printf(catgets(MSG_CREATING_XML_FILE, "Checking XML file...")); if (! -e "$directory/$XMLFILE") { my $tree = XML::LibXML->createDocument('1.0', cdat::locale_charmap); if (!defined($tree)) { printf(STDERR catgets(MSG_CANNOT_CREATE, "Cannot create %s.\n"), "$directory/$XMLFILE"); exit(1); } my $root_elt = $tree->createElement('collect-list'); $tree->setDocumentElement($root_elt); $tree->toFile("$directory/$XMLFILE", 2); $rc = chown($uid, $gid, "$directory/$XMLFILE"); if (!$rc) { printf(STDERR catgets(MSG_CANNOT_CHANGE_OWNER, "Cannot change %s owner.\n"), "$directory/$XMLFILE"); exit(1); } printf(catgets(MSG_CREATED, "created\n")); } else { printf(catgets(MSG_FOUND, "found\n")); } printf(catgets(MSG_DONE, "Done.\n")); } main;