AFS-Command

 view release on metacpan or  search on metacpan

CONFIG  view on Meta::CPAN

# We will need to create a pts group and user, and if these names are
# already taken, then change these lines.  The code will *remove* them
# when its done.
#
AFS_COMMAND_PTS_GROUP		= afscmdgroup
AFS_COMMAND_PTS_USER		= afscmduser

#
# If the AFS client on which the tests run does NOT match that
# specified above, then the pts group/user we create will NOT be
# visible to the fs setacl command.  Therefore, we need the name of an
# existing pts user or group to use for that test.
#
# Yes, I promise the tests will NOT remove this one, 'cause I did
# all the tests using my own ID. ;-)
#
AFS_COMMAND_PTS_EXISTING	= wpm

#
# If you don't have either gzip/gunzip, of bzip2/bunzip2, then comment
# the appropriate line to disable the tests using these compression

Changes  view on Meta::CPAN

    [2004-11-18 17:20:36] Error in vos release command.
    [2004-11-18 17:20:36] VLDB: no permission access for call

=head1 Changes in 1.8

=head1 Bug Fixes

=head2 vos examine did not pick up the LOCKED flag

The code to parse the VLDB header was missing the LOCKED flag, if it
was present, so this attribute was not being set properly.  It is now.

=head2 pts membership error checking was bogus

Well, it still is bogus, actually, since the code has to deal with the
fact that pts has never produced meaningful return codes, so a failed
pts membership command can still exit 0, and we have to figure out if
it failed by other means.  This is done by looking for the known error
messages that pts prints out, which is a good example of why parsing
the ASCII test output of commands like this is a weak architecture.

Changes  view on Meta::CPAN

=head1 Enhancements

=head2 Boolean flags can be turned off, as well as on

If an argument to a method (and its corresponding command line
argument) doesn't take a value, it is treated like a Boolean flag.
However, the code used to assume that the existence of a Boolean key
in the argument list implied the Boolean argument was always true.

Now, the truth of the arguments I<value> is tested to determine if the
flag should be set on or off.  This makes it easy to have subroutines
that just blindly pass certain arguments along, without haing to test
them, and allows for much cleaner code.

For example:

    my $result = $vos->release
      (
       name		=> $name,
       force		=> $force,
      );

Changes  view on Meta::CPAN


When a volume is busy or can not be attached, "vos examine" will be
unable to display the volume headers.  Instead, a one line message is
printed, such as one of the following:

    **** Volume 123456789 is busy ****
    **** Could not attach volume 123456789 ****

The examine method now parses these, and the AFS::Object::VolumeHeader
object will have only the 'id' and 'status' attributes.  Previously,
those lines were incorrectly parsed and the 'name' attribute set to
'****', which is pretty obviously wrong.




=head1 Changes in 1.3

=head1 Enhancements

=head2 AFS::Command::VOS->release support both -f and -force

Changes.html  view on Meta::CPAN

<HR>
<H1><A NAME="Bug_Fixes">Bug Fixes

</A></H1>
<P>
<HR>
<H2><A NAME="vos_examine_did_not_pick_up_the_">vos examine did not pick up the LOCKED flag

</A></H2>
The code to parse the VLDB header was missing the LOCKED flag, if it was
present, so this attribute was not being set properly. It is now.


<P>

<P>
<HR>
<H2><A NAME="pts_membership_error_checking_wa">pts membership error checking was bogus

</A></H2>
Well, it still is bogus, actually, since the code has to deal with the fact

Changes.html  view on Meta::CPAN


</A></H2>
If an argument to a method (and its corresponding command line argument)
doesn't take a value, it is treated like a Boolean flag. However, the code
used to assume that the existence of a Boolean key in the argument list
implied the Boolean argument was always true.


<P>

Now, the truth of the arguments <EM>value</EM> is tested to determine if the flag should be set on or off. This makes it
easy to have subroutines that just blindly pass certain arguments along,
without haing to test them, and allows for much cleaner code.


<P>

For example:


<P>

Changes.html  view on Meta::CPAN

<P>

<PRE>    **** Volume 123456789 is busy ****
    **** Could not attach volume 123456789 ****
</PRE>

<P>

The examine method now parses these, and the AFS::Object::VolumeHeader
object will have only the 'id' and 'status' attributes. Previously, those
lines were incorrectly parsed and the 'name' attribute set to '****', which
is pretty obviously wrong.


<P>

<P>
<HR>
<H1><A NAME="Changes_in_1_3">Changes in 1.3

</A></H1>

ToDo  view on Meta::CPAN

=head1 NAME

AFS::Command ToDo List

=head1 Enhancements

=head2 Accept AFS::Object objects as arguments

Methods like $fs->listacl() return these handy little AFS::Object::ACL
objects.  It would be nice if we could manipulate them via OO method
calls, and then pass them right back to $fs->setacl(), wouldn't it?

And how about passing the AFS::Object::Path objects returned from
$fs->whichcell directly to an $fs->listquota call, so that the final
AFS::Object::Path objects have all of the attributes returned by both
calls, but in one set of objects?

Look for this in version 1.1

=head2 stderr handling

stderr processing needs to be handled in the _exec_cmds() method, and
for that matter, _reap_cmds() needs to be folded into _exec_cmds().

The problem is that each API method calls _save_stderr(), and then
later calls _restore_stderr(), and we leave stderr redirected for

ToDo.html  view on Meta::CPAN

<H1><A NAME="Enhancements">Enhancements

</A></H1>
<P>
<HR>
<H2><A NAME="Accept_AFS_Object_objects_as_ar">Accept AFS::Object objects as arguments

</A></H2>
Methods like $fs-&gt;listacl() return these handy little AFS::Object::ACL
objects. It would be nice if we could manipulate them via OO method calls,
and then pass them right back to $fs-&gt;setacl(), wouldn't it?


<P>

And how about passing the AFS::Object::Path objects returned from
$fs-&gt;whichcell directly to an $fs-&gt;listquota call, so that the final
AFS::Object::Path objects have all of the attributes returned by both
calls, but in one set of objects?


<P>

Look for this in version 1.1


<P>

<P>

lib/AFS/Command.pod  view on Meta::CPAN


=head1 NAME

AFS::Command -- Wrapper Classes for the AFS Command Line Utilities

=head1 INTRODUCTION

Welcome to the OO Perl API for the AFS Command Line Utilities.  OK,
enough with formalities....

This set of classes implements a perl API for developing systems
administration applications for AFS, and is essentially a complete
rewrite of a similar API developed for perl4 almost a decade ago.

The API is designed to be as intuitive as the underlying command
themselves.  One of the strengths of the AFS CLI is its consistent
command line parsing, since all of the utilities share a common
library, and this API leverages this fact.  The methods available, and
their available arguments, are determined dynamically by parsing the
command help strings.

lib/AFS/Command/BOS.pm  view on Meta::CPAN


	next unless m:File $directory/(\S+) dated ([^,]+),:;

	my $file = AFS::Object->new
	  (
	   file			=> $1,
	   date			=> $2,
	  );

	if ( /\.BAK dated ([^,]+),/ ) {
	    $file->_setAttribute( bak => $1 );
	}

	if ( /\.OLD dated ([^,\.]+)/ ) {
	    $file->_setAttribute( old => $1 );
	}

	$result->_addFile($file);

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;

lib/AFS/Command/BOS.pm  view on Meta::CPAN

	} else {
	    $log .= $_;
	}
    }

    if ( $redirect ) {
	$redirect->close()|| do {
	    $self->_Carp("Unable to close $redirectname: $ERRNO");
	    $errors++
	};
	$result->_setAttribute( log => $redirectname );
    } else {
	$result->_setAttribute( log => $log );
    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

}

