#===============================================================#
#                                                               #
# $ID$                                                          #
#                                                               #
# resource_pool.rb                                              #
#                                                               #
# Copyright (c) 2011 NetApp, Inc. All rights reserved.          #
# Specifications subject to change without notice.              #
#                                                               #
# Sample code to demonstrate how to manage resource pool        #
# on a DFM server                                               #
# you can create,list and delete resource pools                 #
# add,list and remove members                                   #
#                                                               #
# This Sample code is supported from DataFabric Manager 3.6R2   #
# onwards.                                                      #
# However few of the functionalities of the sample code may     #
# work on older versions of DataFabric Manager.                 #
#===============================================================#

$:.unshift '../../../../../../lib/ruby/NetApp'
require 'NaServer'

def usage
    print ("Usage:\nresource_pool.rb <dfmserver> <user> <password> list [ <rpool> ]\n")
    print ("resource_pool.rb <dfmserver> <user> <password> delete <rpool>\n")
    print ("resource_pool.rb <dfmserver> <user> <password> create <rpool>  [ -t <rtag> ][-f <rp-full-thresh>] [-n <rp-nearly-full-thresh>]\n")
    print ("resource_pool.rb <dfmserver> <user> <password> member-add <a-mem-rpool> <member> [ -m mem-rtag ]\n")
    print ("resource_pool.rb <dfmserver> <user> <password> member-list <mem-rpool> [ <member> ]\n")
    print ("resource_pool.rb <dfmserver> <user> <password> member-remove <mem-rpool> <member>\n")
    print ("<dfmserver>             -- Name/IP Address of the DFM server\n")
    print ("<user>                  -- DFM server User name\n")
    print ("<password>              -- DFM server User Password\n")
    print ("<rpool>                 -- Resource pool name\n")
    print ("<rtag>                  -- resource tag to be attached to a resourcepool\n")
    print ("<rp-full-thresh>        -- fullness threshold percentage to generate a resource pool full event.Range: [0..1000]\n")
    print ("<rp-nearly-full-thresh> -- fullness threshold percentage to generate a resource pool nearly full event.Range: [0..1000]\n")
    print ("<a-mem-rpool>           -- resourcepool to which the member will be added\n")
    print ("<mem-rpool>             -- resourcepool containing the member\n")
    print ("<member>                -- name or Id of the member (host or aggregate)\n")
    print ("<mem-rtag>              -- resource tag to be attached to member\n")
    exit 
end


def create()
    # creating the input for api execution
    # creating a resourcepool-create element and adding child elements
    resource_input = NaElement.new("resourcepool-create")
    resourcepool = NaElement.new("resourcepool")
    resourcepoolinfo = NaElement.new("resourcepool-info")
    resourcepoolinfo.child_add_string( "resourcepool-name", $dfmval )
    resourcepoolinfo.child_add_string( "resource-tag", $resource_tag )
    resourcepoolinfo.child_add_string( "resourcepool-full-threshold", $full_thresh )
    resourcepoolinfo.child_add_string( "resourcepool-nearly-full-threshold", $nearly_full )
    resourcepool.child_add(resourcepoolinfo)
    resource_input.child_add(resourcepool)

    #invoking the api and printing the xml ouput
    output = $server.invoke_elem(resource_input)
    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
    end
    print ("\nResource pool creation Successful \n")
end


