#===============================================================#
#                                                               #
# $ID$                                                          #
#                                                               #
#  policy.pl                                                    #
#                                                               #
# Copyright (c) 2009 NetApp, Inc. All rights reserved.          #
# Specifications subject to change without notice.              #
#                                                               #
# Sample code to demonstrate how to:                            #
#        - list/delete protection policies                      #
#        - list/create/delete a new provisionoing policy        #
#                                                               #
# This Sample code is supported from DataFabric Manager 3.8     #
# onwards.                                                      #
# However few of the functionalities of the sample code may     #
# work on older versions of DataFabric Manager.                 #
#===============================================================#
require 5.6.1;

use lib '../../../../../../../lib/perl/NetApp';
use NaServer;
use NaElement;
use strict;

# Variables declaration
my $args      = $#ARGV + 1;
my $dfmserver = shift;
my $dfmuser   = shift;
my $dfmpw     = shift;
my $command   = shift;

# check for valid number of parameters
if ( $args < 4 ) {
	print_usage();
}

# Print usage of this script
sub print_usage() {
	print <<MSG;
Usage:
 policy.pl <dfmserver> <user> <password> list {-v [<prov-name>] | -t [<prot-name>]}
 policy.pl <dfmserver> <user> <password> destroy <prov-name>
 policy.pl <dfmserver> <user> <password> create <prov-name> <type> <rtag>

 <dfmserver>        -- Name/IP Address of the DFM server
 <user>             -- DFM server User name
 <password>         -- DFM server User Password
 <prov-name>        -- provisioning policy name
 <prot-name>        -- protection policy name
 <type>             -- provisioning policy type, san or nas
 <rtag>             -- Resource tag for policy

Creates policy with default options :
	NAS - User-quota=Group-quota=1G,Thin-prov=True, Snapshot-reserve=False
	SAN - Storage-Container=Volume, Thin-prov=True.
MSG
	exit 1;
}

# Setup DFM server connection
my $s = NaServer->new( $dfmserver, 1, 0 );
$s->set_style("LOGIN");
$s->set_transport_type("HTTP");
$s->set_server_type("DFM");
$s->set_port(8088);
$s->set_admin_user( $dfmuser, $dfmpw );

