#!/usr/bin/perl
# External STONITH module for VMWare Server Guests
#
# Copyright (c) 2004 SUSE LINUX AG - Andrew Beekhof <abeekhof@suse.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like.  Any license provided herein, whether implied or
# otherwise, applies only to this software file.  Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#

sub supply_default
{
    my $name = $_[0];
    my $value = $_[1];

    if ( defined $ENV{$name} ) {
	#print "Set: $name=$ENV{$name}\n";
    } else {
	$ENV{$name} = $value;
	#print "Default: $name=$ENV{$name}\n";
    }
}

sub vmware_command
{
    my $config = $_[0];
    my $action = $_[1];
    my @lines;

    my $device = $ENV{'device_host'}; 

    if ( $device =~ /localhost/ ) {
	@lines = readpipe "vmware-cmd $config $action";

    } else {
	@lines = readpipe "ssh $device \"vmware-cmd \\\"$config\\\" $action\"";
    }

    #print @lines;
    return @lines;
}

sub is_host_active
{
    my $config = config_for_host($_[0]);
    my @lines = vmware_command($config, "getstate");
    foreach $line (@lines) {
	if ( $line =~ /getstate.* = on/ ) {
	    return 1;
	}
    }
    return 0;
}

sub supported_hosts
{
    my $line;
    my @lines;

    if ( defined $ENV{'host_map'} ) { 
	@lines = split(/;/, $ENV{'host_map'});
	foreach $line (@lines){
	    @config = split(/=/, $line);
	    $host = $config[0];
	    if ( is_host_active($host) == 1 ) {
		print "$host\n";
	    }
	}
	
    } else {
	@lines = vmware_command("-l");
	foreach $line (@lines){
	    my @elements = split(/\//, $line);
	    $host = $elements[$#elements-1];
	    if ( is_host_active($host) == 1 ) {
		print "$host\n";
	    }
	}
    }
}

sub config_for_host
{
    my $line;
    my @lines;
    my $target = $_[0];

    if ( defined $ENV{'host_map'} ) { 
	@lines = split(/;/, $ENV{'host_map'});
	foreach $line (@lines){
	    if ( $line =~ /^$target=/ ) {
		@config = split(/=/, $line);
		return $config[1];
	    }
	}
	
    } else {
	@lines = vmware_command("-l");
	
	foreach $line (@lines){
	    if ( $line =~ /\/$target\// ) {
		chop($line);
		return $line;
	    }
	}
    }
}

$command = $ARGV[0];
if ( defined $ARGV[1] ) {
    $targetHost = $ARGV[1];
}

supply_default("device_host", "localhost");

if ( $command =~ /^gethosts$/ ) {
    supported_hosts;

} elsif ( $command =~ /^getconfignames$/ ) {
    print "device_host\n";

} elsif ( $command =~ /^getinfo-devid$/ ) {
    print "VMware Server STONITH device\n";
} elsif ( $command =~ /^getinfo-devname$/ ) {
    print "VMware Server STONITH device\n";
} elsif ( $command =~ /^getinfo-devdescr$/ ) {
    print "VMware Server STONITH device\n";
} elsif ( $command =~ /^getinfo-devurl$/ ) {
    print "http://www.vmware.com/";

} elsif ( $command =~ /^on$/ ) {
    $config = config_for_host($targetHost);
    my @lines = vmware_command($config, "start hard");
    print @lines;

} elsif ( $command =~ /^off$/ ) {
    $config = config_for_host($targetHost);
    my @lines = vmware_command($config, "stop hard");
    print @lines;

} elsif ( $command =~ /^reset$/ ) {
    $config = config_for_host($targetHost);
    my @lines = vmware_command($config, "reset hard");
    print @lines;

} elsif ( $command =~ /^status$/ ) {
    my $rc = 7;
    my $device = $ENV{'device_host'}; 
    if ( $device =~ /localhost/ ) {
	$rc = 0;
	# TODO: Check for the vmware process
	print "Local version: always running\n";

    } else {
	print "Remote version: running ping\n";
	@lines = readpipe "ping -c1 $device";
	print @lines;

	foreach $line ( @lines ) {
	    if ( $line =~ /0% packet loss/ ) {
		$rc = 0;
		last;
	    }
	}
    }
    exit($rc);

} elsif ( $command =~ /^getinfo-xml$/ ) {
    $metadata = <<END;
<parameters>
<parameter name="host_map" unique="0" required="0">
<content type="string" />
<shortdesc lang="en">
Host Map
</shortdesc>
<longdesc lang="en">
A mapping of hostnames to config paths supported by this device.
Eg. host1=/config/path/1;host2=/config/path/2;host3=/config/path/3;
</longdesc>
</parameter>
<parameter name="device_host" unique="0" required="0">
<content type="string" />
<shortdesc lang="en">
Device Host
</shortdesc>
<longdesc lang="en">
The machine _hosting_ the virtual machines
</longdesc>
</parameter>
</parameters>
END

print $metadata;

} else {
    print "Command $command: not supported\n";
    exit(3); # Not implemented
}


exit(0);
