Skip to content

Commit e6a5521

Browse files
Merge pull request #19 from pedrorcs/feature/sample_asset_cleanupApi_perlScript
Add Perl sample code to get Asset by a filter and invoke Asset Cleanu…
2 parents f02416e + 06a736a commit e6a5521

File tree

3 files changed

+269
-6
lines changed

3 files changed

+269
-6
lines changed

snippets/perl/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,13 @@ Catalog Image Details:
7070

7171
- Use the following command to obtain the catalog image details from your NetBackup Master server:
7272
- `perl get_nb_images.pl -nbmaster <master_server> -username <username> -password <password> [-domainname <domain_name>] [-domaintype <domain_type>] [--verbose]`
73+
74+
75+
Asset Cleanup Details:
76+
- Use the following command to query Assets by a user given specified filter, and cleanup time to delete all Assets returned by the filter. The cleanupTime field is an
77+
ISO 8601 formatted UTC timestamp.
78+
- Keep in mind that those Assets returned by the filter will be only delete if, the last discovered time of the Asset is older than the given cleanupTime and there is
79+
no a subscription associated with this asset.
80+
81+
- Example: perl post_nb_asset_cleanup.pl -nbmaster <master_server> -username <username> -password <pass> -filter "workloadType eq 'VMware'" -cleanuptime 2018-06-29T15:58:45.678Z
82+

snippets/perl/netbackup.pm

Lines changed: 184 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use LWP::UserAgent;
99
use LWP::Protocol::https;
1010

1111
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
12-
$CONTENT_TYPE = "application/vnd.netbackup+json; version=1.0";
12+
$CONTENT_TYPE_V1 = "application/vnd.netbackup+json; version=1.0";
13+
$CONTENT_TYPE_V2 = "application/vnd.netbackup+json; version=2.0";
1314
$NB_PORT = 1556;
1415

1516

@@ -48,7 +49,7 @@ sub login {
4849
}
4950

5051
my $req = HTTP::Request->new(POST => $token_url);
51-
$req->header('content-type' => "$CONTENT_TYPE");
52+
$req->header('content-type' => "$CONTENT_TYPE_V1");
5253
$req->content($post_data);
5354