lib/AFS/Command/BOS.pm  view on Meta::CPAN


    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {

	if ( /restarts at (.*)/ || /restarts (never)/ ) {
	    $result->_setAttribute( restart => $1 );
	} elsif ( /binaries at (.*)/ || /binaries (never)/ ) {
	    $result->_setAttribute( binaries => $1 );
	}

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/BOS.pm  view on Meta::CPAN


    $errors++ unless $self->_exec_cmds();

    my @hosts = ();

    while ( defined($_ = $self->{handle}->getline()) ) {

	chomp;

	if ( /Cell name is (\S+)/i ) {
	    $result->_setAttribute( cell => $1 );
	}

	if ( /Host \d+ is (\S+)/i ) {
	    push(@hosts,$1);
	}

    }

    $result->_setAttribute( hosts => \@hosts );

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

}

sub listkeys {

lib/AFS/Command/BOS.pm  view on Meta::CPAN


    while ( defined($_ = $self->{handle}->getline()) ) {

	chomp;

	if ( /key (\d+)/ ) {

	    my $key = AFS::Object->new( index => $1 );

	    if ( /has cksum (\d+)/ ) {
		$key->_setAttribute( cksum => $1 );
	    } elsif ( /is \'([^\']+)\'/ ) {
		$key->_setAttribute( value => $1 );
	    }

	    $result->_addKey($key);

	}

	if ( /last changed on (.*)\./ ) {
	    $result->_setAttribute( keyschanged => $1 );
	}

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/BOS.pm  view on Meta::CPAN


    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {

	chomp;

	if ( /^SUsers are: (.*)/ ) {
	    $result->_setAttribute( susers => [split(/\s+/,$1)] );
	}

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/BOS.pm  view on Meta::CPAN


    $errors++ unless $self->_exec_cmds();

    my $instance = undef;

    while ( defined($_ = $self->{handle}->getline()) ) {

	chomp;

	if ( /inappropriate access/ ) {
	    $result->_setAttribute( access => 1 );
	    next;
	}

	if ( /Instance (\S+),/ ) {

	    if ( defined $instance ) {
		$result->_addInstance($instance);
	    }

	    $instance = AFS::Object::Instance->new( instance => $1 );

	    #
	    # This is ugly, since the order and number of these
	    # strings varies.
	    #
	    if ( /\(type is (\S+)\)/ ) {
		$instance->_setAttribute( type => $1 );
	    }

	    if ( /(disabled|temporarily disabled|temporarily enabled),/ ) {
		$instance->_setAttribute( state => $1 );
	    }

	    if ( /stopped for too many errors/ ) {
		$instance->_setAttribute( errorstop => 1 );
	    }

	    if ( /has core file/ ) {
		$instance->_setAttribute( core => 1 );
	    }

	    if ( /currently (.*)\.$/ ) {
		$instance->_setAttribute( status => $1 );
	    }

	}

	if ( /Auxiliary status is: (.*)\.$/ ) {
	    $instance->_setAttribute( auxiliary => $1 );
	}

	if ( /Process last started at (.*) \((\d+) proc starts\)/ ) {
	    $instance->_setAttribute
	      (
	       startdate		=> $1,
	       startcount		=> $2,
	      );
	}

	if ( /Last exit at (.*)/ ) {
	    $instance->_setAttribute( exitdate => $1 );
	}

	if ( /Last error exit at ([^,]+),/ ) {

	    $instance->_setAttribute( errorexitdate => $1 );

	    if ( /due to shutdown request/ ) {
		$instance->_setAttribute( errorexitdue => 'shutdown' );
	    }

	    if ( /due to signal (\d+)/ ) {
		$instance->_setAttribute
		  (
		   errorexitdue 	=> 'signal',
		   errorexitsignal	=> $1,
		  );
	    }

	    if ( /by exiting with code (\d+)/ ) {
		$instance->_setAttribute
		  (
		   errorexitdue 	=> 'code',
		   errorexitcode	=> $1,
		  );
	    }

	}

	if ( /Command\s+(\d+)\s+is\s+\'(.*)\'/ ) {
	    my $command = AFS::Object->new
	      (
	       index			=> $1,
	       command			=> $2,
	      );
	    $instance->_addCommand($command);
	}

	if ( /Notifier\s+is\s+\'(.*)\'/ ) {
	    $instance->_setAttribute( notifier => $1 );
	}

    }

    if ( defined $instance ) {
	$result->_addInstance($instance);
    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

lib/AFS/Command/BOS.pod  view on Meta::CPAN

       UseRootDirACL		=> 1,
       TraceBadLinkCounts	=> 1,
       DontAskFS		=> 1,
       LogLevel			=> $loglevel,
       rxdebug			=> 1,
       cell			=> $cell,
       noauth			=> 1,
       localauth		=> 1,
      );

=head2 setauth

The bos help string is:

    bos setauth: set authentication required flag
    Usage: bos setauth -server <machine name>
		       -authrequired <on or off: authentication required for admin requests>
		       [-cell <cell name>] [-noauth] [-localauth]

The corresponding method invocation looks like:

    my $result = $bos->setauth
      (
       # Required arguments
       server			=> $server,
       authrequired		=> $authrequired,
       # Optional arguments
       cell			=> $cell,
       noauth			=> 1,
       localauth		=> 1,
      );

=head2 setcellname

The bos help string is:

    bos setcellname: set cell name
    Usage: bos setcellname -server <machine name> -name <cell name>
			   [-cell <cell name>] [-noauth] [-localauth]

The corresponding method invocation looks like:

    my $result = $bos->setcellname
      (
       # Required arguments
       server			=> $server,
       name			=> $name,
       # Optional arguments
       cell			=> $cell,
       noauth			=> 1,
       localauth		=> 1,
      );

=head2 setrestart

The bos help string is:

    bos setrestart: set restart times
    Usage: bos setrestart -server <machine name> -time <time to restart server>
			  [-general] [-newbinary] [-cell <cell name>]
			  [-noauth] [-localauth]
    Where: -general    set general restart time
	   -newbinary  set new binary restart time

The corresponding method invocation looks like:

    my $result = $bos->setrestart
      (
       # Required arguments
       server			=> $server,
       time			=> $time,
       # Optional arguments
       general			=> 1,
       newbinary		=> 1,
       cell			=> $cell,
       noauth			=> 1,
       localauth		=> 1,

lib/AFS/Command/Base.pm  view on Meta::CPAN


our $AUTOLOAD	= "";
our $VERSION = '1.99';

our %Carp =
  (
   carp		=> \&Carp::carp,
   croak	=> \&Carp::croak,
  );

sub setCarp {

    my $class = shift;
    my (%args) = @_;

    foreach my $key ( keys %args ) {
	unless ( $Carp{$key} ) {
	    croak("Unsupported argument: '$key'");
	}
	unless ( ref $args{$key} eq 'CODE' ) {
	    croak("Not a code reference: '$args{$key}'");
	}
	$Carp{$key} = $args{$key};
    }

    return AFS::Object->_setCarp(@_);

}

sub new {

    my $proto = shift;
    my $class = ref($proto) || $proto;
    my %args = @_;

    my $self = {};

lib/AFS/Command/Base.pod  view on Meta::CPAN

     );

If the path given is invalid, then expect the API to implode on itself
when it can't be found, or it isn't an AFS vos command.

=item localauth, noauth, encrypt

All of these arguments correspond to command line arguments common
across the entire command line suite.  Typically, if an application
uses this flag once, it will be using it for B<all> subsequent calls as
well.  Therefore, the state of these flags can be set globally by
setting them when creating the command object.

    my $vos = AFS::Command::VOS->new
      (
       localauth	=> 1,
       encrypt		=> 1,
      );

NOTE: The encrypt option is only available in more recent versions of
AFS, and may be unsupported by the underlying commands.

lib/AFS/Command/Base.pod  view on Meta::CPAN

vos release, which can be very time consuming.  Since we enable
-verbose by default, this option will let us determine the relative
time required for each step in these complex operations.

This only applies to commands that return simple return values, eg:
release, restore, etc.  Commands that return complex structures of
objects, such as listvldb, listvol, etc will not be affected.

=back

=head2 setCarp

This class method configures the carp and/or croak subroutines used
throughout the API.  By default, the obviously sensible thing is done:
the carp an croak subroutines exported by the Carp module are used.
These normally print output to stderr, and this method provides a
mechanism for trapping these errors and redirecting them elsewhere.

For example, stderr in a system daemon may be entirely ignored, and
syslog may be a more appropriate destination.  In this case, the
setCarp method may be used to configure this, globally, for the entire
API.

    AFS::Command->setCarp
      (

       carp => sub {
	   my ($lines) = @_;
	   foreach my $line ( split(/\n+/,$lines) ) {
	       syslog('warning',$line);
	   }
       },

       croak => sub {

lib/AFS/Command/Base.pod  view on Meta::CPAN

This method returns true of false, depending on whether or not the
carp and/or croak subroutines were properly configured.  If the values
are not CODE references, then this method will itself croak.

=head1 INSTANCE METHODS

=head2 errors

This method takes no arguments, and it returns a string, containing the
unparsed errors from the last command method invoked.  This string is
reset with each subsequent command method invocation.  The string is
normally the output written to stderr by the process, but in the case
of unparsed boolean commands, it contains both the stdout as well as
the stderr output.

    my $result = $vos->examine
      (
       id		=> $volname,
       cell		=> $cell,
      );
    unless ( $result ) {

lib/AFS/Command/FS.pm  view on Meta::CPAN


    $errors++ unless $self->_exec_cmds();

    my @servers = ();

    while ( defined($_ = $self->{handle}->getline()) ) {

	chomp;

	if ( /The current down server probe interval is (\d+) secs/ ) {
	    $result->_setAttribute( interval => $1 );
	}

	if ( /These servers are still down:/ ) {
	    while ( defined($_ = $self->{handle}->getline()) ) {
		s/^\s+//g;
		s/\s+$//g;
		push(@servers,$_);
	    }
	}
    }

    $result->_setAttribute( servers => \@servers );

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

}

sub diskfree {

lib/AFS/Command/FS.pm  view on Meta::CPAN


	next if /^Volume Name/;

	my $path = AFS::Object::Path->new();

	if ( /fs: Invalid argument; it is possible that (.*) is not in AFS./ ||
	     /fs: no such cell as \'(.*)\'/ ||
	     /fs: File \'(.*)\' doesn\'t exist/ ||
	     /fs: You don\'t have the required access rights on \'(.*)\'/ ) {

	    $path->_setAttribute
	      (
	       path 		=> $1,
	       error		=> $_,
	      );

	    delete $paths{$1};
	    @paths = grep($_ ne $1,@paths);

	} else {

	    if ( $operation eq 'listacl' ) {

		if ( /^Access list for (.*) is/ ) {

		    $path->_setAttribute( path => $1 );
		    delete $paths{$1};

		    my $normal 		= AFS::Object::ACL->new();
		    my $negative 	= AFS::Object::ACL->new();

		    my $type = 0;

		    while ( defined($_ = $self->{handle}->getline()) ) {

			s/^\s+//g;

lib/AFS/Command/FS.pm  view on Meta::CPAN

			my ($principal,$rights) 	= split;

			if ( $type == 1 ) {
			    $normal->_addEntry( $principal => $rights );
			} elsif ( $type == -1 ) {
			    $negative->_addEntry( $principal => $rights );
			}

		    }

		    $path->_setACLNormal($normal);
		    $path->_setACLNegative($negative);

		}

	    }

	    if ( $operation eq 'whichcell' ) {

		if ( /^File (\S+) lives in cell \'([^\']+)\'/ ) {

		    $path->_setAttribute
		      (
		       path	=> $1,
		       cell 	=> $2,
		      );
		    delete $paths{$1};

		}

	    }

	    if ( $operation eq 'whereis' ) {

		if ( /^File (.*) is on hosts? (.*)$/ ) {

		    $path->_setAttribute
		      (
		       path 			=> $1,
		       hosts			=> [split(/\s+/,$2)],
		      );
		    delete $paths{$1};

		}

	    }

	    if ( $operation eq 'storebehind' ) {

		if ( /Default store asynchrony is (\d+) kbytes/ ) {

		    $default = $1;
		    next;

		} elsif ( /Will store (.*?) according to default./ ) {

		    $path->_setAttribute
		      (
		       path 			=> $1,
		       asynchrony 		=> 'default',
		      );

		    delete $paths{$1};
		    @paths = grep($_ ne $1,@paths);

		} elsif ( /Will store up to (\d+) kbytes of (.*?) asynchronously/ ) {

		    $path->_setAttribute
		      (
		       path 			=> $2,
		       asynchrony 		=> $1,
		      );

		    delete $paths{$2};
		    @paths = grep($_ ne $2,@paths);

		}

	    }

	    if ( $operation eq 'quota' ) {

		if ( /^\s*(\d{1,2})%/ ) {

		    $path->_setAttribute
		      (
		       path 			=> $paths[0],
		       percent			=> $1,
		      );
		    delete $paths{$paths[0]};
		    shift @paths;

		}

	    }

lib/AFS/Command/FS.pm  view on Meta::CPAN

		# space, so we get rid of this one annoying instance.
		#
		s/no limit/nolimit/g;

		my ($volname,$quota,$used,$percent,$partition) = split;

		$quota = 0 if $quota eq "nolimit";
		$percent =~ s/\D//g; # want numeric result
		$partition =~ s/\D//g; # want numeric result

		$path->_setAttribute
		  (
		   path				=> $paths[0],
		   volname			=> $volname,
		   quota			=> $quota,
		   used				=> $used,
		   percent			=> $percent,
		   partition			=> $partition,
		  );
		delete $paths{$paths[0]};
		shift @paths;

	    }

	    if ( $operation eq 'diskfree' ) {

		my ($volname,$total,$used,$avail,$percent) = split;
		$percent =~ s/%//g; # Don't need it -- want numeric result

		$path->_setAttribute
		  (
		   path				=> $paths[0],
		   volname			=> $volname,
		   total			=> $total,
		   used				=> $used,
		   avail			=> $avail,
		   percent			=> $percent,
		  );
		delete $paths{$paths[0]};
		shift @paths;

	    }

	    if ( $operation eq 'examine' ) {

		if ( /Volume status for vid = (\d+) named (\S+)/ ) {

		    $path->_setAttribute
		      (
		       path			=> $paths[0],
		       id			=> $1,
		       volname			=> $2,
		      );

		    #
		    # Looking at Transarc's code, we can safely assume we'll
		    # get this output in the order shown. Note we ignore the
		    # "Message of the day" and "Offline reason" output for
		    # now.  Read until we hit a blank line.
		    #
		    while ( defined($_ = $self->{handle}->getline()) ) {

			last if /^\s*$/;

			if ( /Current disk quota is (\d+|unlimited)/ ) {
			    $path->_setAttribute
			      (
			       quota		=>  $1 eq "unlimited" ? 0 : $1,
			      );
			}

			if ( /Current blocks used are (\d+)/ ) {
			    $path->_setAttribute( used => $1 );
			}

			if ( /The partition has (\d+) blocks available out of (\d+)/ ) {
			    $path->_setAttribute
			      (
			       avail		=> $1,
			       total		=> $2,
			      );
			}
		    }

		    delete $paths{$paths[0]};
		    shift @paths;

lib/AFS/Command/FS.pm  view on Meta::CPAN

	    }

	}

	$result->_addPath($path);

    }

    if ( $operation eq 'storebehind' ) {

	$result->_setAttribute( asynchrony => $default );

	#
	# This is ugly, but we get the default last, and it would be nice
	# to put this value into the Path objects as well, rather than the
	# string 'default'.
	#
	foreach my $path ( $result->getPaths() ) {
	    if ( defined($path->asynchrony()) && $path->asynchrony() eq 'default' ) {
		$path->_setAttribute( asynchrony => $default );
	    }
	}
    }

    foreach my $pathname ( keys %paths ) {

	my $path = AFS::Object::Path->new
	  (
	   path			=> $pathname,
	   error		=> "Unable to determine results",

lib/AFS/Command/FS.pm  view on Meta::CPAN


    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {

	/translator is (currently )?enabled/ && do {
	    $result->_setAttribute( enabled => 1 );
	};

	/translator is disabled/ && do {
	    $result->_setAttribute( enabled => 0 );
	};

	/convert owner mode bits/ && do {
	    $result->_setAttribute( convert => 1 );
	};

	/strict unix/ && do {
	    $result->_setAttribute( convert => 0 );
	};

	/strict \'?passwd sync\'?/ && do {
	    $result->_setAttribute( uidcheck => 1 );
	};

	/no \'?passwd sync\'?/ && do {
	    $result->_setAttribute( uidcheck => 0 );
	};

	/allow mounts/i && do {
	    $result->_setAttribute( submounts => 1 );
	};

	/Only mounts/i && do {
	    $result->_setAttribute( submounts => 0 );
	};

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/FS.pm  view on Meta::CPAN

    return unless $self->_parse_arguments(%args);

    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {
	if ( /using (\d+) of the cache.s available (\d+) 1K/ ) {
	    $result->_setAttribute
	      (
	       used			=> $1,
	       avail			=> $2,
	      );
	}
    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

lib/AFS/Command/FS.pm  view on Meta::CPAN

    return unless $self->_parse_arguments(%args);

    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {

	if ( /Cell (\S+) status: (no )?setuid allowed/ ) {
	    my $cell = AFS::Object::Cell->new
	      (
	       cell			=> $1,
	       status			=> $2 ? 0 : 1,
	      );
	    $result->_addCell($cell);
	}

    }

lib/AFS/Command/FS.pm  view on Meta::CPAN


    my @addresses = ();

    while ( defined($_ = $self->{handle}->getline()) ) {
	chomp;
	s/^\s+//;
	s/\s+$//;
	push(@addresses,$_);
    }

    $result->_setAttribute( addresses => \@addresses );

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

}

sub getcrypt {

lib/AFS/Command/FS.pm  view on Meta::CPAN


    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {

	if ( /Security level is currently (crypt|clear)/ ) {
	    $result->_setAttribute( crypt => ($1 eq 'crypt' ? 1 : 0) );
	}

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/FS.pm  view on Meta::CPAN

    my %dirs = map { $_ => 1 } @dirs;

    while ( defined($_ = $self->{handle}->getline()) ) {

	my $current = shift @dirs;
	delete $dirs{$current};

	my $path = AFS::Object::Path->new( path => $current );

	if ( /fs: Can.t read target name/ ) {
	    $path->_setAttribute( error => $_ );
	} elsif ( /fs: File '.*' doesn't exist/ ) {
	    $path->_setAttribute( error => $_ );
	} elsif ( /fs: you may not use \'.\'/ ) {
	    $_ .= $self->{handle}->getline();
	    $path->_setAttribute( error => $_ );
	} elsif ( /\'(.*?)\' is not a mount point/ ) {
	    $path->_setAttribute( error => $_ );
	} elsif ( /^\'(.*?)\'.*?\'(.*?)\'$/ ) {

	    my ($dir,$mount) = ($1,$2);

	    $path->_setAttribute( symlink => 1 ) if /symbolic link/;
	    $path->_setAttribute( readwrite => 1 ) if $mount =~ /^%/;
	    $mount =~ s/^(%|\#)//;

	    my ($volname,$cell) = reverse split(/:/,$mount);

	    $path->_setAttribute( volname => $volname );
	    $path->_setAttribute( cell => $cell) if $cell;

	} else {

	    $self->_Carp("fs lsmount: Unrecognized output: '$_'");
	    $errors++;
	    next;

	}

	$result->_addPath($path);

lib/AFS/Command/FS.pm  view on Meta::CPAN


    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    my @sysname = ();

    while ( defined($_ = $self->{handle}->getline()) ) {

	if ( /Current sysname is \'?([^\']+)\'?/ ) {
	    $result->_setAttribute( sysname => $1 );
	} elsif ( s/Current sysname list is // ) {
	    while ( s/\'([^\']+)\'\s*// ) {
		push(@sysname,$1);
	    }
	    $result->_setAttribute( sysnames => \@sysname );
	    $result->_setAttribute( sysname => $sysname[0] );
	}

    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/FS.pm  view on Meta::CPAN

    return unless $self->_parse_arguments(%args);

    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {
	next unless /belongs to cell\s+\'(.*)\'/;
	$result->_setAttribute( cell => $1 );
    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

}

lib/AFS/Command/FS.pod  view on Meta::CPAN


A number of these methods accept a list of paths, and will return
information for each path, individually.  If you specify a
non-existent path, or one which is not in AFS, then the fs command
returns a non-zero exist status, which normally would mean the command
failed.

If you specify a list of paths to this API, and one or more of them
result in errors, the API call is still considered to succeed, as long
as we can determine the error for each path specified.  The API will
still return an AFS::Object::CacheManager object, which contains a set
of AFS::Object::Path object, for each path specified in the arguments,
as long as we saw some kind of output from the fs commands for each
path.

Each AFS::Object::Path object must be examined to determine the
success of failure for that individual path.  When errors were
encountered for any given path, then the objects will have an "error"
attribute, and nothing else (no other data attributes, except the path
itself).

lib/AFS/Command/FS.pod  view on Meta::CPAN

If no errors were encountered, then the following attributes will be present:

    Attributes			Values
    ----------			------
    path			The pathname
    volname			The AFS volume name that contains the pathname
    id				The numerical volume ID of the above volume
    total			The size (in KB) of the partition that contains 'volname'
    used			The amount of space (in KB) used on that partition
    avail			The amount of space (in KB) available on that partition
    quota			The quota of the volume (in KB), or 0 if set to "unlimited"

=back

=head2 exportafs

=over

=item Arguments

The fs help string is:

lib/AFS/Command/FS.pod  view on Meta::CPAN


This method returns an AFS::Object::CacheManager object with one or
more attributes.

    my $result = $fs->exportafs
      (
       type			=> 'nfs',
       start			=> 'on',
      ) || die $fs->errors();
    foreach my $attr ( qw( convert uidcheck submounts ) ) {
	print "Translator has '$attr' set to '" . $result->$attr() . "'\n";
    }

The object has the following attribute:

B<AFS::Object::CacheManager>

    Attributes			Values
    ----------			------
    enabled			Boolean, true means the translator is on, false means off
    convert			Boolean, true means mode bits are converted from AFS to UNIX, false means off

lib/AFS/Command/FS.pod  view on Meta::CPAN

This method returns an AFS::Object::CacheManager object which contains
one or more AFS::Object::Cell objects.

    my $result = $fs->getcellstatus
      (
       cell			=> [ $cell1 , $cell2 ],
      ) || die $fs->errors();
    foreach my $cellobj ( $result->getCells() ) {
	my $cell = $cellobj->cell();
	if ( $cellobj->status() ) {
	    print("This client allows setuid binaries from cell '$cell'\n";
	} else {
	    print("This client does NOT allow setuid binaries from cell '$cell'\n";
	}
    }

The objects have the following attributes and methods:

B<AFS::Object::CacheManager>

    Methods			Returns
    -------			-------
    getCellNames()		list of cell names
    getCells()			list of AFS::Object::Cell objects
    getCell($cell)		the AFS::Object::Cell object for cell $cell

B<AFS::Object::Cell>

    Attributes			Values
    ----------			------
    cell			AFS cell name
    status			Boolean, true indicating setuid/gid bits are allowed,
				false indicating they are not

=back

=head2 getclientaddrs

=over

=item Arguments

lib/AFS/Command/FS.pod  view on Meta::CPAN

=back

=head2 getcrypt

=over

=item Arguments

The fs help string is:

    fs getcrypt: set cache manager encryption flag
    Usage: fs getcrypt

The corresponding method invocation looks like:

    my $result = $fs->getcrypt();

=item Return Values

This method returns an AFS::Object::CacheManager object with one attribute.

lib/AFS/Command/FS.pod  view on Meta::CPAN

=back

=head2 sysname

=over

=item Arguments

The fs help string is:

    fs sysname: get/set sysname (i.e. @sys) value
    Usage: fs sysname [-newsys <new sysname>+]

The corresponding method invocation looks like:

    my $result = $fs->sysname
      (
       # Optional arguments
       newsys			=> $sysname, # OR [ $sysname1, $sysname2, ... ]
      );

lib/AFS/Command/FS.pod  view on Meta::CPAN

The corresponding method invocation looks like:

    my $result = $fs->rxstatproc
      (
       # Optional arguments
       enable			=> 1,
       disable			=> 1,
       clear			=> 1,
      );

=head2 setacl

The fs help string is:

    fs setacl: set access control list
    Usage: fs setacl -dir <directory>+ -acl <access list entries>+
		     [-clear] [-negative] [-id] [-if]
    Where: -clear     clear access list
	   -negative  apply to negative rights
	   -id        initial directory acl (DFS only)
	   -if        initial file acl (DFS only)

The corresponding method invocation looks like:

    my $result = $fs->setacl
      (
       # Required arguments
       dir			=> $dir, # OR [ $dir1, $dir2, ... ]
       acl			=> [ <<see below>> ],
       # Optional arguments
       clear			=> 1,
       negative			=> 1,
       id			=> 1,
       if			=> 1,
      );

lib/AFS/Command/FS.pod  view on Meta::CPAN

with care.  Unlike many of the other arguments, this has to be a seen
by the 'fs' command as an even number of additional command line
arguments immediately after the -acl flag.

If you construct a single string, such as "user read group write",
then the method will fail.  There is no shell involved in exec'ing fs,
so there will be no splitting of this string on whitespace before we
construct the arguments to fs, so it will look like a single argument,
not four distinct arguments.

Therefore, there are two ways to construct an ACL to pass to setacl():

    my @acl = ( $user, 'read', $group, 'write' );
    my $result = $fs->setacl
      (
       dir			=> $dir,
       acl			=> \@acl,
      );

    my %acl =
      (
       $user			=> 'read',
       $group			=> 'write',
      );
    my $result = $fs->setacl
      (
       dir			=> $dir,
       acl			=> \%acl,
      );

In a future release of the API, maybe even 1.1, it will be possible to
pass AFS::Object::ACL objects as arguments to these API
calls, but not yet...

=head2 setcachesize

The fs help string is:

    fs setcachesize: set cache size
    Usage: fs setcachesize [-blocks <size in 1K byte blocks (0 => reset)>] [-reset]
    Where: -reset  reset size back to boot value

The corresponding method invocation looks like:

    my $result = $fs->setcachesize
      (
       # Optional arguments
       blocks			=> $blocks,
       reset			=> 1,
      );

=head2 setcell

The fs help string is:

    fs setcell: set cell status
    Usage: fs setcell -cell <cell name>+ [-suid] [-nosuid]
    Where: -suid    allow setuid programs
	   -nosuid  disallow setuid programs

The corresponding method invocation looks like:

    my $result = $fs->setcell
      (
       # Required arguments
       cell			=> $cell, # OR [ $cell1, $cell2, ... ]
       # Optional arguments
       suid			=> 1,
       nosuid			=> 1,
      );

=head2 setclientaddrs

The fs help string is:

    fs setclientaddrs: set client network interface addresses
    Usage: fs setclientaddrs [-address <client network interfaces>+]

The corresponding method invocation looks like:

    my $result = $fs->setclientaddrs
      (
       # Required arguments
       address			=> $address, # OR [ $address1, $address2, ... ]
      );

=head2 setcrypt

The fs help string is:

    fs setcrypt: set cache manager encryption flag
    Usage: fs setcrypt -crypt <on or off>

The corresponding method invocation looks like:

    my $result = $fs->setcrypt
      (
       # Required arguments
       crypt			=> 1,
      );

=head2 setquota

The fs help string is:

    fs setquota: set volume quota
    Usage: fs setquota [-path <dir/file path>] -max <max quota in kbytes>

The corresponding method invocation looks like:

    my $result = $fs->setquota
      (
       # Required arguments
       max			=> $max,
       # Optional arguments
       path			=> $path, # OR [ $path1, $path2, ... ]
      );

=head2 setserverprefs

The fs help string is:

    fs setserverprefs: set server ranks
    Usage: fs setserverprefs [-servers <fileserver names and ranks>+]
			     [-vlservers <VL server names and ranks>+]
			     [-file <input from named file>] [-stdin]
    Where: -stdin  input from stdin

The corresponding method invocation looks like:

    my $result = $fs->setserverprefs
      (
       # Optional arguments
       servers			=> $server, # OR [ $server1, $server2, ... ]
       vlservers		=> $vlserver, # OR [ $vlserver1, $vlserver2, ... ]
       file			=> $file,
       stdin			=> 1,
      );

=head2 setvol

The fs help string is:

    fs setvol: set volume status
    Usage: fs setvol [-path <dir/file path>+] [-max <disk space quota in 1K units>]
		     [-offlinemsg <offline message>]

The corresponding method invocation looks like:

    my $result = $fs->setvol
      (
       # Optional arguments
       path			=> $path, # OR [ $path1, $path2, ... ]
       max			=> $max,
       offlinemsg   		=> $offlinemsg,
      );

=head1 SEE ALSO

AFS::Command(1), AFS::Object(1)

lib/AFS/Command/PTS.pm  view on Meta::CPAN

    return unless $self->_parse_arguments(%args);

    return unless $self->_save_stderr();

    my $errors = 0;

    $errors++ unless $self->_exec_cmds();

    while ( defined($_ = $self->{handle}->getline()) ) {
	next unless /Max user id is (\d+) and max group id is (-\d+)/;
	$result->_setAttribute
	  (
	   maxuserid		=> $1,
	   maxgroupid		=> $2,
	  );
    }

    $errors++ unless $self->_reap_cmds();
    $errors++ unless $self->_restore_stderr();

    return if $errors;

lib/AFS/Command/PTS.pod  view on Meta::CPAN

      (
       # Required arguments
       oldname			=> $oldname,
       newname			=> $newname,
       # Optional arguments
       cell			=> $cell,
       noauth			=> 1,
       force			=> 1,
      );

=head2 setfields

The pts help string is:

pts setfields: set fields for an entry
Usage: pts setfields -nameorid <user or group name or id>+ [-access <set privacy flags>]
                     [-groupquota <set limit on group creation>]
                     [-cell <cell name>] [-noauth] [-force]

The corresponding method invocation looks like:

    my $result = $pts->setfields
      (
       # Required arguments
       nameorid			=> $nameorid, # OR [ $nameorid1, $nameorid2, ... ]
       # Optional arguments
       access			=> $access,
       groupquota		=> $groupquota,
       cell			=> $cell,
       noauth			=> 1,
       force			=> 1,
      );

=head2 setmax

The pts help string is:

    pts setmax: set max id
    Usage: pts setmax [-group <group max>] [-user <user max>]
		      [-cell <cell name>] [-noauth] [-force]

The corresponding method invocation looks like:

    my $result = $pts->setmax
      (
       # Optional arguments
       user			=> $user,
       group			=> $group,
       cell			=> $cell,
       noauth			=> 1,
       force			=> 1,
      );

=head1 SEE ALSO

lib/AFS/Command/VOS.pm  view on Meta::CPAN

	# this line, then we go after the information we expect to be
	# right after it.  We also test for this first, because we
	# might very well have several of these chunks of data for RO
	# volumes.
	#
	if ( /^\*{4}/ ) {

	    my $header = AFS::Object::VolumeHeader->new();

	    if ( /Volume (\d+) is busy/ ) {
		$header->_setAttribute
		  (
		   id			=> $1,
		   status		=> 'busy',
		   attached		=> 1,
		  );
	    } elsif ( /Could not attach volume (\d+)/ ) {
		$header->_setAttribute
		  (
		   id			=> $1,
		   status		=> 'offline',
		   attached		=> 0,
		  );
	    }

	    $result->_addVolumeHeader($header);

	    next;

	} elsif ( /^(\S+)\s+(\d+)\s+(RW|RO|BK)\s+(\d+)\s+K/ ) {

	    my $header = AFS::Object::VolumeHeader->new();

	    if ( /^(\S+)\s+(\d+)\s+(RW|RO|BK)\s+(\d+)\s+K\s+([\w-]+)/ ) {

		$header->_setAttribute
		  (
		   name			=> $1,
		   id 			=> $2,
		   type 		=> $3,
		   size 		=> $4,
		  );
		$header->_setAttribute( rwrite	=> $2 ) if $3 eq 'RW';
		$header->_setAttribute( ronly	=> $2 ) if $3 eq 'RO';
		$header->_setAttribute( backup	=> $2 ) if $3 eq 'BK';

		my $status = $5;
		$status = 'offline' if $status eq 'Off-line';
		$status = 'online' if $status eq 'On-line';
		$header->_setAttribute
		  (
		   status 		=> $status,
		   attached		=> 1,
		  );

	    } elsif ( /^(\S+)\s+(\d+)\s+(RW|RO|BK)\s+(\d+)\s+K\s+used\s+(\d+)\s+files\s+([\w-]+)/ ) {

		$header->_setAttribute
		  (
		   name			=> $1,
		   id			=> $2,
		   type 		=> $3,
		   size 		=> $4,
		   files 		=> $5,
		  );
		$header->_setAttribute( rwrite	=> $2 ) if $3 eq 'RW';
		$header->_setAttribute( ronly	=> $2 ) if $3 eq 'RO';
		$header->_setAttribute( backup	=> $2 ) if $3 eq 'BK';

		my $status = $6;
		$status = 'offline' if $status eq 'Off-line';
		$status = 'online' if $status eq 'On-line';
		$header->_setAttribute
		  (
		   status 		=> $status,
		   attached		=> 1,
		  );

	    } else {

		$self->_Carp("Unable to parse volume header: '$_'");

	    }

lib/AFS/Command/VOS.pm  view on Meta::CPAN

	    # from the same volume headers as the one we just matched.
	    # Suck data until we get to a blank line.
	    #
	    while ( defined($_ = $self->{handle}->getline()) ) {

		chomp;

		last if /^\s*$/; # Stop when we hit the blank line

		if ( m:^\s+(\S+)\s+(/vicep\w+)\s*$: ) {
		    $header->_setAttribute
		      (
		       server		=> $1,
		       partition	=> $2,
		      );
		    next;
		}

		#
		# Next we get ALL the volume IDs we can off this next
		# line.
		#
		# Q: Do we want to check that the id already found
		# matches one of these??  Not yet...
		#
		if ( /^\s+RWrite\s+(\d+)\s+ROnly\s+(\d+)\s+Backup\s+(\d+)/ ) {

		    $header->_setAttribute
		      (
		       rwrite		=> $1,
		       ronly		=> $2,
		       backup		=> $3,
		      );

		    if ( /RClone\s+(\d+)/ ) {
			$header->_setAttribute( rclone	=> $1 );
		    }
		    next;

		}

		if ( /^\s+MaxQuota\s+(\d+)/ ) {
		    $header->_setAttribute( maxquota	=> $1 );
		    next;
		}

		if ( /^\s+Creation\s+(.*)\s*$/ ) {
		    $header->_setAttribute( creation	=> $1 );
		    next;
		}

		if ( /^\s+Copy\s+(.*)\s*$/ ) {
		    $header->_setAttribute( copyTime	=> $1 );
		    next;
		}

		if ( /^\s+Backup\s+(.*)\s*$/ ) {
		    $header->_setAttribute( backupTime	=> $1 );
		    next;
		}

		if ( /^\s+Last Access\s+(.*)\s*$/ ) {
		    $header->_setAttribute( access	=> $1 );
		    next;
		}

		if ( /^\s+Last Update\s+(.*)\s*$/ ) {
		    $header->_setAttribute( update	=> $1 );
		    next;
		}

		if ( /^\s+(\d+) accesses/ ) {
		    $header->_setAttribute( accesses	=> $1 );
		    next;
		}

		#
		# If we get this far, then we have an unrecognized
		# line of vos examine output.  Complain.
		#
		$self->_Carp("Unrecognized output format:\n" . $_);

	    }

lib/AFS/Command/VOS.pm  view on Meta::CPAN

			   total		=> $column[2],
			   auth			=> $column[3],
			  );

			my $stats = AFS::Object->new
			  (
			   same			=> $same,
			   diff			=> $diff,
			  );

			$raw->_setAttribute( $class	=> $stats );

		    }

		    $int = '0sec' 		if /^0-60 sec/;
		    $int = '1min' 		if /^1-10 min/;
		    $int = '10min' 		if /^10min-1hr/;
		    $int = '1hr' 		if /^1hr-1day/;
		    $int = '1day' 		if /^1day-1wk/;
		    $int = '1wk' 		if /^> 1wk/;

lib/AFS/Command/VOS.pm  view on Meta::CPAN

			   same			=> $column[2],
			   diff			=> $column[3],
			  );

			my $stats = AFS::Object->new
			  (
			   file			=> $file,
			   dir			=> $dir,
			  );

			$author->_setAttribute( $int	=>  $stats );

		    }

		}

		$header->_setAttribute
		  (
		   raw				=> $raw,
		   author			=> $author,
		  );

	    }

	    $result->_addVolumeHeader($header);

	    next;

lib/AFS/Command/VOS.pm  view on Meta::CPAN

	}

	#
	# The rest of the information we get will be from the
	# VLDB. This will start with the volume ids, which we DO want
	# to check against those found above, since they are from a
	# different source, and a conflict is cause for concern.
	#
	if ( /^\s+RWrite:\s+(\d+)/ ) {

	    if ( /RWrite:\s+(\d+)/ ) { $entry->_setAttribute( rwrite	=> $1 ); }
	    if ( /ROnly:\s+(\d+)/ )  { $entry->_setAttribute( ronly	=> $1 ); }
	    if ( /Backup:\s+(\d+)/ ) { $entry->_setAttribute( backup	=> $1 ); }
	    if ( /RClone:\s+(\d+)/ ) { $entry->_setAttribute( rclone	=> $1 ); }

	    next;

	}			# if ( /^\s+RWrite:....

	#
	# Next we are looking for the number of sites, and then we'll
	# suck that data in as well.
	#
	# NOTE: Because there is more interesting data after the

lib/AFS/Command/VOS.pm  view on Meta::CPAN


	    }

	}

	#
	# Last possibility (that we know of) -- volume might be
	# locked.
	#
	if ( /LOCKED/ ) {
	    $entry->_setAttribute( locked => 1 );
	    next;
	}

	#
	# Actually, this is the last possibility...  The volume name
	# leading the VLDB entry stanza.
	#
	if ( /^(\S+)/ ) {
	    $entry->_setAttribute( name => $1 );
	}

    }

    $result->_addVLDBEntry($entry);

    $errors++ unless $self->_reap_cmds();

    $errors++ unless $self->_restore_stderr();

lib/AFS/Command/VOS.pm  view on Meta::CPAN

		    s/\s*$//g;
		    last if /^\s*$/;
		    chomp;
		    if ( /^\d+\.\d+\.\d+\.\d+$/ ) {
			push(@addresses,$_);
		    } else {
			$hostname = $_;
		    }
		}

		$fileserver->_setAttribute( addresses => \@addresses ) if @addresses;
		$fileserver->_setAttribute( hostname => $hostname ) if $hostname;

		push(@result,$fileserver);

	    }

	}

    } elsif ( $args{uuid} ) {

	my @addresses = ();

lib/AFS/Command/VOS.pm  view on Meta::CPAN

	    s/\s*$//g;
	    if ( /^\d+\.\d+\.\d+\.\d+$/ ) {
		push(@addresses,$_);
	    } else {
		$hostname = $_;
	    }
	}

	if ( $hostname || @addresses ) {
	    my $fileserver = AFS::Object::FileServer->new();
	    $fileserver->_setAttribute( addresses => \@addresses ) if @addresses;
	    $fileserver->_setAttribute( hostname => $hostname ) if $hostname;
	    push(@result,$fileserver);
	}

    } else {

	while ( defined($_ = $self->{handle}->getline()) ) {
	    chomp;
	    s/^\s*//g;
	    s/\s*$//g;
	    if ( /^\d+\.\d+\.\d+\.\d+$/ ) {

lib/AFS/Command/VOS.pm  view on Meta::CPAN

	#
	next if /^VLDB entries for /;

	s/\s+$//g;		# Might be trailing whitespace...

	#
	# We either get the total number of volumes, or we assume the
	# line is a volume name.
	#
	if ( /Total entries:\s+(\d+)/ ) {
	    $result->_setAttribute( total => $1 );
	    next;
	}

	my $name = $_;

	my $entry = AFS::Object::VLDBEntry->new( name => $name );

	while ( defined($_ = $self->{handle}->getline()) ) {

	    chomp;

	    last if /^\s*$/;	# Volume info ends with a blank line

	    #
	    # Code to parse this output lives in examine.pl.  This
	    # will need to be made generic and used here to parse and
	    # return the full vldb entry.
	    #

	    if ( /RWrite:\s+(\d+)/ ) { $entry->_setAttribute( rwrite 	=> $1 ); }
	    if ( /ROnly:\s+(\d+)/ )  { $entry->_setAttribute( ronly 	=> $1 ); }
	    if ( /Backup:\s+(\d+)/ ) { $entry->_setAttribute( backup	=> $1 ); }
	    if ( /RClone:\s+(\d+)/ ) { $entry->_setAttribute( rclone	=> $1 ); }

	    if ( /^\s+number of sites ->\s+(\d+)/ ) {

		my $sites = $1;

		while ( defined($_ = $self->{handle}->getline()) ) {

		    chomp;

		    next unless m:^\s+server\s+(\S+)\s+partition\s+(/vicep\w+)\s+([A-Z]{2})\s+Site\s*(--\s+)?(.*)?:;

lib/AFS/Command/VOS.pm  view on Meta::CPAN


		}

	    }

	    #
	    # Last possibility (that we know of) -- volume might be
	    # locked.
	    #
	    if ( /LOCKED/ ) {
		$entry->_setAttribute( locked => 1 );
		$locked++;
	    }

	}

	$result->_addVLDBEntry( $entry );

    }

    $result->_setAttribute( locked => $locked );

    $errors++ unless $self->_reap_cmds();

    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

}

lib/AFS/Command/VOS.pm  view on Meta::CPAN


	    chomp;

	    last if /^\s*$/ && $args{fast};

	    next if /^\s*$/;

	    s/\s+$//;

	    if ( /^Total volumes onLine (\d+) ; Total volumes offLine (\d+) ; Total busy (\d+)/ ) {
		$partition->_setAttribute
		  (
		   online		=> $1,
		   offline		=> $2,
		   busy			=> $3,
		  );
		last;		# Done with this partition
	    }

	    if ( /Volume (\d+) is busy/ ) {
		my $volume = AFS::Object::VolumeHeader->new

lib/AFS/Command/VOS.pm  view on Meta::CPAN


	    my (@array) = split;
	    my ($name,$id,$type,$size,$status) = ();

	    my $volume = AFS::Object::VolumeHeader->new();

	    if ( @array == 6 ) {
		($name,$id,$type,$size,$status) = @array[0..3,5];
		$status = 'offline' if $status eq 'Off-line';
		$status = 'online' if $status eq 'On-line';
		$volume->_setAttribute
		  (
		   id			=> $id,
		   name			=> $name,
		   type			=> $type,
		   size			=> $size,
		   status		=> $status,
		   attached		=> 1,
		  );
	    } elsif ( @array == 1 ) {
		$volume->_setAttribute
		  (
		   id			=> $_,
		   status		=> 'online',
		   attached		=> 1,
		  );
	    } else {
		$self->_Carp("Unable to parse header summary line:\n" . $_);
		$errors++;
		next;
	    }

lib/AFS/Command/VOS.pm  view on Meta::CPAN

	    # for notes.  This code was stolen from there...
	    #

	    if ( $args{long} || $args{extended} ) {

		while ( defined($_ = $self->{handle}->getline()) ) {

		    last if /^\s*$/;

		    if ( /^\s+RWrite\s+(\d+)\s+ROnly\s+(\d+)\s+Backup\s+(\d+)/ ) {
			$volume->_setAttribute
			  (
			   rwrite		=> $1,
			   ronly		=> $2,
			   backup		=> $3,
			  );
			if ( /RClone\s+(\d+)/ ) {
			    $volume->_setAttribute( rclone => $1 );
			}
			next;
		    }

		    if ( /^\s+MaxQuota\s+(\d+)/ ) {
			$volume->_setAttribute( maxquota => $1 );
			next;
		    }

		    if ( /^\s+Creation\s+(.*)\s*$/ ) {
			$volume->_setAttribute( creation => $1 );
			next;
		    }

		if ( /^\s+Copy\s+(.*)\s*$/ ) {
		    $volume->_setAttribute( copyTime	=> $1 );
		    next;
		}

		if ( /^\s+Backup\s+(.*)\s*$/ ) {
		    $volume->_setAttribute( backupTime	=> $1 );
		    next;
		}

		if ( /^\s+Last Access\s+(.*)\s*$/ ) {
		    $volume->_setAttribute( access	=> $1 );
		    next;
		}

		    if ( /^\s+Last Update\s+(.*)\s*$/ ) {
			$volume->_setAttribute( update => $1 );
			next;
		    }

		    if ( /^\s+(\d+) accesses/ ) {
			$volume->_setAttribute( accesses => $1 );
			next;
		    }
		}		# while(defined($_ = $self->{handle}->getline())) {

	    }

	    $partition->_addVolumeHeader($volume);

	}

lib/AFS/Command/VOS.pm  view on Meta::CPAN


    $errors++ unless $self->_exec_cmds();

    my $transaction = undef;

    while ( defined($_ = $self->{handle}->getline()) ) {

	chomp;

	if ( /No active transactions/ ) {
	    $result->_setAttribute( transactions => 0 );
	    last;
	}

	if ( /Total transactions: (\d+)/ ) {
	    $result->_setAttribute( transactions => $1 );
	    next;
	}

	if ( /^-+\s*$/ ) {

	    if ( $transaction ) {
		$result->_addTransaction($transaction);
		$transaction = undef;
	    } else {
		$transaction = AFS::Object::Transaction->new();
	    }

	}

	next unless $transaction;

	if ( /transaction:\s+(\d+)/ ) {
	    $transaction->_setAttribute( transaction => $1 );
	}

	if ( /created:\s+(.*)$/ ) {
	    $transaction->_setAttribute( created => $1 );
	}

	if ( /attachFlags:\s+(.*)$/ ) {
	    $transaction->_setAttribute( attachFlags => $1 );
	}

	if ( /volume:\s+(\d+)/ ) {
	    $transaction->_setAttribute( volume => $1 );
	}

	if ( /partition:\s+(\S+)/ ) {
	    $transaction->_setAttribute( partition => $1 );
	}

	if ( /procedure:\s+(\S+)/ ) {
	    $transaction->_setAttribute( procedure => $1 );
	}

	if ( /packetRead:\s+(\d+)/ ) {
	    $transaction->_setAttribute( packetRead => $1 );
	}

	if ( /lastReceiveTime:\s+(\d+)/ ) {
	    $transaction->_setAttribute( lastReceiveTime => $1 );
	}

	if ( /packetSend:\s+(\d+)/ ) {
	    $transaction->_setAttribute( packetSend => $1 );
	}

	if ( /lastSendTime:\s+(\d+)/ ) {
	    $transaction->_setAttribute( lastSendTime => $1 );
	}

    }

    $errors++ unless $self->_reap_cmds();

    $errors++ unless $self->_restore_stderr();

    return if $errors;
    return $result;

lib/AFS/Command/VOS.pod  view on Meta::CPAN

       encrypt                  => 1,
       # Enhanced arguments
       gunzip			=> 1,
       bunzip2			=> 1,
       filterin			=> [ @command ], # OR [ [ @cmd1 ], [ @cmd2 ], ... ]
      );

