Index: trunk/Nebulous-Server/bin/neb-host
===================================================================
--- trunk/Nebulous-Server/bin/neb-host	(revision 42863)
+++ trunk/Nebulous-Server/bin/neb-host	(revision 42868)
@@ -16,7 +16,5 @@
 use Pod::Usage qw( pod2usage );
 
-my ($host, $state, $note,
-    $db, $dbhost, $dbpass, $dbuser,
-    $allocate, $available, $debug,$volume);
+my ($host, $state, $xattr, $note, $db, $dbhost, $dbpass, $dbuser, $debug, $volume);
 
 # $db     = $ENV{'NEB_DB'} unless $db;
@@ -25,28 +23,19 @@
 # $dbpass = $ENV{'NEB_PASS'} unless $dbpass;
 
-# my $conffile = "/data/ippc64.1/ippitc/ippconfig/nebulous.config";
 # my $conffile = "/home/panstarrs/ipp/ippconfig/nebulous.config";
 my $conffile = "/home/panstarrs/ippps1/ippconfig/nebulous.config";
 
 if (-e $conffile) {
-#    printf STDERR "found config\n";
+    # printf STDERR "found config\n";
     open(IN,$conffile);
     while(<IN>) {
 	chomp;
-	if ($_ =~ /NEB_DB\s+/) {
-	    $db = (split /\s+/,$_)[2];
-	}
-	elsif ($_ =~ /NEB_DBHOST/) {
-	    $dbhost = (split /\s+/,$_)[2];
-	}
-	elsif ($_ =~ /NEB_USER/) {
-	    $dbuser = (split /\s+/,$_)[2];
-	}
-	elsif ($_ =~ /NEB_PASS/) {
-	    $dbpass = (split /\s+/,$_)[2];
-	}
+	if ($_ =~ /NEB_DB\s+/)  { $db     = (split /\s+/,$_)[2]; next; }
+	if ($_ =~ /NEB_DBHOST/) { $dbhost = (split /\s+/,$_)[2]; next; }
+	if ($_ =~ /NEB_USER/)   { $dbuser = (split /\s+/,$_)[2]; next; }
+	if ($_ =~ /NEB_PASS/)   { $dbpass = (split /\s+/,$_)[2]; next; }
     }
     close(IN);
-#    print STDERR  "$db $dbhost $dbuser $dbpass\n";
+    # print STDERR  "$db $dbhost $dbuser $dbpass\n";
 }
 
@@ -54,4 +43,5 @@
     'host=s'         => \$host,
     'state=s'        => \$state,
+    'xattr=s'        => \$xattr,
     'note=s'         => \$note,
     'db=s'           => \$db,
@@ -60,8 +50,14 @@
     'dbpass=s'       => \$dbpass,
     'volume'         => \$volume,
-    
     ) || pod2usage( 2 );
 
