Active IQ Unified Manager Discussions

perl webservices client

kleemola
7,698 Views

Has anybody written any code to use perl to connect to WFA webservices?  Can it be done?  The only example provided in the webservices guide uses a MS-specific auth method.  I'm trying to write some perl, but I'm stuck at the auth piece.  I'm a bit of a webservices newbie here.

1 ACCEPTED SOLUTION

arndt
5,554 Views

Here are some more examples of using Perl to interact with WFA via SOAP...along with comments that give some hints about where I had struggles.  I'm not sure if my struggles were due to the immaturity of the SOAP::Lite module or my own lack of SOAP experience, but I suspect it's a combination of both .

wfa_get_all_workflows.pl

------------------------------------

#!/usr/bin/perl -w

use strict;

# Use 'trace' if you need to debug the XML interactions.

#use SOAP::Lite 'trace';

use SOAP::Lite;

# We have to use the RPC interface for SOAP calls that don't have

# any arguments.  Google xsi:nil true soap::lite if you want the gory

# details about how SOAP::Lite is broken.  Thankfully, WFA supports

# both doc and rpc interfaces.

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_rpc?wsdl';

my $namespace = 'http://ws.wfa.netapp.com/';

my $user      = "admin";

my $pass      = "admin";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

$service->ns($namespace);

# Setting autotype is not really necessary, but I like it when debugging.

$service->autotype('0');

# The use_prefix setting is deprecated, but I think it makes debbuing easier

# if you have tracing enabled.

#$service->use_prefix('0');

my $som    = $service->getAllWorkflows();

my $result = $som->result;

my $items  = $result->{'item'};

for my $item (@$items) {

        print "Workflow ID:          $item->{'id'}\n";

        print "Workflow Category:    $item->{'category'}\n";

        print "Workflow Name:        $item->{'name'}\n";

        print "Workflow Description: $item->{'description'}\n";

        print "Workflow Input: \n";

        my $inputs = $item->{'userInput'};

        for my $input (sort @$inputs) {

                print "  $input->{'name'} ($input->{'type'})\n";

        }

        print "\n";

}

------------------------------------

wfa_run_workflow.pl

----------------------------

#!/usr/bin/perl -w

use strict;

# Use 'trace' if you need to debug the XML interactions.

#use SOAP::Lite 'trace';

use SOAP::Lite;

# Oddly, the doc interface works and the rpc interface does not work when

# making a SOAP call with arguments.  The opposite is true when making

# SOAP calls with no arguments.  Good thing WFA supports both.  SOAP is fun.

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_doc?wsdl';

my $namespace = 'http://ws.wfa.netapp.com/';

my $user      = "admin";

my $pass      = "admin";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

$service->ns($namespace);

# Setting autotype is not really necessary, but I like it when debugging.

$service->autotype('0');

# The use_prefix setting is deprecated, but I think it makes debbuing easier

# if you have tracing enabled.

#$service->use_prefix('0');

my $wfid      = 31;

my $wfidparam = SOAP::Data->name('workflowId')->value($wfid);

my $wfparams  = SOAP::Data->name('userInputsEqualsValues')->value

([

        'controllerName=demo3020a.demo.ntapmn.com',

        'vfilerName=dmvfiler1',

        'volName_1=arndt_test',

        'qtreeName_1=wfasoapqt4',

        'qtreeStyle_1=unix',

        'create_Share_1=no',

        'create_Export_1=yes',

        'rootHosts=10.26.69.212:10.26.69.213',

]);

# I had to set even the optional arguments to make this work.

my $wftime   = SOAP::Data->name('executionDateAndTime')->value('');

my $wfcom    = SOAP::Data->name('comment')->value('');

my $som = $service->runWorkflow($wfidparam,$wfparams,$wftime,$wfcom);

if ($som->faultcode) {

        print "Fault Code:", $som->faultcode, "\n";

        print "Fault String:", $som->faultstring, "\n";

} else {

        my $result   = $som->result;

        print "Job $result has been submitted.\n";

}

----------------------------

wfa_get_job_status.pl

-------------------------------

#!/usr/bin/perl -w

use strict;

# Use 'trace' if you need to debug the XML interactions.