5455
my $ua = LWP::UserAgent->new(
@@ -61,7 +62,7 @@ sub login {
6162
if ($resp->is_success) {
6263
my $message = decode_json($resp->content);
6364
my $token = $message->{"token"};
64-
print "Successfully completed Login Request.\n";
65+
print "Successfully completed Login Request.\n\n";
6566
return $token;
6667
}
6768
else {
@@ -100,7 +101,7 @@ sub logout {
100101
ssl_opts => { verify_hostname => 0, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE },
101102
);
102103

103-
print "Performing Logout Request on $logout_url\n";
104+
print "\n\nPerforming Logout Request on $logout_url\n";
104105
my $resp = $ua->request($logout_req);
105106
if ($resp->is_success) {
106107
print "Successfully completed Logout Request.\n";
@@ -133,7 +134,7 @@ sub getJobs {
133134
my $url = "https://$fqdn_hostname:$NB_PORT/netbackup/admin/jobs";
134135
my $jobs_req = HTTP::Request->new(GET => $url);
135136
$jobs_req->header('Authorization' => $token);
136-
$jobs_req->header('content-type' => "$CONTENT_TYPE");
137+
$jobs_req->header('content-type' => "$CONTENT_TYPE_V1");
137138

138139
my $ua = LWP::UserAgent->new(
139140
timeout => 500,
@@ -177,7 +178,7 @@ sub getCatalogImages {
177178
my $url = "https://$fqdn_hostname:$NB_PORT/netbackup/catalog/images";
178179
my $catalog_req = HTTP::Request->new(GET => $url);
179180
$catalog_req->header('Authorization' => $token);
180-
$catalog_req->header('content-type' => "$CONTENT_TYPE");
181+
$catalog_req->header('content-type' => "$CONTENT_TYPE_V1");
181182

182183
my $ua = LWP::UserAgent->new(
183184
timeout => 500,
@@ -316,5 +317,182 @@ sub displayCatalogImages {
316317

317318
}
318319

320+
#
321+
# This function returns a list of Asset based on
322+
# a filter parameter
323+
#
324+
325+
sub getAssetsByFilter {
326+
327+
my $arguments_count = scalar(@_);
328+
if ($arguments_count != 3) {
329+
print "ERROR :: Incorrect number of arguments passed to getAssetsByFilter()\n";
330+
print "Usage : getAssetsByFilter( <Asset filter> ) \n";
331+
return;
332+
}
333+
334+
my $fqdn_hostname = $_[0];
335+
my $token = $_[1];
336+
my $filter = $_[2];
337+
338+
my $url = "https://$fqdn_hostname:$NB_PORT/netbackup/assets?filter=$filter";
339+
my $assets_req = HTTP::Request->new(GET => $url);
340+
$assets_req->header('Authorization' => $token);
341+
$assets_req->header('content-type' => "$CONTENT_TYPE_V1");
342+
343+
my $ua = LWP::UserAgent->new(
344+
timeout => 1000,
345+
ssl_opts => { verify_hostname => 0, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE },
346+
);
347+
348+
print "Performing Get Assets Request on $url\n";
349+
my $response = $ua->request($assets_req);
350+
if ($response->is_success) {
351+
print "Successfully completed Get Assets by filter Request.\n";
352+
353+
$data = decode_json($response->content);
354+
my $pretty = JSON->new->pretty->encode($data);
355+
return $pretty;
356+
}
357+
else {
358+
print "ERROR :: Get Assets Request Failed!\n";
359+
print "HTTP GET error code: ", $response->code, "\n";
360+
print "HTTP GET error message: ", $response->message, "\n";
361+
}
362+
363+
}
364+
365+
#
366+
## This function displays the JSON content returned from Asset API
367+
## using query filter in a tabular format
368+
##
369+
sub displayAssets {
370+
371+
my $arguments_count = scalar(@_);
372+
if ($arguments_count != 1) {
373+
print "ERROR :: Incorrect number of arguments passed to displayAssets()\n";
374+
print "Usage : displayAssets( <JSON content returned from Assets API> ) \n";
375+
return;
376+
}
377+
378+
my $jsonstring = $_[0];
379+
my $json = decode_json($jsonstring);
380+
my @assets = @{$json->{'data'}};
381+
382+
my @tablerows;
383+
384+
foreach (@assets) {
385+
my $asset = $_;
386+
387+
my $assetId = $asset->{'id'};
388+
my $assetType = $asset->{'attributes'}->{'assetType'};
389+
my $workloadType = $asset->{'attributes'}->{'workloadType'};
390+
my $displayName = $asset->{'attributes'}->{'displayName'};
391+
my $version = $asset->{'attributes'}->{'version'};
392+
393+
my @tablerow = ($assetId, $assetType, $workloadType, $displayName, $version);
394+
push @tablerows, \@tablerow;
395+
}
396+
397+
my @title = ("Asset ID", "Asset Type", "Workload Type", "Display Name", "Version");
398+
print "\n";
399+
displayDataInTable(\@title, \@tablerows);
400+
print "\n";
401+
402+
}
403+
404+
#
405+
## This function create the Json payload for the Asset Cleanup API
406+
## It receives 2 paramters, the Json response from the GetAssetByFilter
407+
## and the cleanupTime. The response of this function is a proper payload
408+
## with all Assets from the filter.
409+
##
410+
sub createAssetCleanupPayload {
411+
412+
my $arguments_count = scalar(@_);
413+
if ($arguments_count != 2) {
414+
print "ERROR :: Incorrect number of arguments passed to createAssetCleanupPayload()\n";
415+
print "Usage : createAssetCleanupPayload( <Json content returned from Assets API>, <cleanupTime> ) \n";
416+
return;
417+
}
418+
419+
my $jsonstring = $_[0];
420+
my $cleanupTime = $_[1];
421+
my $valid_input = "false";
422+
my $json = decode_json($jsonstring);
423+
my @assets = @{$json->{'data'}};
424+
425+
my $payload = "{ \"data\":{ \"type\":\"assetCleanup\", \"id\":\"cleanupId\",";
426+
$payload = "$payload \"attributes\": { \"cleanupTime\":\"$cleanupTime\",";
427+
$payload = "$payload \"assetIds\":[";
428+
429+
foreach (@assets) {
430+
my $asset = $_;
431+
432+
my $assetId = $asset->{'id'};
433+
$payload = " $payload \"$assetId\",";
434+
$valid_input = "true";
435+
}
436+
437+
$payload = substr($payload, 0, (length $payload) - 1);
438+
$payload = " $payload ] } } }";
439+
440+
if ($valid_input eq "false"){
441+
return $valid_input;
442+
} else {
443+
return $payload;
444+
}
445+
446+
}
447+
448+
#
449+
## This function makes the call to the Asset Cleanup API.
450+
## If the web service goes successfully a HTTP 204 code is returned.
451+
## Any other HTTP response code will be considered a error in the Asset Cleanup API.
452+
##
453+
sub cleanAssets {
454+
455+
my $arguments_count = scalar(@_);
456+
if ($arguments_count != 4) {
457+
print "ERROR :: Incorrect number of arguments passed to cleanAssets()\n";
458+
print "Usage : cleanAssets( <Host Name>, <Authorization Token>, <Json content returned from Assets API>, <Cleanup Time> ) \n";
459+
return;
460+
}
461+
462+
my $hostname = $_[0];
463+
my $myToken = $_[1];
464+
my $jsonstring = $_[2];
465+
my $cleanuptime = $_[3];
466+
467+
my $payload = createAssetCleanupPayload($jsonstring, $cleanuptime);
468+
469+
if ($payload ne "false"){
470+
471+
my $asset_cleanup_url = "https://$hostname:$NB_PORT/netbackup/assets/asset-cleanup";
472+
my $asset_cleanup_req = HTTP::Request->new(POST => $asset_cleanup_url);
473+
$asset_cleanup_req->header('Authorization' => $myToken);
474+
$asset_cleanup_req->header('content-type' => "$CONTENT_TYPE_V2");
475+
$asset_cleanup_req->content($payload);
476+
477+
my $ua = LWP::UserAgent->new(
478+
timeout => 1000,
479+
ssl_opts => { verify_hostname => 0, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE },
480+
);
481+
482+
print "\n\nPerforming Asset Cleanup Request on $asset_cleanup_url\n";
483+
my $resp = $ua->request($asset_cleanup_req);
484+
if ($resp->is_success) {
485+
print "Successfully completed Asset Cleanup Request.\n";
486+
}
487+
else {
488+
print "ERROR :: Asset Cleanup Request Failed!\n";
489+
print "HTTP POST error code: ", $resp->code, "\n";
490+
print "HTTP POST error message: ", $resp->message, "\n";
491+
}
492+
} else {
493+
print "There is no asset to be clean\n";
494+
495+
}
496+
}
319497

320498
1;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#Load module netbackup.pm from current directory
2+
use lib '.';
3+
4+
use netbackup;
5+
use strict;
6+
use warnings;
7+
use Getopt::Long qw(GetOptions);
8+
use JSON;
9+
10+
sub printUsage {
11+
print "\nUsage : perl post_nb_asset_cleanup.pl -nbmaster <master_server> -username <username> -password <password> -filter <filter> -cleanuptime <cleanuptime> [-domainname <domain_name>] [-domaintype <domain_type>] [--verbose]\n\n";
12+
die;
13+
}
14+
15+
my $fqdn_hostname;
16+
my $username;
17+
my $password;
18+
my $filter;
19+
my $cleanuptime;
20+
my $domainname;
21+
my $domaintype;
22+
my $verbose;
23+
24+
GetOptions(
25+
'nbmaster=s' => \$fqdn_hostname,
26+
'username=s' => \$username,
27+
'password=s' => \$password,
28+
'filter=s' => \$filter,
29+
'cleanuptime=s' => \$cleanuptime,
30+
'domainname=s' => \$domainname,
31+
'domaintype=s' => \$domaintype,
32+
'verbose' => \$verbose
33+
) or printUsage();
34+
35+
if (!$fqdn_hostname || !$username || !$password || !$filter || !$cleanuptime) {
36+
printUsage();
37+
}
38+
39+
if($verbose){
40+
print "\nRecieved the following parameters : \n";
41+
print " FQDN Hostname : $fqdn_hostname\n";
42+
print " Username : $username\n";
43+
print " Password : $password\n";
44+
print " Filter: $filter\n";
45+
print " CleanupTime $cleanuptime\n";
46+
if ($domainname) {
47+
print " Domain Name : $domainname\n";
48+
}
49+
if ($domaintype) {
50+
print " Domain Type : $domaintype\n";
51+
}
52+
}
53+
54+
print "\n";
55+
my $myToken;
56+
if ($domainname && $domaintype) {
57+
$myToken = netbackup::login($fqdn_hostname, $username, $password, $domainname, $domaintype);
58+
}
59+
else{
60+
$myToken = netbackup::login($fqdn_hostname, $username, $password);
61+
}
62+
63+
my $jsonstring = netbackup::getAssetsByFilter($fqdn_hostname, $myToken, $filter);
64+
my $page_count = decode_json($jsonstring)->{'meta'}->{'pagination'}->{'count'};
65+
66+
if ($page_count ne 0 ){
67+
print "\nNetBackup Assets returned by filter: $filter\n";
68+
netbackup::displayAssets($jsonstring);
69+
netbackup::cleanAssets($fqdn_hostname, $myToken, $jsonstring, $cleanuptime);
70+
} else {
71+
print "\n Your filter: $filter did not return any asset."
72+
}
73+
74+
netbackup::logout($fqdn_hostname, $myToken);
75+
print "\n";

0 commit comments

Comments
 (0)