AFS-Command

 view release on metacpan or  search on metacpan

CONFIG  view on Meta::CPAN

#
AFS_COMMAND_VOLNAME_PREFIX	= afscmd.

#
# Two fileserver:/partition names in which to create volumes.  These
# must be in the same AFS cell as specified at the top of this file.
#
AFS_COMMAND_PARTITION_LIST	= server1:/vicepa server2:/vicepb

#
# The bos tests need the name of a database server to work with.
#
AFS_COMMAND_DBSERVER		= dbserver1

#
# We need a valid pathname (directory) in AFS that we can abuse (that
# is, we will be hacking the ACL on this directory, and a few other
# intrusive things, to test the FS API).  This directory must be in a
# RW volume, and system:administratoirs must have write access to it.
#
AFS_COMMAND_PATHNAME_AFS	= /afs/your.cell.name/home/you/hackmebaby

Changes  view on Meta::CPAN

=head1 Bugs

=head1 Changes in 1.5

=head1 Enhancements

=head2 Principal names, as user supplied arguments, are lowercased

As a convenience, when PTS names are passed to methods like
getUserByName(), they will be lower-cased before looking up the user,
or group.  Since PTS is a case-insensitive database, this will avoid
the need for applications to lc() some strings, although not in all
cases.

For example, you can pass a mixed case string to pts->creategroup(),
and then use the same string to query the resulting AFS::Object::Group
object using getGroupByName().

The object's "group" attribute, however, will be in lower case, since
that will be the value returned by the pts command itself.

Changes  view on Meta::CPAN


=head1 Enhancements

=head2 AFS::Command::VOS->status()

This method now parses the individual transaction stanzas, and the API
provides access to objects that encapsulate each of them.  So, instead
of just finding out how many transactions are active, you can analyze
each of them in detail.

=head2 AFS::Object::VLDB data is now keyed on volume ID, as well as name

This changes the way the AFS::Object::VLDB data can be extracted.  In
1.0, the API allowed AFS::Object::VLDBEntry object to be queried only
by name, but 3 new methods calls allow this data to be queried by
numeric ID as well as name:

    getVLDBEntryById($id)
    getVLDBEntryByName($name)
    getVolumeIds()

The API for getVLDBEntry has changed, and the single argument usage:

    getVLDBEntry($name)		# DEPRECATED!!!!

has been deprecated.  If warnings are enabled (perl -w), then the API
will carp at you.  In the next release (1.2), that usage will no
longer be supported.  Upgrade your code, or pay the price.

The new usage of getVLDBEntry is one of:

    getVLDBEntry( name => $name )
    getVLDBEntry( id => $id )

The internal method _addEntry() now manages the data by id as well as
name, but you're not supposed to know that anyway...

=head1 Bugs

=head2 AFS::Command::BOS->status

When querying a specific instance, if it wasn't there, the API would
try to add an undefined instance object to the result, and croak.
Now, you just get a result object with no instances.

Changes.html  view on Meta::CPAN


		<LI><A HREF="#AFS_Command_VOS_offline_and">AFS::Command::VOS->offline() and ->online()</A>
	</UL>

	<LI><A HREF="#Bugs">Bugs</A>
	<LI><A HREF="#Changes_in_1_1">Changes in 1.1</A>
	<LI><A HREF="#Enhancements">Enhancements</A>
	<UL>

		<LI><A HREF="#AFS_Command_VOS_status_">AFS::Command::VOS->status()</A>
		<LI><A HREF="#AFS_Object_VLDB_data_is_now_ke">AFS::Object::VLDB data is now keyed on volume ID, as well as name</A>
	</UL>

	<LI><A HREF="#Bugs">Bugs</A>
	<UL>

		<LI><A HREF="#AFS_Command_BOS_status">AFS::Command::BOS->status</A>
		<LI><A HREF="#AFS_Command_FS_several_metho">AFS::Command::FS->(several methods)</A>
		<LI><A HREF="#AFS_Command_FS_lsmount">AFS::Command::FS->lsmount</A>
		<LI><A HREF="#AFS_Command_FS_sysname">AFS::Command::FS->sysname</A>
	</UL>