# List provisioning or protection policy
if ( $command eq "list" ) {
	my $subCommand = shift;

	#List provisioning policy
	if ( $subCommand eq "-v" ) {
		my $pname = shift;

		# Begin the iterator APIs
		my $in = NaElement->new("provisioning-policy-list-iter-start");
		if ( $pname ne "" ) {
			$in->child_add_string( "provisioning-policy-name-or-id", $pname );
		}
		my $out = $s->invoke_elem($in);
		if ( $out->results_status() eq "failed" ) {
			print( "Error : " . $out->results_reason() . "\n" );
			exit(-2);
		}

		# Use tag and records retrieved in previous API call to initiate records retrieval
		my $in = NaElement->new("provisioning-policy-list-iter-next");
		$in->child_add_string( "maximum", $out->child_get_int("records") );
		$in->child_add_string( "tag",     $out->child_get_string("tag") );

		my $out = $s->invoke_elem($in);
		if ( $out->results_status() eq "failed" ) {
			print( "Error : " . $out->results_reason() . "\n" );
			exit(-2);
		}
		print "\nProvisioning Policies:\n";
		print
"===================================================================\n";
		my $pps = $out->child_get("provisioning-policies");
		if ( $pps eq "" ) {
			print "Error: No Provisioning Policies!\n";
			exit;
		}
		my @ppInfos = $pps->children_get("provisioning-policy-info");

		# Print details from the records retrieved iteratively
		foreach my $ppi (@ppInfos) {
			print "Policy Name\t: "
			  . $ppi->child_get_string("provisioning-policy-name");
			print "\n";
			my $pType = $ppi->child_get_string("provisioning-policy-type");
			print "Policy Type\t: " . $pType;
			print "\n";
			print "Resource Tag\t: " . $ppi->child_get_string("resource-tag");
			print "\n";

			# If it is a NAS policy
			if ( $pType eq "nas" ) {
				print "NAS container Settings:\n";
				my $nas = $ppi->child_get("nas-container-settings");
				print "\t\tDefault User Quota  : "
				  . $nas->child_get_int("default-user-quota");
				print "\n";
				print "\t\tDefault Group Quota : "
				  . $nas->child_get_int("default-group-quota");
				print "\n";
				print "\t\tSnapshot Reserve    : "
				  . $nas->child_get_string("snapshot-reserve");
				print "\n";
				print "\t\tThin Provision      : "
				  . $nas->child_get_string("thin-provision");
				print "\n";
			} elsif ( $pType eq "san" ) { # If it is a SAN policy
				print "SAN container Settings:\n";
				my $san = $ppi->child_get("san-container-settings");
				print "\t\tStorage Container Type\t: "
				  . $san->child_get_string("storage-container-type");
				print "\n";
				print "\t\tThin Provision\t\t: "
				  . $san->child_get_string("thin-provision");
				print "\n";
				print "\t\tThin Prov. Config.\t: "
				  . $san->child_get_string("thin-provisioning-configuration");
				print "\n";
			}
			my $srel = $ppi->child_get("storage-reliability");
			print "Availability Features:\n";
			print "\t\tStorage Sub-system Failure (aggr SyncMirror): "
			  . $srel->child_get_string("sub-system-failure");
			print "\n";
			print "\t\tStorage Controller Failure (active/active)  : "
			  . $srel->child_get_string("controller-failure");
			print "\n";
			print "\t\tDisk Failure Protection (RAID Level)        : "
			  . $srel->child_get_string("disk-failure");
			print "\n";
			print "\n";
			print
"===================================================================\n";
		}
	} elsif ( $subCommand eq "-t" ) { # List Data Protection policies
		my $pname = shift;

		my $in = NaElement->new("dp-policy-list-iter-start");
		if ( $pname ne "" ) {
			$in->child_add_string( "dp-policy-name-or-id", $pname );
		}
		my $out = $s->invoke_elem($in);
		if ( $out->results_status() eq "failed" ) {
			print( "Error : " . $out->results_reason() . "\n" );
			exit(-2);
		}

		my $in = NaElement->new("dp-policy-list-iter-next");
		$in->child_add_string( "maximum", $out->child_get_int("records") );
		$in->child_add_string( "tag",     $out->child_get_string("tag") );

		my $out = $s->invoke_elem($in);
		if ( $out->results_status() eq "failed" ) {
			print( "Error : " . $out->results_reason() . "\n" );
			exit(-2);
		}
		print "\nProtection Policies:\n";
		print
"===================================================================\n";
		my $dps = $out->child_get("dp-policy-infos");
		if ( $dps eq "" ) {
			print "Error: No Provisioning Policies!\n";
			exit;
		}
		my @dpInfo = $dps->children_get("dp-policy-info");
		foreach my $ppi (@dpInfo) {
			my $dpContent = $ppi->child_get("dp-policy-content");
			print "Policy Name\t: "
			  . $dpContent->child_get_string("name") . "\n";
			my $dpCons     = $dpContent->child_get("dp-policy-connections");
			my @dpConInfos = $dpCons->children_get("dp-policy-connection-info");
			foreach my $dpi (@dpConInfos) {
				if ( $dpi ne "" ) {
					print "-----------------------------------\n";
					print "Connection Type\t: "
					  . $dpi->child_get_string("type");
					print "\n";
					print "Source Node\t: "
					  . $dpi->child_get_string("from-node-name");
					print "\n";
					print "To Node\t\t: "
					  . $dpi->child_get_string("to-node-name");
					print "\n";
				}
			}
			print
"\n===================================================================\n";
		}
		print "\n";
		print
"===================================================================\n";
	} else {
		print_usage();
	}
} elsif ( $command eq "create" ) { # Create a new Provisioning Policy
	my $ppname = shift;
	my $pptype = shift;
	my $rtag   = shift;

	if ( $args < 7 ) {
		print_usage();
	}

	my $in  = NaElement->new("provisioning-policy-create");
	my $ppi = NaElement->new("provisioning-policy-info");
	$ppi->child_add_string( "provisioning-policy-name", $ppname );
	$ppi->child_add_string( "provisioning-policy-type", $pptype );
	$ppi->child_add_string( "resource-tag",             $rtag );

# Set default options for a NAS policy.  You can otherwise collect these 
# details on commandline or a config file
	if ( $pptype eq "nas" ) {
		my $nas = NaElement->new("nas-container-settings");
		$nas->child_add_string( "default-user-quota",  "1000000000" );
		$nas->child_add_string( "default-group-quota", "1000000000" );
		$nas->child_add_string( "thin-provision",      "true" );
		$nas->child_add_string( "snapshot-reserve",    "false" );
		$ppi->child_add($nas);
	} elsif ( $pptype eq "san" ) {
		# Set default options for a SAN policy.  You can otherwise collect 
		# these details on commandline or a config file
		my $san = NaElement->new("san-container-settings");
		$san->child_add_string( "storage-container-type", "volume" );
		$san->child_add_string( "thin-provision",         "true" );
		$ppi->child_add($san);
	}
	$in->child_add($ppi);

	my $out = $s->invoke_elem($in);
	if ( $out->results_status() eq "failed" ) {
		print( "Error : " . $out->results_reason() . "\n" );
		exit(-2);
	}
	print "New Provisioning Policy " 
	  . $ppname
	  . " created with ID : "
	  . $out->child_get_string("provisioning-policy-id") . "\n";
} elsif ( $command eq "destroy" ) {

	my $pname = shift;

	if ( $args < 5 ) {
		print_usage();
	}
	my $out = $s->invoke( "provisioning-policy-destroy",
		"provisioning-policy-name-or-id", $pname );
	if ( $out->results_status() eq "failed" ) {
		print( "Error : " . $out->results_reason() . "\n" );
		exit(-2);
	}
	print "Provisioning Policy " . $pname . " destroyed!\n";
} else {
	print_usage();
}