NOTE: The 'creation' and 'lastupdate' options are available only in a
very recent patch to the vos command, which should be available in the
OpenAFS 1.2.11 or 1.2.12 releases.  These options control how the
Creation and LastUpdate timestamps are set on the restored volume.

The 3 values these options can take, and their meanings, are:

=over

=item dump

Use the timestamp from the volume dump file being restored to the
volume.  This is the default behavior for the LastUpdate timestamp.

lib/AFS/Command/VOS.pod  view on Meta::CPAN

    type			"RO" | "RW" | "BK"
    size			Numeric size in KB
    server			Fileserver hostname
    partition			Fileserver /vice partition
    maxquota			Volume quota in KB
    creation			Volume creation date (ctime format, eg: Sat Oct  6 04:39:50 2001)
    copyTime			Volume copy date   (also in ctime format)
    backupTime			Volume backup date (also in ctime format)
    access      Volume Last Access date (also in ctime format)
    update			Volume update date (also in ctime format)
    accesses			Number of volume accesses since the last reset
    rwrite			Numeric Volume ID for the RW volume
    ronly			Numeric Volume ID for the RO volume
    backup			Numeric Volume ID for the BK volume
    rclone			Numeric Volume ID for the RClone volume, if present

Note that the 'rclone' attribute is only present if the volume was
actively being cloned while being examined.  This is true when a 'vos
release' command is actively updating the RO volumes.