Changes.html  view on Meta::CPAN

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

</A></H1>
<P>
<HR>
<H2><A NAME="Principal_names_as_user_supplie">Principal names, as user supplied arguments, are lowercased

</A></H2>
As a convenience, when PTS names are passed to methods like
<CODE>getUserByName(),</CODE> they will be lower-cased before looking up
the user, or group. Since PTS is a case-insensitive database, this will
avoid the need for applications to <CODE>lc()</CODE> some strings, although
not in all cases.


<P>

For example, you can pass a mixed case string to pts-&gt;creategroup(), and
then use the same string to query the resulting AFS::Object::Group object
using <CODE>getGroupByName().</CODE>

Changes.html  view on Meta::CPAN

This method now parses the individual transaction stanzas, and the API
provides access to objects that encapsulate each of them. So, instead of
just finding out how many transactions are active, you can analyze each of
them in detail.


<P>

<P>
<HR>
<H2><A NAME="AFS_Object_VLDB_data_is_now_ke">AFS::Object::VLDB data is now keyed on volume ID, as well as name

</A></H2>
This changes the way the AFS::Object::VLDB data can be extracted. In 1.0,
the API allowed AFS::Object::VLDBEntry object to be queried only by name,
but 3 new methods calls allow this data to be queried by numeric ID as well
as name:


<P>

<PRE>    getVLDBEntryById($id)
    getVLDBEntryByName($name)
    getVolumeIds()
</PRE>

Changes.html  view on Meta::CPAN



<P>

<PRE>    getVLDBEntry( name =&gt; $name )
    getVLDBEntry( id =&gt; $id )
</PRE>

<P>

The internal method <CODE>_addEntry()</CODE> now manages the data by id as
well as name, but you're not supposed to know that anyway...


<P>

<P>
<HR>
<H1><A NAME="Bugs">Bugs

</A></H1>

MANIFEST  view on Meta::CPAN

lib/AFS/Object/User.pm
lib/AFS/Object/VLDB.pm
lib/AFS/Object/VLDBEntry.pm
lib/AFS/Object/VLDBSite.pm
lib/AFS/Object/VolServer.pm
lib/AFS/Object/Volume.pm
lib/AFS/Object/VolumeHeader.pm
LICENSE
Makefile.PL
MANIFEST			This list of files
META.yml			Module meta-data (added by MakeMaker)
README
README.html
t/00vos_basic.t
t/01vos_dumprestore.t
t/02vos_volserver.t
t/10bos_basic.t
t/20fs_basic.t
t/30pts_basic.t
t/40fs_complex.t
t/99pts_cleanup.t

README  view on Meta::CPAN


This module builds like almost everything else on CPAN:

  perl Makefile.PL
  make
  make test
  make install

Before running 'make test', edit the CONFIG file and follow the
instructions in the comments.  Minimally, you have to specify a couple
of AFS file servers and one AFS database server against which to run
the tests, as well as a pathname in AFS where we can create mount
points.

The test suite will require AFS super-user privileges, so you must
either be a member of the system:administrators protection group, or a
member of the super users list on the servers.  If you don't know what
that means, you shouldn't be testing this module, so consult your AFS
administrators.

See the CONFIG file for more details.  Its pretty verbosely

README.html  view on Meta::CPAN

<PRE>  perl Makefile.PL
  make
  make test
  make install
</PRE>

<P>

Before running 'make test', edit the CONFIG file and follow the
instructions in the comments. Minimally, you have to specify a couple of
AFS file servers and one AFS database server against which to run the
tests, as well as a pathname in AFS where we can create mount points.


<P>

The test suite will require AFS super-user privileges, so you must either
be a member of the system:administrators protection group, or a member of
the super users list on the servers. If you don't know what that means, you
shouldn't be testing this module, so consult your AFS administrators.

