#
# Copyright 1998 VMware, Inc.  All rights reserved. -- VMware Confidential
#

package VMware::Control::Server;

use strict;
use Carp;

require DynaLoader;

use vars qw($VERSION @ISA);

BEGIN{$VERSION = '1.01'};

@ISA = qw(DynaLoader);

use VMware::Control $VERSION;
use VMware::Control::Profiler;

my $p = VMware::Control::Profiler::getInstance("mui");

# Preloaded methods go here.

sub new {
    my $stub = $p->profile();
    my ($hostname, $port, $username, $password) = (undef, 0, undef, undef);

    $hostname = shift if $#_ >= 0;
    $port = shift if $#_ >= 0;
    $username = shift if $#_ >= 0;
    $password = shift if $#_ >= 0;

    if (!defined($port)) {
        $port = 0;
    }
            
    return New($hostname, $port, $username, $password);
}

sub get_last_error {
    my $stub = $p->profile();
    my $server = shift;
    my ($ret, $string) = $server->GetLastError();
    if (wantarray) {
        return ($ret, $string);
    } else {
        return $ret;
    }
}

sub connect {
    my $stub = $p->profile();
    my $server = shift;
    my $ret = $server->Connect();

    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

sub is_connected {
    my $stub = $p->profile();
    my $server = shift;
    return $server->IsConnected();
}

sub enumerate {
    my $stub = $p->profile();
    my $server = shift;
    my %hash;
    my @values = $server->Enumerate();

    # Hack to remove duplicates XXX
    my @unique_values;
    foreach my $value (@values) {
        if (!defined($hash{$value})) {
            $hash{$value} = 1;
            push @unique_values, $value;
        }
    }
    return @unique_values;
}

sub disconnect {
    my $stub = $p->profile();
    my $server = shift;
    my $ret = $server->Disconnect();

    return 1;
}

sub register {
    my $stub = $p->profile();
    my $server = shift;
    my $cfg = shift;
    my $ret = $server->Register($cfg);
    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

sub unregister {
    my $stub = $p->profile();
    my $server = shift;
    my $cfg = shift;
    my $ret = $server->Unregister($cfg);
    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

sub is_registered {
    my $stub = $p->profile();
    my $server = shift;
    my $cfg = shift;
    my ($ret, $isRegistered) = $server->IsRegistered($cfg);
    if ($ret) {
	if (!defined($isRegistered)) {
	    croak("VMware::Control::Server::is_registered query succeeded but isRegistered not defined");
	}
        return $isRegistered;
    } else {
        return undef;
    }
}

sub get {
    my $server = shift;
    my $query = shift;
    my $ret = $server->GetAsString($query);
    # XXX It's possible to get lists of values from GetAsString.  We should
    # parse these lists into better Perl structures. -jhu
    return $ret;
}

sub set {
    my $server = shift;

    my %pairs = @_;
    my $ret;

    foreach my $key (keys(%pairs)) {
        my $value = $pairs{$key};
        if (!defined($value)) {
            $server->SetError(VM_E_INVALIDARGS,
			      "uneven number of arguments -- set() requires a hash");
            return undef;
        }
	if ($key =~ m/^Resource\..+$/) {
	    $ret = $server->SetAsString($key, $value);
        } else {
            $server->SetError(VM_E_INVALIDARGS,
			      "Only keys in the Resource.* namespace can be set.");
            return undef;
	}
    }
    
    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

sub exec {
    my $stub = $p->profile();
    my $server = shift;
    my $xmlargs = shift;
    my $ret = $server->Exec($xmlargs);
    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

sub shutdown {
    my $stub = $p->profile();
    my $server = shift;
    my $ret = $server->Shutdown();
    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

sub set_timeout {
    my $server = shift;
    my $timeout = shift;
    return $server->SetTimeout($timeout);
}

sub test {
    my $stub = $p->profile();
    my $server = shift;
    my $query = shift;
    my $ret = $server->Test($query);
    if ($ret) {
        return $ret;
    } else {
        return undef;
    }
}

#Initialize the Server portion of the API library and return 1 if OK
VMware::Control::Server::Init();
__END__

=head1 NAME

VMware::Control::Server - Programmatically manipulate a server running
VMware virtual machines.

=head1 SYNOPSIS

  use VMware::Control::Server;

  # Connect to a remote machine
  $server = VMware::Control::Server::new("vmware.companyX.com", 902, 
                                         $username, $password);
  $err = $server->connect();

  # Connect to the local machine as the current user
  $server = VMware::Control::Server::new();
  $err = $server->connect();
  if (!defined($err)) {
    ($errorNumber, $errorString) = $server->get_last_error();
  }

  @vm_identifiers = $server->enumerate();

  $server->disconnect();

=head1 DESCRIPTION

This package provides an interface for connecting to a VMware server
product and listing the virtual machines available on the server.

CAUTION: This API is preliminary and will change significantly between
this Beta and the final release version.

(This package in particular is far from complete -- future versions
will provide more access to information about the server and more
control over the server.)

=item VMware::Control::Server::new($hostname, $port, $username, $password)

Connects to the given hostname and network port and authenticates with
the supplied username and password.  If $hostname is not given or
undef, the authentication is performed for the local machine.  In this
case, the username and password are optional: if they are not supplied
the current user is authenticated to VMware.  (Otherwise, username and
password may still be supplied to authenticate as a different user.)

=item $server->connect()

Attempt to establish a connection to the server.

=item $server->get_last_error()

When a method fails (that is, returns undef), this method will return
the error code corresponding to the failure, along with a string
description (often with more specific error information).

=item $server->enumerate()

This method enumerates the VMs on the server, and returns a list of VM
identifiers.  Given a VM_IDENTIFIER, a VM object can be created using
VMware::Control::VM.  The results are not returned in any particular order.

C<$server-E<gt>enumerate> only returns identifiers for VMs for which you
have appropriate access rights. Thus it is possible that enumerate
will not return a complete list of the VMs on the current machine.
See L<ACCESS CONTROL> for more information.

Returns a list of VM_IDENTIFIERS.

=item $server->disconnect()

Close the connection to the server.

=head1 AUTHORS

John Haggerty, Daniel Kerns, Brett Vasconcellos.

=head1 COPYRIGHT

    (c) 2000 VMware Incorporated.  All rights reserved.

=head1 VERSION

Version 0.2	   21 Sep  2000

C<% pod2html --header --title="VMware::Control::Server" E<lt> Server.pm E<gt> perlAPI-server.html>

=head1 SEE ALSO

perl(1).

=cut