The following attributes are only present if the 'extended' argument

lib/AFS/Command/VOS.pod  view on Meta::CPAN

    Attributes			Values
    ----------			------
    server			Fileserver hostname
    partition			Fileserver /vice partition
    maxquota			Volume quota in KB
    creation			Volume creation date (ctime format, eg: Sat Oct  6 04:39:50 2001)
    copyTime			Volume copy date   (also in ctime format)
    backupTime			Volume backup date (also in ctime format)
    access			Volume Last Access date (also in ctime format)
    update			Volume update date (also in ctime format)
    accesses			Number of volume accesses since the last reset
    rwrite			Numeric Volume ID for the RW volume
    ronly			Numeric Volume ID for the RO volume
    backup			Numeric Volume ID for the BK volume
    rclone			Numeric Volume ID for the RClone volume, if present

=back

=head2 partinfo

=over

lib/AFS/Command/VOS.pod  view on Meta::CPAN

       oldname			=> $oldname,
       newname			=> $newname,
       # Optional arguments
       cell                     => $cell,
       noauth                   => 1,
       localauth                => 1,
       verbose                  => 1,
       encrypt                  => 1,
      );

=head2 setfields

The vos help string is:

    vos setfields: change volume info fields
    Usage: vos setfields -id <volume name or ID> [-maxquota <quota (KB)>]
			 [-clearuse] [-cell <cell name>] [-noauth]
			 [-localauth] [-verbose] [-encrypt]
    Where: -clearuse   clear dayUse