ToDo  view on Meta::CPAN

The problem is that each API method calls _save_stderr(), and then
later calls _restore_stderr(), and we leave stderr redirected for
longer than necessary.  The contents of the redirected output should
be *only* the output from the commands we run, and right now, some of
our own carping can creep in there.

Worse, its possible that a failure in the API can leave stderr
redirected, resulting in a lot of confusion.

Its possible we should just suck in *ALL* of the output, both
stdout/stderr, and drop that data into a couple of arrays.  Then,
method calls on the command object get gets individual rows of
stdout/stderr output.

  return unless $self->_exec_cmds();

  #
  # Process stdout
  #
  while ( defined($_ = $self->_stdout() ) ) {

  }

  #
  # Process stderr (in some cases, there's interesting data in here.
  # see the fs examine/diskfree and similar api calls)
  #
  while ( defined($_ = $self->_stderr() ) ) {

  }

Maybe something like that.  By the time _exec_cmds returns, we have
reaped the commands, and collected *ALL* of the output into arrays in
the object.

ToDo.html  view on Meta::CPAN


<P>

Worse, its possible that a failure in the API can leave stderr redirected,
resulting in a lot of confusion.


<P>

Its possible we should just suck in *ALL* of the output, both
stdout/stderr, and drop that data into a couple of arrays. Then, method
calls on the command object get gets individual rows of stdout/stderr
output.


<P>

<PRE>  return unless $self-&gt;_exec_cmds();
</PRE>

<P>

ToDo.html  view on Meta::CPAN

</PRE>

<P>

<PRE>  }
</PRE>

<P>

<PRE>  #
  # Process stderr (in some cases, there's interesting data in here.
  # see the fs examine/diskfree and similar api calls)
  #
  while ( defined($_ = $self-&gt;_stderr() ) ) {
</PRE>

<P>

<PRE>  }
</PRE>

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


WARNING: This is an early design phase (1.x) of this API, and it is in
its infancy, so expect it to change in future releases, and expect to
change your code to accomodate it.

The entire API is designed to be pure OO, with the following classes:

=head2 AFS::Command::(VOS|BOS|PTS|FS)

These are the primary classes used by applications directly.  All of
the other objects are used internally to encapsulate the data parsed
from the underlying commands, and returned by the primary methods.

Each of these classes has a shared constructor (new), and methods that
correspond to each of the underlying commands.  For example, the "vos"
utility has a command called "listvldb", and the AFS::Command::VOS
objects have a "listvldb" method.  Each of the methods such as
"listvldb" take a list of key/value pairs that correspond to the
command line options for the "vos listvldb" command.

These classes implement the externally supported interface to the

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


=head2 AFS::Command::Base

This is the base class for the command suite, which implements the
shared constructor, and a couple of other useful class and object
methods.

=head2 AFS::Object

This is the base class for the objects returned from the command
methods that encapsulate some form of structured data.  Many of the
methods return simple boolean true/false values (either the command
worked, or it failed), with no need for any special objects, so we
don't create them.  Anything that has to return interesting data uses
this class, or one of its base classes.

The subclasses are associated with data structures such as volume
headers, a VLDB entry, or a partition on a server.  Each of these
classes has methods to retrieve the objects they "contain", such as a
method to query the list of volume names on a partition object, and a
method to get a list of VLDB entries from a VLDB site.

The data structures, and their varying relationships, are documented
in details of the methods for each of the commands, and the specific
interfaces for each object type are documented in the corresponding
class documentation.

The subclasses for encapsulating the VLDB data are:

    AFS::Object::VLDB
    AFS::Object::VLDBEntry
    AFS::Object::VLDBSite

The subclasses for encapsulating the volume headers are:

    AFS::Object::FileServer
    AFS::Object::VolServer
    AFS::Object::Partition
    AFS::Object::Volume
    AFS::Object::VolumeHeader

The subclasses for encapsulating the bosserver data are:

    AFS::Object::BosServer
    AFS::Object::Instance