def resource_list()
    # invoking the api and capturing the ouput
    if ($dfmval)
        output = $server.invoke( "resourcepool-list-info-iter-start","object-name-or-id", $dfmval )
    else 
        output = $server.invoke("resourcepool-list-info-iter-start")
    end
    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
    end
    # Extracting the record and tag values and printing them
    records = output.child_get_string("records")
    tag = output.child_get_string("tag")
    if(records.to_i == 0)
        print("\nNo resourcepools to display\n")
        output = $server.invoke("resourcepool-list-info-iter-end", "tag", tag)
        exit
    end
    # Iterating through each record
    # Extracting records one at a time
    record = $server.invoke( "resourcepool-list-info-iter-next", "maximum", records, "tag", tag )
    if ( record.results_status() == "failed" )
        print( "Error : " + record.results_reason() + "\n" )
        exit
    end

    # Navigating to the resourcepools child element
    if(not record)
        exit
    else
        stat = record.child_get("resourcepools")
    end
    
    # Navigating to the resourcepool-info child element
    if(not stat)
        exit 
    else
        information = stat.children_get() 
    end
	
    # Iterating through each record
    information.each do |info|
        # extracting the schedule details and printing it
        print('-'*80 + "\n")
        print ("Resourcepool Name : " + info.child_get_string("resourcepool-name").to_s + "\n")
        print ("Resourcepool Id : "  + info.child_get_string("resourcepool-id").to_s + "\n")
        print ("Resource Description : " + info.child_get_string("resource-description").to_s + "\n")
        print ('-'*80 + "\n")

	# printing detials if only one resource-pool is selected for listing
        if ($dfmval) 
            print ("\nResourcepool Status                      : " + info.child_get_string("resourcepool-status").to_s + "\n")
            print ("Resourcepool Perf Status                 : " + info.child_get_string("resourcepool-perf-status").to_s + "\n")
            print ("Resource Tag                             : " + info.child_get_string("resource-tag").to_s + "\n")
            print ("Resourcepool Member Count                : " + info.child_get_string("resourcepool-member-count").to_s + "\n")
            print ("Resourcepool Full Threshold              : "+info.child_get_string("resourcepool-full-threshold").to_s+"%\n")
            print ("Resourcepool Nearly Full Threshold       : "+info.child_get_string("resourcepool-nearly-full-threshold").to_s+"%\n")
            print ("Aggregate Nearly Overcommitted Threshold : "+info.child_get_string("aggregate-nearly-overcommitted-threshold").to_s+"%\n")
            print ("Aggregate Overcommitted Threshold        : "+info.child_get_string("aggregate-overcommitted-threshold").to_s+"%\n")
		end
	end
	
    # invoking the iter-end zapi
    output = $server.invoke( "resourcepool-list-info-iter-end", "tag", tag )

    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
	end
end
    

def resource_del()
    # invoking the api and printing the xml ouput
    output = $server.invoke( "resourcepool-destroy", "resourcepool-name-or-id", $dfmval )

    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
	end
	
    print ("\nResource pool deletion Successful \n")
end


def member_add()
    # creating the input for api execution
    # creating a resourcepool add member element and adding child elements
    resource_input = NaElement.new("resourcepool-add-member")
    resource_input.child_add_string( "member-name-or-id", $dfmmem )
    resource_input.child_add_string( "resourcepool-name-or-id", $dfmval )

    if($mem_rtag)
		resource_input.child_add_string( "resource-tag", $mem_rtag ) 
	end
	
    # invoking the api and printing the xml ouput
    output = $server.invoke_elem(resource_input)

    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
	end

    print ("\nMember Add Successful \n")
end


def member_list() 
    # invoking the api and capturing the ouput
    if ($dfmmem) 
        output = $server.invoke("resourcepool-member-list-info-iter-start","resourcepool-member-name-or-id",$dfmmem, "resourcepool-name-or-id", $dfmval)
    else   
	output = $server.invoke( "resourcepool-member-list-info-iter-start","resourcepool-name-or-id", $dfmval )
    end
    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
    end
    # Extracting the record and tag values and printing them
    records = output.child_get_string("records")
    tag = output.child_get_string("tag")
    if(records.to_i == 0)
        output = $server.invoke("resourcepool-member-list-info-iter-end", "tag", tag)
        print ("\nNo members to display\n")
        exit
    end

    # Iterating through each record
    # Extracting records one at a time
    record = $server.invoke( "resourcepool-member-list-info-iter-next","maximum", records, "tag", tag )

    if ( record.results_status() == "failed" )
        print( "Error : " + record.results_reason() + "\n" )
        exit
	end
	
    # Navigating to the resourcepools member element
    if(not record)
        exit
    else
        stat = record.child_get("resourcepools")
    end
	   
    # Reading resourcepool-info child into array
    if(not stat)
        exit 
    else
        info = stat.children_get() 
    end
	
    # Iterating through each record
    info.each do |element|
        # extracting the member name and printing it
        name = element.child_get_string("member-name")
        resource_id = element.child_get_string("member-id")
        if ( not $dfmmem or ( $dfmmem and ( name == $dfmmem or resource_id == $dfmmem ) ) )
            print ('-'*80 + "\n")
            print ("Member Name : " +name +"\n")
            print ("Member Id : " +resource_id +"\n")
            print ('-'*80 + "\n")
	else 
	    print("Member "+$dfmmem+" not found")
            exit
	end
        # printing detials if only one member is selected for listing
        # This is a work around because list api wont return single child for
        # adding the member element
        if ( $dfmmem and ( name == $dfmmem or resource_id == $dfmmem))
            print ("\nMember Type            : " + element.child_get_string("member-type") + "\n")
            print ("Member Status          : " + element.child_get_string("member-status") + "\n")
            print ("Member Perf Status     : " + element.child_get_string("member-perf-status") + "\n")
            print ("Resource Tag           : " + element.child_get_string("resource-tag") + "\n")
            print ("Member Member Count    : " + element.child_get_string("member-member-count") + "\n")
            print ("Member Used Space      : " + element.child_get_string("member-used-space") + " bytes\n")
            print ("Member Committed Space : " + element.child_get_string("member-committed-space") + " bytes\n")
            print ("Member Size            : " + element.child_get_string("member-size") + " bytes\n")
	end
    end            

    # invoking the iter-end zapi
    output = $server.invoke( "resourcepool-member-list-info-iter-end", "tag", tag )

    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
    end
