Für diejenigen unter euch, denen VCO kein Begriff ist, sei gesagt, dass es sich bei diesem Produkt um ein mächtiges Automatisierungs- und Orchestrierungs-Tool handelt, das dem VMware vCenter Server kostenlos beiliegt (Eine virtuelle Appliance ist ebenfalls verfügbar).
Weitere Informationen findet man u.a. unter den folgenden Links.
An dieser Stelle möchten wir nicht weiter auf die Funktionalität des VCO’s eingehen. So viel sei jedoch gesagt, der VCO erlaubt es jeden uns bekannten Task in einem virtuellen Datacenter und/oder Private-/Public-/Hybrid- Cloud zu automatisieren inkl. Einbindung bestehender Komponenten, wie beispielsweise einem Active Directory, Datenbanken, Provisioning Tools, Monitoring Tools usw. VCO ist ebenfalls das Bindeglied zwischen Produkten wie VMware Service Manager, VMware vCloud Director, RabbitMQ und erlaubt somit Rich Cloud Environments zur Verfügung zu stellen.
Nun jedoch zurück zum Thema. Wie kann man im VCO definierte Automatisierungs- und Orchestrierungs- Workflow von „außen“ ausführen/abfragen?! Hierzu bietet der VMware Orchestrator einen WebService Schnittstelle (SOAP) incl. WSDL. Sollte man Java oder .NET zum externen Aufruf von Workflows nutzen wollen ist dies mittlerweile sehr einfach, da bereits vorgefertigte Stubs und Klassen existieren die Ihr nutzen könnt. (Informationen findet Ihr hier). Möchte man das ganze jedoch mit einer anderen Sprache wie beispielsweise PHP/Perl/C/Python o.ä. realisieren gibt es einige Hürden die man nehmen muss.
Aus diesem Grund geben wir euch am Beispiel von Perl ein exemplarisches Skript an die Hand, das euch alle Schritte zeigt die nötig sind, um den WebService des VCO zu nutzen. Das Perl Skript sowie der Orchestrator Workflow sind bewusst sehr simpel gehalten, damit wir uns auf das wesentliche konzentrieren können. Das Perl Skript durchläuft dabei folgende Schritte:
- Es verbindet sich an den WebService von VCO
- Es versucht unseren Workflow ‚Show GuestOS‘ zu finden
- Durchsucht alle an den VCO angeschlossen vCenter nach virtuellen Maschinen
- Serialisiert ein Array in VMware Format mit den eindeutigen Namen der virtuellen Maschinen (dunesUri)
- Aufruf unseres Workflows mit dem Array
- Anschließend prüfen wir den Status des Workflows und warten auf dessen Beendigung
- Nach Abschluss des Tasks erhalten wir von unserem Workflow ein Serialisiertes Array im VMware Format zurück, das eine Liste der Gastbetriebssystem für die übergebenen virtuellen Maschinen enthält. Wir zeigen in diesem Zusammenhang auch, wie man die Informationen De-Serialisiert.
Damit Sie das Perl Skript und den Workflow nutzen könnt sind vor-ab noch folgende Schritte durchzuführen um die WebService Stubs zu generieren.
- Perl installieren (Unter Linux ist dies in den meisten Fällen über den Paketmanager der Distribution möglich, unter Windows empfehlen wir Strawberry Perl )
- SOAP::WSDL aus dem CPAN installieren, z.B. via ‚cpan SOAP::WSDL‚
- Stubs aus dem WSDL generieren (In diesem Zusammenhang weisen wir darauf hin, das die Stubs von einem AXIS 1.1 kompatiblen Generator erstellt werden müssen, unabhängig davon welche Programmier-/Skript- Sprache verwendet wird.) . Im Fall von Perl ist es ‚wsdl2perl.pl‚ was zusammen mit dem CPAN Modul installiert wird.
#!/usr/bin/perl
use Getopt::Long;
use Pod::Usage;
use SOAP::WSDL;
use MyInterfaces::VSOWebControlService::webservice;
use MyTypes::Workflow;
use Data::Dumper;
use warnings;
use strict;
my $man = 0;
my $help = 0;
my ( $username, $password );
GetOptions( 'help|?' => $help,
'man' => $man,
'username=s' => $username,
'password=s' => $password ) or pod2usage(2);
pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;
unless ( defined ( $username ) && defined ( $password ) ) {
pod2usage(message => "nSyntax error.n", -exitstatus => 1, -verbose => 2);
}
my $workflowName = "Show GuestOS";
my $interface = MyInterfaces::VSOWebControlService::webservice->new();
# Find workflow
my $response = $interface->getWorkflowsWithName ( {
workflowName => $workflowName,
username => $username,
password => $password,
},,
);
die $response if not $response;
my $elements = $response->get_getWorkflowsWithNameReturn();
die ("Exception: There is no worklows with name: '$workflowName' in the orchestrator.") unless ( defined ($elements) ) ;
die ("Exception: There are more than one workflow with name '$workflowName' in the orchestrator.") if ( @$elements > 1 ) ;
my $workflowId = $elements->get_id();
$response = $interface->find({
type => "VC:VirtualMachine", # string
query => "", # string
username => $username, # string
password => $password, # string
},,
);
die $response if not $response;
my $vmCount = $response->get_findReturn()->get_totalCount();
die ("Exception: There are no virtual machines in the vCenter's connected to the orchestrator.") if ( ! $vmCount ) ;
#get all virtual machines
my $vm = $response->get_findReturn()->get_elements()->get_item();
# cycle through all virutal machines and get dunes uri (unique object reference)
my @dunesUri;
for ( my $i = 0; $i < $vmCount ; $i++ ) { push (@dunesUri, $vm->[$i]->get_dunesUri());
}
my $vmSerialized = sprintf '#{#VC:VirtualMachine#%s#}#',join('#;#VC:VirtualMachine#', @dunesUri);
# Execute workflow
$response = $interface->executeWorkflow ( {
workflowId => $workflowId,
username => $username,
password => $password,
workflowInputs => [ {
name => "vms",
type => "Array/VC:VirtualMachine",
value => "$vmSerialized"
}]
});
sdie $response if not $response;
my $workflowToken = $response->get_executeWorkflowReturn();
$| = 1;
my $wfStatus;
my $counter=1;
do {
$response = $interface->getWorkflowTokenStatus( {
workflowTokenIds => $workflowToken->get_id(),
username => $username,
password => $password,
},,
);
$wfStatus = $response->get_getWorkflowTokenStatusReturn();
printf ("Workflow status: %s - Time elapsed: %s seconds. n" , $wfStatus, $counter);
sleep(1);
$counter++;
} while ($wfStatus eq "running");
$response = $interface->getWorkflowTokenResult( {
workflowTokenId => $workflowToken->get_id(),
username => $username,
password => $password,
},,
);
my $wfResult = $response->get_getWorkflowTokenResultReturn();
if ($wfStatus eq "failed") {
printf ("Reason: %sn", $wfResult->[0]->get_value());
}else {
my $returnSerialized = $wfResult->[1]->get_value();
$returnSerialized =~ s/^#{#string#(.*)#}#$/$1/;
my @ready = split ('#;#string#', $returnSerialized);
foreach (@ready) {
print "$_n";
}
}
__END__
=head1 NAME
showGuestOSFromAllVms
=head1 SYNOPSIS
Use:
perl showGuestOSFromAllVms.pl [--help] [--man] --username --password
Examples:
perl showGuestOSFromAllVms.pl --help
perl showGuestOSFromAllVms.pl --man
perl showGuestOSFromAllVms.pl --username xxxx --password xxx
=head1 DESCRIPTION
B demonstrates the use of orchestrator webservice API with Perl. It calls the workflow 'Show GuestOS' for all VM's (Danger! It will use all SdkConnectiosn of the Orchestrator). It also demonstrates how to pass simple and complex types (inclusive serialization/desirialization) to workflows, handle exceptions and handle return values from a workflow.
=head1 ARGUMENTS
=over 8
=item B
(Optional.) Print a brief help message and exits.
=item B
(Optional.) Prints the manual page and exits.
=back
=cut
Für diejenigen unter euch, denen VCO kein Begriff ist, sei gesagt es handelt sich bei diesem Produkt um ein mächtiges Automatisierungs- und Orchestrierungs-Tool das dem VMware vCenter Server kostenlos beiliegt (Eine VA ist ebenfalls verfügbar). Weitere Informationen findet man u.a. unter den folgenden Links.
An dieser Stelle möchten wir nicht weiter auf die Funktionalität des VCO’s eingehen. So viel sei jedoch gesagt, der VCO erlaubt es jeden uns bekannten Task in einem virtuellen Datacenter und/oder Private-/Public-/Hybrid- Cloud zu automatisieren inkl. Einbindung bestehender Komponenten, wie beispielsweise einem Active Directory, Datenbanken, Provisioning Tools, Monitoring Tools usw. VCO ist ebenfalls das Bindeglied zwischen Produkten wie VMware Service Manager, VMware vCloud Director, RabbitMQ und erlaubt somit Rich Cloud Environemnts zur Verfügung zu stellen.
Nun jedoch zurück zum Thema, wie man im VCO definierte Automatisierungs- und Orchestrierungs- Workflow von „außen“ ausführen/abfragen kann. Hierzu bietet der VMware Orchestrator einen WebService Schnittstelle (SOAP) incl. WSDL. Sollte man Java oder .NET zum externen Aufruf von Workflows nutzen wollen ist dies mittlerweile sehr einfach, da es bereits vorgefertigte Stubs und Klassen gibt die Ihr ganz normal einbinden könnt. (Informationen findet Ihr hier). Möchte man das ganze jedoch mit PHP/Perl o.ä. realisieren gibt es einige Hürden die man nehmen muss. WIr haben hierzu ein kleines Perl Skript inkl. eines Orchestrator Workflows erstellt, Ihr findet diese Dateien im Anhang dieses Blog Eintrags. Die beiden Komponenten sind bewusst sehr simpel gehalten, damit wir uns auf das wesentliche konzentrieren können, die Serialisierung/De-Serialisierung von komplexen Datentypen. Das Perl Skript durchläuft dabei folgende Schritte:
- Es verbindet sich an den WebService von VCO
- Es versucht unseren Workflow ‚Show GuestOS‘ zu finden
- Dursucht alle an den VCO angeschlossen vCenter nach virtuellen Maschinen
- Serialisiert ein Array in VMware Format mit den eindeutigen Namen der virtuellen Maschinen (dunesUri)
- Aufruf unseres Workflows mit dem Array
- Anschließend prüfen wir den Status des Workflows und warten auf dessen Beendigung
- Nach Abschluss des Tasks erhalten wir von unserem Workflow ein Serialisiertes Array im VMware Format zurück, das eine Liste der Gastbetriebssystem für die übergebenen virtuellen Maschinen enthält. Wir zeigen in diesem Zusammenhang auch wie man die Informationen De-Serialisiert.
Anbei findet Ihr das vollständig Perl-Skript das den Aufruf von Workflows inkl. Serialisierung/De-Serialisierung aufzeigt. Vor-Ab sind noch folgende Schritte durchzuführen um die WebService Stubs zu generieren.
- Perl installieren (Unter Linux ist dies in den meisten Fällen über den Paketmanager der Distribution möglich, unter Windows würde ich Strawberry Perl empfehlen)
- SOAP::WSDL aus dem CPAN installieren, z.B. via ‚cpan SOAP::WSDL‚
- Stubs aus dem WSDL generieren (In diesem Zusammenhang weise ich darauf hin das wenn Ihr die Stubs generiert einen AXIS 1.1 kompatiblen Generator nutzen müsst, unabhängig welche Programmier-/Skript- Sprache ihr verwendet.) . Im Fall von Perl nutzt Ihr ‚wsdl2perl.pl‚ was zusammen mit dem CPAN Modul installiert wurde.
#!/usr/bin/perl use Getopt::Long; use Pod::Usage; use SOAP::WSDL; use MyInterfaces::VSOWebControlService::webservice; use MyTypes::Workflow; use Data::Dumper; use warnings; use strict; my $man = 0; my $help = 0; my ( $username, $password ); GetOptions( 'help|?' => $help, 'man' => $man, 'username=s' => $username, 'password=s' => $password ) or pod2usage(2); pod2usage(1) if $help; pod2usage(-exitstatus => 0, -verbose => 2) if $man; unless ( defined ( $username ) && defined ( $password ) ) { pod2usage(message => "nSyntax error.n", -exitstatus => 1, -verbose => 2); } my $workflowName = "Show GuestOS"; my $interface = MyInterfaces::VSOWebControlService::webservice->new(); # Find workflow my $response = $interface->getWorkflowsWithName ( { workflowName => $workflowName, username => $username, password => $password, },, ); die $response if not $response; my $elements = $response->get_getWorkflowsWithNameReturn(); die ("Exception: There is no worklows with name: '$workflowName' in the orchestrator.") unless ( defined ($elements) ) ; die ("Exception: There are more than one workflow with name '$workflowName' in the orchestrator.") if ( @$elements > 1 ) ; my $workflowId = $elements->get_id(); $response = $interface->find({ type => "VC:VirtualMachine", # string query => "", # string username => $username, # string password => $password, # string },, ); die $response if not $response; my $vmCount = $response->get_findReturn()->get_totalCount(); die ("Exception: There are no virtual machines in the vCenter's connected to the orchestrator.") if ( ! $vmCount ) ; #get all virtual machines my $vm = $response->get_findReturn()->get_elements()->get_item(); # cycle through all virutal machines and get dunes uri (unique object reference) my @dunesUri; for ( my $i = 0; $i < $vmCount ; $i++ ) { push (@dunesUri, $vm->[$i]->get_dunesUri()); } my $vmSerialized = sprintf '#{#VC:VirtualMachine#%s#}#',join('#;#VC:VirtualMachine#', @dunesUri); # Execute workflow $response = $interface->executeWorkflow ( { workflowId => $workflowId, username => $username, password => $password, workflowInputs => [ { name => "vms", type => "Array/VC:VirtualMachine", value => "$vmSerialized" }] }); sdie $response if not $response; my $workflowToken = $response->get_executeWorkflowReturn(); $| = 1; my $wfStatus; my $counter=1; do { $response = $interface->getWorkflowTokenStatus( { workflowTokenIds => $workflowToken->get_id(), username => $username, password => $password, },, ); $wfStatus = $response->get_getWorkflowTokenStatusReturn(); printf ("Workflow status: %s - Time elapsed: %s seconds. n" , $wfStatus, $counter); sleep(1); $counter++; } while ($wfStatus eq "running"); $response = $interface->getWorkflowTokenResult( { workflowTokenId => $workflowToken->get_id(), username => $username, password => $password, },, ); my $wfResult = $response->get_getWorkflowTokenResultReturn(); if ($wfStatus eq "failed") { printf ("Reason: %sn", $wfResult->[0]->get_value()); }else { my $returnSerialized = $wfResult->[1]->get_value(); $returnSerialized =~ s/^#{#string#(.*)#}#$/$1/; my @ready = split ('#;#string#', $returnSerialized); foreach (@ready) { print "$_n"; } } __END__ =head1 NAME showGuestOSFromAllVms =head1 SYNOPSIS Use: perl showGuestOSFromAllVms.pl [--help] [--man] --username --password Examples: perl showGuestOSFromAllVms.pl --help perl showGuestOSFromAllVms.pl --man perl showGuestOSFromAllVms.pl --username xxxx --password xxx =head1 DESCRIPTION B demonstrates the use of orchestrator webservice API with Perl. It calls the workflow 'Show GuestOS' for all VM's (Danger! It will use all SdkConnectiosn of the Orchestrator). It also demonstrates how to pass simple and complex types (inclusive serialization/desirialization) to workflows, handle exceptions and handle return values from a workflow. =head1 ARGUMENTS =over 8 =item B (Optional.) Print a brief help message and exits. =item B (Optional.) Prints the manual page and exits. =back =cut