Note that none of these classes are specifically documented, since the
structure of the classes is subject to change.  The API for accessin
the results of any given AFS command (eg. vos listvol) is considered
reasonably stable, but the encapsulation may change radically.

Don't get too attached to these class names, because they will likely

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

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).

This holds true for the following API methods: diskfree, examine,
listquota, quota, storebehind, whereis, whichcell, and listacl.

=head2 checkservers

=over

=item Arguments

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

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

=head2 flushvolume

The fs help string is:

    fs flushvolume: flush all data in volume
    Usage: fs flushvolume [-path <dir/file path>+]

The corresponding method invocation looks like:

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

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


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

	chomp;

	while ( /,\s*$/ ) {
	    $_ .= $self->{handle}->getline();
	    chomp;
	}

	my %data = ();

	foreach my $field ( split(/,\s*/) ) {

	    my ($key,$value) = split(/:\s+/,$field,2);

	    $key =~ tr/A-Z/a-z/;
	    $key =~ s/\s+//g;	# group quota -> groupquota
	    $value =~ s/\.$//;

	    $data{$key} = $value;

	}

	unless ( $data{id} ) {
	    $self->_Carp("pts examine: Unrecognized output: '$_'");
	    $errors++;
	    next;
	}

	if ( $data{id} > 0 ) {
	    $result->_addUser( AFS::Object::User->new(%data) );
	} else {
	    $result->_addGroup( AFS::Object::Group->new(%data) );
	}

    }

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

    return if $errors;
    return $result;

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


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

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

	next if /^Name/;

	my ($name,$id,$owner,$creator) = split;

	#
	# We seem to be getting this one bogus line of data, with no
	# name, and 0's for the IDs.  Probably a bug in pts...
	#
	next if ( ! $name && ! $id && ! $owner && ! $creator );

	if ( $id > 0 ) {
	    my $user = AFS::Object::User->new
	      (
	       name 			=> $name,
	       id			=> $id,
	       owner			=> $owner,

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

		$user->_addOwned($1);
	    } else {
		$group->_addOwned($2);
	    }

	} elsif ( /unable to get owner list/ ) {

	    #
	    # pts still (as of OpenAFS 1.2.8) doesn't have proper exit codes.
	    # If we see this string, then let the command fail, even
	    # though we might have partial data.
	    #
	    $self->{errors} .= $_;
	    $errors++;

	}

    }

    $result->_addUser($user) if $user;
    $result->_addGroup($group) if $group;

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

		$group->_addMembership($1);
	    }

	} elsif ( /unable to get membership/ ||
		  /User or group doesn't exist/ ||
		  /membership list for id \d+ exceeds display limit/ ) {

	    #
	    # pts still (as of OpenAFS 1.2.8) doesn't have proper exit codes.
	    # If we see this string, then let the command fail, even
	    # though we might have partial data.
	    #
	    $self->{errors} .= $_;
	    $errors++;

	}

    }

    $result->_addUser($user) if $user;
    $result->_addGroup($group) if $group;

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

=back

=head2 listentries

=over

=item Arguments

The pts help string is:

    pts listentries: list users/groups in the protection database
    Usage: pts listentries [-users] [-groups] [-cell <cell name>]
			   [-noauth] [-force]
    Where: -users   list user entries
	   -groups  list group entries

The corresponding method invocation looks like:

    my $result = $pts->listentries
      (
       # Optional arguments

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

       # Optional arguments
       cell			=> $cell,
       noauth			=> 1,
       force			=> 1,
      );

=head2 delete

The pts help string is:

    pts delete: delete a user or group from database
    Usage: pts delete -nameorid <user or group name or id>+
		      [-cell <cell name>] [-noauth] [-force]