#use SOAP::Lite 'trace';

use SOAP::Lite;

# Oddly, the doc interface works and the rpc interface does not work when

# making a SOAP call with arguments.  The opposite is true when making

# SOAP calls with no arguments.  Good thing WFA supports both.  SOAP is fun.

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_doc?wsdl';

my $namespace = 'http://ws.wfa.netapp.com/';

my $user      = "admin";

my $pass      = "admin";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

$service->ns($namespace);

# Setting autotype is not really necessary, but I like it when debugging.

$service->autotype('0');

# The use_prefix setting is deprecated, but I think it makes debbuing easier

# if you have tracing enabled.

#$service->use_prefix('0');

my $jobid      = 392;

my $jobidparam = SOAP::Data->name('jobId')->value($jobid);

my $som = $service->getJobStatus($jobidparam);

if ($som->faultcode) {

        print "Fault Code:", $som->faultcode, "\n";

        print "Fault String:", $som->faultstring, "\n";

} else {

        my $result   = $som->result;

        print "Job start time: $result->{'startTime'}\n";

        print "Job end time:   $result->{'endTime'}\n" if ($result->{'endTime'});

        print "Job status:     $result->{'jobStatus'}\n";

        print "Job messages:   $result->{'errorMessage'}\n" if ($result->{'errorMessage'});

}

-------------------------------

View solution in original post

10 REPLIES 10

goodrum
7,631 Views

I have done this with PHP but I assume that it will be very similar.  The key is to look at the function in the WSDL to determine what values need to be passed and how. 

<code php>

$soapClient   = new SoapClient("http://wfaServer/wfa-ws/WorkflowService_doc?wsdl",

   array(

   'login'=>'admin',

   'password'=>'admin'))

$client->executeWorkflow (array ("workflowId" => WorkflowNumber, "userInputsEqualsValues" =>

        array ("userInput1=Value1", "userInput2=Value2")

        )

);

</code php>

tp7317
7,631 Views

None of the examples here work for me.   The PHP example I get:

PHP Parse error:  syntax error, unexpected T_VARIABLE in /root/wfa/wfa.php on line 20

And the Perl Example the variable is empty even though the script completes without error.

kleemola
7,631 Views

I'm having some success using the SOAP::WSDL module.

1a.  Install SOAP::WSDL and SOAP::Lite from cpan. 

1b. Libexpat-dev is required on the system first!!

2.  wsdl2perl.pl -b /usr/lib/perl5/ http://wfaserver/wfa-ws/WorkflowService_doc?wsdl

where: /usr/lib/perl is somewhere in your @INC path and the second arg is the url of the doc/literal service for your WFA inst.

3.  Here's what I've got so far.  Replace $user and $password.  Authentication works fine, though I'd prefer to use the WSDL module auth.  The result comes back as the body of the SOAP message.  I'm now working on parsing it.  If anybody has any input on that, please speak up. 

#!/usr/bin/perl

use SOAP::Lite;
#use SOAP::Lite +autodispatch, +trace => debug;
use MyInterfaces::WorkflowService::WorkflowService_docPort;
use MyTypes::getAllWorkflows;
use MyElements::getAllWorkflows;
use MyTypemaps::WorkflowService;
use SOAP::WSDL;
use SOAP::WSDL::Client;
use SOAP::WSDL::Transport::HTTP;

my $user = "myuser";
my $password = "mypassword";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {
return $user => $password ;
}

## Connect to service
my $service = MyInterfaces::WorkflowService::WorkflowService_docPort->new();

## Print results
#my $result = MyTypes::getAllWorkflows;
my $result = $service->getAllWorkflows();
die $result if not $result;
my $xml = $result;
print "\nMy xml:\n $xml \n\n";

pwl
NetApp Alumni
7,630 Views

girirp
7,630 Views

Hi,

here is a sample code.

=================================================

#!perl -w

use SOAP::Lite;

my $lite = SOAP::Lite -> service('http://wfa_ip_address/wfa-ws/WorkflowService_doc?wsdl');

print "After creating Service \n";

my $res = $lite->getAllWorkflows();