end


def member_rem() 
    # invoking the api and printing the xml ouput
    output = $server.invoke( "resourcepool-remove-member", "member-name-or-id", $dfmmem, "resourcepool-name-or-id", $dfmval )
    if ( output.results_status() == "failed" )
        print( "Error : " + output.results_reason() + "\n" )
        exit
    end
    print ("\nMember remove Successful \n")
end


args = ARGV.length
$resource_tag = nil
$full_thresh = nil
$nearly_full = nil
$mem_rtag = nil

if(args < 4 )
    usage() 
end

dfmserver = ARGV[0]
dfmuser = ARGV[1]
dfmpw = ARGV[2]
dfmop = ARGV[3]

if(args > 5)
    $dfmval = ARGV[4]
    opt_param = ARGV[5,ARGV.length]
    # extracting the member if its a member operation
	if(dfmop =~ /member/i)
	    $dfmmem = opt_param[0]
	end
elsif(args == 5)
    $dfmval = ARGV[4]
    $dfmmem = nil
else
    $dfmval = nil
    $dfmmem = nil
end

##### MAIN SECTION
# checking for valid number of parameters for the respective operations
if((dfmop == "list" and args < 4) or (dfmop == "delete" and args != 5) or (dfmop == "create" and args < 5) or (dfmop == "member-list" and args < 5) or (dfmop == "member-remove" and args != 6 ) or (dfmop == "member-add" and args < 6))
    usage()
end

# checking if the operation selected is valid
if((dfmop != "list") and (dfmop != "create") and (dfmop != "delete") and (dfmop != "member-add") and (dfmop != "member-list") and (dfmop != "member-remove"))
    usage()
end

# parsing optional parameters
i = 0
while (dfmop == "create" and args > 5 and i < opt_param.length )
    if(opt_param[i]  == '-t')
        i = i + 1
        $resource_tag  = opt_param[i]
        i = i + 1
    elsif(opt_param[i]  == '-f')
        i = i + 1
        $full_thresh = opt_param[i]
        i = i + 1
    elsif(opt_param[i]  == '-n' )
        i = i + 1
        $nearly_full  = opt_param[i]
        i = i + 1

    elsif(opt_param[i]  == '-m')
        i = i + 1      
        $mem_rtag  = opt_param[i]
        i = i + 1

    else 
        usage()
	end
end

# Creating a server object and setting appropriate attributes
$server = NaServer.new(dfmserver, 1, 0 )
$server.set_server_type('DFM')
$server.set_admin_user( dfmuser, dfmpw )

# Calling the subroutines based on the operation selected
if(dfmop == 'create')
    create()

elsif(dfmop == 'list')
    resource_list()

elsif(dfmop == 'delete')
    resource_del()

elsif(dfmop == 'member-add')
    member_add()

elsif(dfmop == 'member-list')
    member_list()

elsif(dfmop == 'member-remove')
    member_rem(serv)

else
    usage()
end