The corresponding method invocation looks like:

    my $result = $pts->delete
      (
       # Required arguments
       nameorid			=> $nameorid, # OR [ $nameorid1, $nameorid2, ... ]
       # Optional arguments

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

	#
	# These two lines are part of the verbose output
	#
	next if /Fetching VLDB entry/;
	next if /Getting volume listing/;

	#
	# This code parses the volume header information.  If we match
	# 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,

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


	    } else {

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

	    }

	    #
	    # We are interested in the next 6 lines as they are also
	    # 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
		      (

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


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

	    }

	    #
	    # Are we looking for extended data??
	    #
	    if ( $args{extended} ) {

		my $raw = AFS::Object->new();
		my $author = AFS::Object->new();

		my $boundary = 0;

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

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

	    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
	# locations, we fall through to the next test once we are done
	# parsing them.
	#
	if ( /^\s+number of sites ->\s+(\d+)/ ) {

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

		chomp;

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

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

       verbose			=> 1,
       encrypt			=> 1,
      );

=item Return Values

This method returns an AFS::Object::FileServer object, which
contains one or more AFS::Object::Partition objects.  Because
'listpart' returns nothing other than the partition names, the
underlying Partition objects have only one attribute ('partition'), so
the API for access this data is trivial:

    my $result = $vos->listpart
      (
       server			=> 'fs1.ms.com',
      ) || die $vos->errors();

    foreach my $partition ( $result->getPartitionNames() ) {
	print "Server '$server' has partition '$partition'\n";
    }

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

B<AFS::Object::Partition>

This object has one boring attribute:

    Attributes			Values
    ----------			------
    partition			Fileserver /vice partition name

When used to encapsulate 'vos listpart' output, this object has no
relevant methods.  Note, however, that this version of the API reuses
this object to represent other partition-related data (see 'vos
listvol' method documentation, for example), but they are not relevant
in this usage of the object.  This multiple personality of the objects
may be changed in a future release, so don't get too attached to the
specific class names.

See the AFS::Object documentation for a discussion of the
planned evolution of the API.

=back

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

	    print "Volume $name has attribute $attr => " . $entry->$attr() . "\n";
	}
	foreach my $site ( $entry->getVLDBSites() ) {
	    my %attrs = $site->getAttributes();
	    while ( my($attr,$value) = each %attrs ) {
		print "Site has attribute $attr => $value\n";
	    }
	}
    }

Another way to slice and dice this data:

    foreach my $name ( $result->getVolumeNames() ) {
	my $entry = $result->getVLDBEntry( name => $name );
	....
    }

Each of these objects has the following attributes and methods:

B<AFS::Object::VLDB>

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

       cell                     => $cell,
       noauth                   => 1,
       localauth                => 1,
       verbose                  => 1,
       encrypt                  => 1,
      );

NOTE: 'extended' is not supported in this version of the API, and
specifying it will result in a warning, but not an error.  However,
'vos examine' does parse the extended output, so if you really want
that data you can get it on a volume by volume basis.  Adding support
for 'extended' to 'vos listvol' is on the todo list.

=item Return Values

This method returns an AFS::Object::VolServer object, which
merely contains one or more AFS::Object::Partition objects,
which in turn have a few attributes and contain one or more
AFS::Object::VolumeHeader objects.

    my $result = $vos->listvol

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

AFS::Object - Base class for encapsulating AFS::Command results

=head1 SYNOPSIS

This module is not used directly by applications, only indirectly
through the return values of the various AFS::Command::* methods.

=head1 DESCRIPTION

This class is used by the various AFS::Command classes to encapsulate
data returned from any command that has structured return values.  In
the simplest case, this object just encapsulates a simple list of
key/value pairs.  Each distinct key is represented as an object
attribute, and is query-able via one of several methods documented
below.

There are numerous subclasses of this class, which are used when
objects must contains other objects, and these subclasses just
implement special methods for querying the embedded objects.

=head1 METHODS

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

END {print "not ok 1\n" unless $Loaded;}
use AFS::Command::VOS 1.99;
$Loaded = 1;
$TestCounter = 1;
print "ok $TestCounter\n";
$TestCounter++;

exit 0 unless $TestTotal;