print "After calling getAllworkflows\n";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

    return 'username' => 'password';

}

================================================

arndt
7,630 Views

I'm trying this sample code to call getAllWorkflows, and I have XML output enabled to help me debug this  I get the following error when using the _doc service address:

<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><env:Header></env:Header><env:Body><env:Fault xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><faultcode>env:Server</faultcode><faultstring>Request struct cannot be null</faultstring></env:Fault></env:Body></env:Envelope>

I've also tried the _rpc service address, and then I get the following error:

<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><env:Header></env:Header><env:Body><env:Fault xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><faultcode>env:VersionMismatch</faultcode><faultstring>Invalid SOAP envelope namespace: http://schemas.xmlsoap.org/wsdl/soap/</faultstring></env:Fault></env:Body></env:Envelope>

I do believe that my authentication is working, as I get a different error if I put in the wrong URL or wrong user/pass.  My code is below....any thoughts?  Thanks!

#!/usr/bin/perl -w

use strict;

use SOAP::Lite;

my $user    = "admin";

my $pass    = "admin";

my $soapurl = "http://WFA_IP/wfa-ws/WorkflowService_doc?wsdl";

my $usexml  = 1;

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = SOAP::Lite -> service($soapurl);

$service->outputxml($usexml);

my $result = $service->getAllWorkflows();

print "R:$result\n";

kleemola
7,630 Views

Try:

use SOAP::Lite +autodispatch;

And/or:

use SOAP::Lite +autodispatch, +trace => debug;

See my post elsewhere in the thread.  I'm having better success using the SOAP::WSDL module.  I believe the WFA team is working on some official documentation on WFA/perf webservice integration, so stay tuned.

arndt
7,630 Views

OK, I finally got this figured out by looking at the XML request being sent by the perl script that was not working with a PHP script that was working.  The Perl script was not properly setting the namespace, so I modified the way that the Perl script connects as shown below.  Below is also an example of parsing the output sent back for the GetAllWorkflows call.  Note that I also had to use the _rpc interface instead of the _doc interface to the WFA web services.  Hope this helps someone else looking to connect to WFA web services via Perl.

#!/usr/bin/perl -w

use strict;

use SOAP::Lite;

my $user      = "admin";

my $pass      = "admin";

my $namespace = 'http://ws.wfa.netapp.com/';

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_rpc?wsdl';

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

my $som    = $service->getAllWorkflows();

my $result = $som->result;

my $items  = $result->{'item'};

for my $item (@$items) {

        print "Workflow ID:          $item->{'id'}\n";

        print "Workflow Category:    $item->{'category'}\n";

        print "Workflow Name:        $item->{'name'}\n";

        print "Workflow Description: $item->{'description'}\n";

        print "Workflow Input: \n";

        my $inputs = $item->{'userInput'};

        for my $input (sort @$inputs) {

                print "  $input->{'name'} ($input->{'type'})\n";

        }

        print "\n";

}

pwl
NetApp Alumni
7,630 Views

Great work mike!

arndt
5,555 Views

Here are some more examples of using Perl to interact with WFA via SOAP...along with comments that give some hints about where I had struggles.  I'm not sure if my struggles were due to the immaturity of the SOAP::Lite module or my own lack of SOAP experience, but I suspect it's a combination of both .

wfa_get_all_workflows.pl

------------------------------------

#!/usr/bin/perl -w

use strict;

# Use 'trace' if you need to debug the XML interactions.

#use SOAP::Lite 'trace';

use SOAP::Lite;

# We have to use the RPC interface for SOAP calls that don't have

# any arguments.  Google xsi:nil true soap::lite if you want the gory

# details about how SOAP::Lite is broken.  Thankfully, WFA supports

# both doc and rpc interfaces.

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_rpc?wsdl';

my $namespace = 'http://ws.wfa.netapp.com/';

my $user      = "admin";

my $pass      = "admin";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

$service->ns($namespace);

# Setting autotype is not really necessary, but I like it when debugging.

$service->autotype('0');

# The use_prefix setting is deprecated, but I think it makes debbuing easier

# if you have tracing enabled.

#$service->use_prefix('0');

my $som    = $service->getAllWorkflows();