The corresponding method invocation looks like:

    my $result = $vos->setfields
      (
       # Required arguments
       id			=> $id,
       # Optional arguments
       maxquota			=> $maxquota,
       clearuse			=> 1,
       cell                     => $cell,
       noauth                   => 1,
       localauth                => 1,
       verbose                  => 1,

lib/AFS/Object.pm  view on Meta::CPAN


our $AUTOLOAD = "";
our $VERSION = '1.99';

our %Carp =
  (
   carp		=> \&Carp::carp,
   croak	=> \&Carp::croak,
  );

sub _setCarp {
    my $class = shift;
    my (%args) = @_;
    foreach my $key ( keys %args ) {
	$Carp{$key} = $args{$key};
    }
    return 1;
}

sub new {
    my $proto = shift;

lib/AFS/Object.pm  view on Meta::CPAN

sub _Carp {
    my $self = shift;
    $Carp{carp}->(@_);
}

sub _Croak {
    my $self = shift;
    $Carp{croak}->(@_);
}

sub _setAttribute {
    my $self = shift;
    my (%attrs) = @_;
    foreach my $attr ( keys %attrs ) {
	$self->{_attrs}->{$attr} = $attrs{$attr};
    }
    return 1;
}

sub DESTROY {}

lib/AFS/Object/Path.pm  view on Meta::CPAN

sub getACLNormal {
    my $self = shift;
    return $self->getACL();
}

sub getACLNegative {
    my $self = shift;
    return $self->getACL('negative');
}

sub _setACLNormal {

    my $self = shift;
    my $acl = shift;

    unless ( ref $acl && $acl->isa("AFS::Object::ACL") ) {
	$self->_Croak("Invalid argument: must be an AFS::Object::ACL object");
    }

    return $self->{_acl}->{_normal} = $acl;

}

sub _setACLNegative {

    my $self = shift;
    my $acl = shift;

    unless ( ref $acl && $acl->isa("AFS::Object::ACL") ) {
	$self->_Croak("Invalid argument: must be an AFS::Object::ACL object");
    }

    return $self->{_acl}->{_negative} = $acl;

t/00vos_basic.t  view on Meta::CPAN

	} else {
	    warn("Volume header 'size' is '" .
		 $header->size() . "', should be 2\n");
	    print "not ok $TestCounter\n";
	    $errors++;
	}
	$TestCounter++;

	#
	# Both the update and creation times should be ctime values.
	# NOTE: This test may very well break if LANG is set, and
	# affects vos output syntax.  Note that in that case, we'll
	# need code in VOS.pm to deal with more generic time strings.
 	#
	foreach my $method ( qw( update creation ) ) {
	    if ( $header->$method() =~ /^\S+\s+\S+\s+\d+\s+\d{2}:\d{2}:\d{2}\s+\d{4}$/ ) {
		print "ok $TestCounter\n";
	    } else {
		warn("Volume header '$method' is '" .
		    $header->$method() . "', should be a ctime date value\n");
		print "not ok $TestCounter\n";

t/40fs_complex.t  view on Meta::CPAN

	    print "$ok $TestCounter\n";
	    $TestCounter++;
	}

    }

}

#
# Sadly, if the localhost is not in the same AFS cell as that being
# tested, the setacl command is guaranteed to fail, because the test
# pts entries will not be defined.
#
# Thus, we use a different, existing pts entry for these tests, and
# not the ones we created above.
#
my %entries =
  (
   $ptsexisting			=> 'rlidwk',
  );

foreach my $type ( qw(normal negative) ) {

    $result = $fs->setacl
      (
       dir			=> $mtpath,
       acl			=> \%entries,
       (
	$type eq 'negative' ?
	( negative		=> 1 ) : ()
       ),
      );
    if ( $result ) {
	print "ok $TestCounter\n";
	$TestCounter++;
    } else {
	print "not ok $TestCounter..$TestTotal\n";
	die("Unable to setacl dirs:" .
	    $fs->errors() .
	    Data::Dumper->Dump([$fs],['fs']));
    }

    $result = $fs->listacl
      (
       path			=> $mtpath,
      );
    if ( ref $result && $result->isa("AFS::Object::CacheManager") ) {
	print "ok $TestCounter\n";



( run in 1.095 second using v1.01-cache-2.11-cpan-49f99fa48dc )