#
# First, let's get all the config data we need.
#
my $volname_prefix = $AFS::Command::Tests::Config{AFS_COMMAND_VOLNAME_PREFIX} || do {
    print "not ok $TestCounter..$TestTotal\n";
    die "Missing configuration variable AFS_COMMAND_VOLNAME_PREFIX\n";
};

my $cell = $AFS::Command::Tests::Config{AFS_COMMAND_CELLNAME} || do {
    print "not ok $TestCounter..$TestTotal\n";
    die "Missing configuration variable AFS_COMMAND_CELLNAME\n";
};

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


    #
    # Second, we check the VLDB entry for this volume.
    #
    my $vldbentry = $result->getVLDBEntry();

    if ( ref $vldbentry && $vldbentry->isa("AFS::Object::VLDBEntry") ) {
	print "ok $TestCounter\n";
    } else {
	print "not ok $TestCounter..$TestTotal\n";
	die("Invalid object type: getVLDBEntry() method call returned bogus data\n" .
	    Data::Dumper->Dump([$result],['result']));
    }
    $TestCounter++;

    if ( $vldbentry->rwrite() =~ /^\d+$/ ) {
	print "ok $TestCounter\n";
    } else {
	warn("VLDB Entry 'rwrite' is '" .
	     $vldbentry->rwrite() . "', should be a numeric value\n");
	print "not ok $TestCounter\n";

t/01vos_dumprestore.t  view on Meta::CPAN

END {print "not ok 1\n" unless $Loaded;}
use AFS::Command::VOS 1.99;
$Loaded = 1;
$TestCounter = 1;
print "ok $TestCounter\n";
$TestCounter++;

exit 0 unless $TestTotal;

#
# First, let's get all the config data we need.
#
my $volname_prefix = $AFS::Command::Tests::Config{AFS_COMMAND_VOLNAME_PREFIX} || do {
    print "not ok $TestCounter..$TestTotal\n";
    die "Missing configuration variable AFS_COMMAND_VOLNAME_PREFIX\n";
};

my $cell = $AFS::Command::Tests::Config{AFS_COMMAND_CELLNAME} || do {
    print "not ok $TestCounter..$TestTotal\n";
    die "Missing configuration variable AFS_COMMAND_CELLNAME\n";
};

t/02vos_volserver.t  view on Meta::CPAN

END {print "not ok 1\n" unless $Loaded;}
use AFS::Command::VOS 1.99;
$Loaded = 1;
$TestCounter = 1;
print "ok $TestCounter\n";
$TestCounter++;

exit 0 unless $TestTotal;

#
# First, let's get all the config data we need.
#
my $volname_prefix = $AFS::Command::Tests::Config{AFS_COMMAND_VOLNAME_PREFIX} || do {
    print "not ok $TestCounter..$TestTotal\n";
    die "Missing configuration variable AFS_COMMAND_VOLNAME_PREFIX\n";
};

my $cell = $AFS::Command::Tests::Config{AFS_COMMAND_CELLNAME} || do {
    print "not ok $TestCounter..$TestTotal\n";
    die "Missing configuration variable AFS_COMMAND_CELLNAME\n";
};

t/02vos_volserver.t  view on Meta::CPAN

    }

    my $attribute_test = 1;

    foreach my $partname ( @partitions ) {

	my $partition = $dst->getPartition($partname);

	unless ( ref $partition && $partition->isa("AFS::Object::Partition") ) {
	    print "not ok $TestCounter..$TestTotal\n";
	    die("Inconsistent data in listpart and partinfo output\n" .
		"Found partname '$partname' in one, but not the other");
	}

	if ( $partition->hasAttribute('available') ) {

	    my $available 	= $partition->available();
	    my $total		= $partition->total();

	    unless ( $available =~ /^\d+$/ && $total =~ /^\d+$/ && $available < $total ) {
		$attribute_test = 0;



( run in 0.612 second using v1.01-cache-2.11-cpan-a5abf4f5562 )