my $result = $som->result;

my $items  = $result->{'item'};

for my $item (@$items) {

        print "Workflow ID:          $item->{'id'}\n";

        print "Workflow Category:    $item->{'category'}\n";

        print "Workflow Name:        $item->{'name'}\n";

        print "Workflow Description: $item->{'description'}\n";

        print "Workflow Input: \n";

        my $inputs = $item->{'userInput'};

        for my $input (sort @$inputs) {

                print "  $input->{'name'} ($input->{'type'})\n";

        }

        print "\n";

}

------------------------------------

wfa_run_workflow.pl

----------------------------

#!/usr/bin/perl -w

use strict;

# Use 'trace' if you need to debug the XML interactions.

#use SOAP::Lite 'trace';

use SOAP::Lite;

# Oddly, the doc interface works and the rpc interface does not work when

# making a SOAP call with arguments.  The opposite is true when making

# SOAP calls with no arguments.  Good thing WFA supports both.  SOAP is fun.

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_doc?wsdl';

my $namespace = 'http://ws.wfa.netapp.com/';

my $user      = "admin";

my $pass      = "admin";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

$service->ns($namespace);

# Setting autotype is not really necessary, but I like it when debugging.

$service->autotype('0');

# The use_prefix setting is deprecated, but I think it makes debbuing easier

# if you have tracing enabled.

#$service->use_prefix('0');

my $wfid      = 31;

my $wfidparam = SOAP::Data->name('workflowId')->value($wfid);

my $wfparams  = SOAP::Data->name('userInputsEqualsValues')->value

([

        'controllerName=demo3020a.demo.ntapmn.com',

        'vfilerName=dmvfiler1',

        'volName_1=arndt_test',

        'qtreeName_1=wfasoapqt4',

        'qtreeStyle_1=unix',

        'create_Share_1=no',

        'create_Export_1=yes',

        'rootHosts=10.26.69.212:10.26.69.213',

]);

# I had to set even the optional arguments to make this work.

my $wftime   = SOAP::Data->name('executionDateAndTime')->value('');

my $wfcom    = SOAP::Data->name('comment')->value('');

my $som = $service->runWorkflow($wfidparam,$wfparams,$wftime,$wfcom);

if ($som->faultcode) {

        print "Fault Code:", $som->faultcode, "\n";

        print "Fault String:", $som->faultstring, "\n";

} else {

        my $result   = $som->result;

        print "Job $result has been submitted.\n";

}

----------------------------

wfa_get_job_status.pl

-------------------------------

#!/usr/bin/perl -w

use strict;

# Use 'trace' if you need to debug the XML interactions.

#use SOAP::Lite 'trace';

use SOAP::Lite;

# Oddly, the doc interface works and the rpc interface does not work when

# making a SOAP call with arguments.  The opposite is true when making

# SOAP calls with no arguments.  Good thing WFA supports both.  SOAP is fun.

my $soapurl   = 'http://WFA_IP/wfa-ws/WorkflowService_doc?wsdl';

my $namespace = 'http://ws.wfa.netapp.com/';

my $user      = "admin";

my $pass      = "admin";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

        return $user => $pass;

}

my $service = new SOAP::Lite

        uri   => $namespace,

        proxy => $soapurl,

;

$service->ns($namespace);

# Setting autotype is not really necessary, but I like it when debugging.

$service->autotype('0');

# The use_prefix setting is deprecated, but I think it makes debbuing easier

# if you have tracing enabled.

#$service->use_prefix('0');

my $jobid      = 392;

my $jobidparam = SOAP::Data->name('jobId')->value($jobid);

my $som = $service->getJobStatus($jobidparam);

if ($som->faultcode) {

        print "Fault Code:", $som->faultcode, "\n";

        print "Fault String:", $som->faultstring, "\n";

} else {

        my $result   = $som->result;

        print "Job start time: $result->{'startTime'}\n";

        print "Job end time:   $result->{'endTime'}\n" if ($result->{'endTime'});

        print "Job status:     $result->{'jobStatus'}\n";

        print "Job messages:   $result->{'errorMessage'}\n" if ($result->{'errorMessage'});

}

-------------------------------

Public