-if (($#ARGV == 1)&&(!defined($host))&&(!defined($state))) {
+# if --host and --state are not supplied, look for positional arguments
+my $Narg = @ARGV;
+
+if (($Narg == 1) && (!defined($host)) && (!defined($state))) {
+    # neb-host (host) : return volume into for specified host
+    $host = shift(@ARGV);
+}
+if (($Narg == 2) && (!defined($host)) && (!defined($state))) {
     $host = shift(@ARGV);
     $state = shift(@ARGV);
@@ -83,60 +79,80 @@
     );
 
-if ((defined($host))&&(defined($state))) {
-    if ($state eq 'up') {
-	$allocate = 1;
-	$available = 1;
-    }
-    elsif ($state eq 'down') {
-	$allocate = 0;
-	$available = 0;
-    }
-    elsif ($state eq 'repair') {
-	$allocate = 0;
-	$available = 1;
-    }
-    else {
-	die "Unknown state '$state'";
-    }
+if (defined($host) && defined($state)) {
+
+    # strip dangerous characters
+    if (defined($note)) { $note =~ s/'/ /g; $note =~ s/;/ /g; $note =~ s/"/ /g; }
+    if (defined($host)) { $host =~ s/'/ /g; $host =~ s/;/ /g; $host =~ s/"/ /g; }
+
+    if (($state ne 'up') && ($state ne 'down') && ($state ne 'repair')) { die "Unknown state '$state'"; }
     
-    my %constraint;
+    # for 'up', we want to exclude set volumes with xattr = 3, and possible issue an equivalent of 'repair' for xattr = 3
+    # for 'up' and 'repair', we should exclude volumes with xattr = 5
+    # for 'down', all volumes are ok
+    
+    # up:
+    # UPDATE volume SET (allocate = 1, available = 1, note = '$note') WHERE (name = '$host') AND (xattr != 3) AND (xattr != 5)
+    # UPDATE volume SET (allocate = 0, available = 1, note = '$note') WHERE (name = '$host') AND (xattr = 3)
+
+    # repair:
+    # UPDATE volume SET (allocate = 0, available = 1, note = '$note') WHERE (name = '$host') AND (xattr != 5)
+
+    # down:
+    # UPDATE volume SET (allocate = 0, available = 0, note = '$note') WHERE (name = '$host')
+
+    # $volume is a boolean which means 'use' the supplied host as the 'name' field
+    my $hostWhere;
     if (defined($volume)) {
-	$constraint{'v.name'} = $host;
-    }
-    else {
-	$constraint{'v.host'} = $host;
-    }
-    my %set;
-    $set{'v.allocate'} = $allocate if defined $allocate;
-    $set{'v.available'} = $available if defined $available;
-    $set{'v.note'} = $note if defined $note;
-
-    eval {
-	my ($q, @bind) = sql_interp("UPDATE volume AS v SET", \%set, "WHERE", \%constraint);
-	warn "$q\n" if $debug;
-	my $query = $dbh->prepare($q);
-	$query->execute(@bind);
-	$dbh->commit;
-    };
-    if ($@) {
-	$dbh->rollback;
-	die $@;
-    }
-    eval {
-	my ($q, @bind) = sql_interp("UPDATE mountedvol AS v SET", \%set, "WHERE", \%constraint);
-	warn "$q\n" if $debug;
-	my $query = $dbh->prepare($q);
-	$query->execute(@bind);
-	$dbh->commit;
-    };
-    if ($@) {
-	$dbh->rollback;
-	die $@;
-    }
+	$hostWhere = "(name = '$host')";
+    } else {
+	$hostWhere = "(host = '$host')";
+    }
+
+    my ($selections, $constraint);
+
+    if ($state eq 'up')     { 
+	$selections = "allocate = 1, available = 1";
+	$constraint = "$hostWhere AND (xattr != 3) AND (xattr != 5)";
+    }
+
+    if ($state eq 'repair')     { 
+	$selections = "allocate = 0, available = 1";
+	$constraint = "$hostWhere AND (xattr != 5)";
+    }
+
+    if ($state eq 'down')     { 
+	$selections = "allocate = 0, available = 0";
+	$constraint = "$hostWhere";
+    }
+
+    &modify_hosts ($selections, $constraint, $note);
+
+    ## for 'up', make a second call to set hosts with (xattr = 3) to 'repair':
+    if ($state eq 'up')     { 
+	$selections = "allocate = 0, available = 1";
+	$constraint = "$hostWhere AND (xattr = 3)";
+
+	&modify_hosts ($selections, $constraint, $note);
+    }
+    exit 0;
 }
 
 my $sql = Nebulous::Server::SQL->new();
 my ($q, @bind);
-$q = $sql->get_volumes . " ORDER BY v.host, v.name";
+
+if (defined($host)) {
+    if (defined($xattr)) {
+	$q = $sql->get_volumes . " WHERE v.host = '$host' AND v.xattr = $xattr ORDER BY v.host, v.name";
+    } else {
+	$q = $sql->get_volumes . " WHERE v.host = '$host' ORDER BY v.host, v.name";
+    }
+} else {
+    if (defined($xattr)) {
+	$q = $sql->get_volumes . " WHERE v.xattr = $xattr ORDER BY v.host, v.name";
+    } else {
+	$q = $sql->get_volumes . " ORDER BY v.host, v.name";
+    }
+}
+
 warn "$q\n" if $debug;
 my $query = $dbh->prepare($q);
@@ -152,9 +168,38 @@
 	$$row{ 'note' } = '-';
     }
-
     printf($format, @$row{@columns});
 }
 
+sub modify_hosts {
+
+    my $selections = $_[0];
+    my $constraint = $_[1];
+
+    my $note = $_[2];
+    # print "NOTE: $note\n";
+
+    if (defined $note) { $selections = $selections . ", note = '$note'"; }
+
+    {
+	my $sqlLine = "UPDATE volume SET $selections WHERE $constraint";
+	# print "SQL: $sqlLine\n";
+	my $query = $dbh->prepare($sqlLine);
+	$query->execute() or die "error from Nebulous database\n";
+	$dbh->commit;
+    }
+    
+    { 
+	my $sqlLine = "UPDATE mountedvol SET $selections WHERE $constraint";
+	# print "SQL: $sqlLine\n";
+	my $query = $dbh->prepare($sqlLine);
+	$query->execute() or die "error from Nebulous database\n";
+	$dbh->commit;
+    }
+}
+
+
 __END__
+
+
 
 =pod
@@ -169,4 +214,5 @@
     [--note '<status note>']
     [--host <nebulous host>] [--state <up|down|repair>]
+    [--xattr N]
     [--volume]
     [--dbhost <database host>] [--db <database name>]
@@ -180,4 +226,6 @@
 given, the host and state are read directly from the command line.  If nothing
 is specified, prints out the table of currently mounted volumes in nebulous.
+If the state is not specified, but a host is supplied, the table of values is restricted 
+to the specified host.
 
 =head1 OPTIONS
@@ -200,4 +248,8 @@
     repair Allocate = 0, Available = 1
 
+=item * --xattr <N>
+
+Limit the listed volumes to the specified xattr value
+
 =item * --volume
 
