# # Copyright (c) 2001-2017 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary Base class for all API Sets ## @author pressley@netapp.com, dl-nacl-dev@netapp.com ## @change 2014 rohit4@netapp.com, Added set=>SMTT support ## @status shared ## @pod here package NACL::APISet; # # Compiler Directives # use strict; use warnings; # Note that the required APISet packages will be imported dynamically at # run time. Refer the implementation in new() # Other module imports use NACL::APISet::Version; # NATE imports use NATE::Log qw(log_global); my $Log = log_global(); use Params::Validate qw(:all); use Data::Dumper; use NACL::APISet::_Mixins::CLI qw(_load_version_xml); use autouse 'STB::Util' => qw(is_non_netapp_site); # Exceptions imported use NATE::BaseException qw(:try); use NATE::Exceptions::Argument; use NACL::APISet::Exceptions::MissingSchema; use NACL::APISet::Exceptions::ConnectionFailedException; use NACL::APISet::Exceptions::MissingVersionManager; use NATE::ParamSet qw( param_global); my $nate_params = NATE::ParamSet->new(global => 1); BEGIN { Params::Validate::validation_options( on_fail => sub { NATE::Exceptions::Argument->throw(shift); } ); } use Class::MethodMaker [ scalar => [ { -read_cb => sub { $_[0]->{session}->timeout_scaling_factor }, -store_cb => sub { $_[0]->{session}->timeout_scaling_factor($_[1]); } }, 'timeout_scaling_factor' ], scalar => [ { -default_ctor => sub { return $_[0]->{hostobj} || $_[0]->{connection}->hostp(); } }, 'hostobj' ], scalar => [ {-static => 1}, 'no_set_command' ], ]; ############################################################################### # Method: new # Objective: Constructor to create new APISet object # Details: See POD documentation at the end of this file. ############################################################################### sub new { $Log->enter(); my ($proto, %args) = @_; my $class = ref($proto) || $proto; my $spec = $class->get_validation_spec(); # Set is NA for Eseries APISets, hence modifying the spec here $spec->{set}->{optional} = 1 if (defined $args{category} && $args{category} eq 'Eseries'); # Validate parameters and populate member variables my $self = $class->validate_params( params => \%args, spec => $spec, allow_extra => 0 ); if ($self->{set} eq 'SP') { # as per burt#1082720, use 'bmc_login' template for Aurora platform. # assuming AURORA testbeds do share common model: 'AFF-A700s' if ((defined $self->{hostobj}) && ($self->{hostobj}->{model} eq 'AFF-A700s')) { $self->{connid} = 'bmc_login'; } } # Bless the hash returned which will make it a Perl object bless $self, $class; # if vmapi then set shell type to set value if ($self->{interface} eq 'VMAPI') { $self->{shell_type} = $self->{set}; } # if xapi then set shell type to set value if ($self->{interface} eq 'XAPI') { $self->{shell_type} = $self->{set}; } # Keep the set for ESeries APIset as empty if ($self->{category} eq 'Eseries') { $self->{set} = ""; } # Here, $self is of type NACL::APISet. Later we will create the object # of the actual desired category, interface and set. We will need to # move back member attributes when we redefine self, so we move these # member variables into temporary variables. # #host and connection are mutually exclusive if ($self->{hostobj} && $self->{connection}) { $Log->exit(); NATE::Exceptions::Argument->throw("Method 'NACL::APISet->new' " . "parameters 'hostobj' and 'connection' are exclusive"); } if (!$self->{hostobj} && !$self->{connection}) { # This is to make it backwards compatible with the earlier syntax # of sending in 'name'. if ($self->{name}) { $self->hostobj(Tharn::host($self->{name})); # Delete the argument name from args, otherwise the check # for invalid parameters passed will fail delete $args{name}; } else { $Log->exit(); NATE::Exceptions::Argument->throw("Method 'NACL::APISet->new' " . "requires parameter 'hostobj' or parameter 'connection', but " . "both are missing"); } } ## end if (!$self->{hostobj} ... # If set is "Vfiler" or "Nodescope", then we can do Vfiler/Nodescope # specific things in future if the need arises. Currently if set is # "Vfiler" or "Nodescope", we will make use of the 7Mode APISet itself. # Same holds good for Vserver too but here we will return CMode APISet # object. my $actual_set = $self->{actual_set} = $self->{set}; # For GUI related api's versioning is implemented at "set" level. # Also versioning info cannot be retrieved from GUI,, hence it is # assumed that the version is part of the tharnhost object; my $hobj = $self->hostobj(); if ( ($self->{set} eq "Vfiler") || ($self->{set} eq "Nodescope") || ($self->{set} eq "NodescopeNGSH")) { $self->{set} = "7Mode"; } elsif (($self->{set} eq "Vserver")) { $self->{set} = "CMode"; } elsif (($self->{set} eq "Systemshell")) { $self->{category} = "Host"; $self->{set} = "Freebsd"; } elsif (($self->{set} eq "SystemshellNGSH")) { $self->{category} = "Host"; $self->{set} = "Freebsd"; } elsif (($self->{set} eq "Solaris")) { $self->{set} = "Linux"; } elsif ($self->{set} eq "SysManager_7Mode") { $self->{set} = "SysManager::7Mode"; } elsif ($self->{set} eq "SysManager_CMode") { $self->{set} = "SysManager::CMode"; } elsif ($self->{set} eq "HPUX") { $self->{set} = "Linux"; } elsif ($self->{set} eq "AIX") { $self->{set} = "Linux"; } elsif ($self->{set} eq "MarsRoot" || $self->{set} eq "AVARoot") { # If set is MarsRoot or AVARoot, redirect APISet to Host/CLI/Linux $self->{category} = "Host"; $self->{set} = "Linux"; } $self->_determine_cdef_path(); my ($prompt_user, $prompt_password); $self->_set_context_definition( actual_set => $actual_set, prompt_user => \$prompt_user, prompt_password => \$prompt_password, ); unless (defined($self->{shell_type})) { $self->_find_shell_type(); } my $interface = $self->{interface}; my $set = $self->{set}; my $version = $self->{version}; my $category = $self->{category}; my $connection = $self->{connection}; my $cdef_path = $self->{cdef_path}; my $hostobj = $self->hostobj(); my $shell_type = $self->{shell_type}; my $context_definition = $self->{context_definition}; my $version_info = $self->{version_info}; my $snmp_auth = $self->{snmp_auth}; my $privilege_level = $self->{'privilege-level'}; # # Now, we separate the arguments into those required for: # 1. Version Object creation # 2. Session overrides # 3. Versioning specific overrides # # # We populate individual hashes for the different types of arguments # my @object_creation_fields = qw(category hostobj); my %object_creation_params = $self->_populate_hash(@object_creation_fields); # If users had passed a connection object, then get the hostobj from it # and send it to versioning. unless (defined $object_creation_params{hostobj}) { $object_creation_params{hostobj} = $self->{connection}->hostp(); } # Pass appropriate shell_type as expected by versioning # # Pass the actual category specified by the user. In case of # Systemshell/SystemshellNGSH, category is changed from "Node" to "Host" # So we'll change it back to "Node" for versioning. $object_creation_params{category} = "Node" if (($self->{actual_set} eq "Systemshell") or ($self->{actual_set} eq "SystemshellNGSH")); # By default, shell_type will be same as "set" $object_creation_params{shell_type} = $self->{set}; # Do other processing for shell-type to be sent for versioning if ($object_creation_params{category} eq "Node") { $object_creation_params{shell_type} = $self->{shell_type}; if (defined $connection && $connection->is_console()) { # Set the console connection in the version manager object if # version manager was passed as a parameter while APISet creation. if (defined $self->{version_info}->{version_manager}) { $self->{version_info}->{version_manager} ->console_connection($connection) unless ($self->{version_info}->{version_manager} ->console_connection_isset()); } else { # Pass the console connection object to version manager so # that it can reuse the same $object_creation_params{console_connection} = $connection; } } } my @conn_overrides_fields = $self->get_conn_override_fields(); my %conn_overrides_params = $self->_populate_hash(@conn_overrides_fields); # Keep conn overrides for versioning and apiset object separately as in the # case of direct connection to systemshell, the list of overrides will # differ my %version_conn_overrides = %conn_overrides_params; my %session_conn_overrides = %conn_overrides_params; # For set being "systemshell", if the connid override supplied by the # user is not "7-system" or "c-system", then its a direct connection # to systemshell. # Then connection overrides shouldn't be passed to versioning. Also the # password override should be considered as prompt_password incase of # direct connection to systemshell. The actual username and password to # login to ngshell/7mode shell will be obtained from hostobj fields if ( ($self->{actual_set} eq "Systemshell") && (defined $self->{connid}) && ($self->{connid} ne "7-system") && ($self->{connid} ne "c-system")) { foreach my $override (qw(username password conntype connid)) { delete $version_conn_overrides{$override}; } # The password override should be considered as prompt_password $version_conn_overrides{'prompt_password'} = $self->hostobj()->{conn}->{$self->{connid}}->{password}; $version_conn_overrides{'prompt_password'} = $self->{password} if (defined $self->{password}); } ## end if (($self->{actual_set... # Below code is only required when login connection is missing in nate_host file for MarsRoot if ($self->{actual_set} eq "MarsRoot") { $conn_overrides_params{username} = "root" if (!defined $self->hostobj()->{conn}->{login}->{username}); $conn_overrides_params{password} = "netapp1!" if (!defined $self->hostobj()->{conn}->{login}->{password}); $conn_overrides_params{conntype} = "libssh-persay"; $conn_overrides_params{connid} = "login"; } # Below code is only required when login connection is missing in nate_host file for AVARoot if ($self->{actual_set} eq "AVARoot") { $conn_overrides_params{username} = "root" if (!defined $self->hostobj()->{conn}->{login}->{username}); $conn_overrides_params{conntype} = "ssh-persist"; $conn_overrides_params{connid} = "system"; } if (scalar keys(%conn_overrides_params) and ($self->{connection})) { NATE::Exceptions::Argument->throw("Method 'NACL::APISet->new' takes " . "either parameter 'connection' or connection overrides but " . " parameter(s) " . join(" ", keys(%conn_overrides_params)) . " were provided along with parameter 'connection'"); } # Pass in a special set of parameters for SOAP interfaces if ($self->{interface} eq 'SOAP') { my @soap_override_fields = qw(port url base_path); if ($self->{set} eq 'VPserver') { my @vpserver_override_fields = qw(include_credential credential); push(@soap_override_fields, @vpserver_override_fields); } my %soap_overrides_params = $self->_populate_hash(@soap_override_fields); foreach my $key (keys %soap_overrides_params) { $conn_overrides_params{$key} = $soap_overrides_params{$key}; } } # for the Service Processor, pass in a special set of fields in if ($set eq 'SP') { if (defined($self->{login_to_console})) { $conn_overrides_params{'login_to_console'} = $self->{login_to_console}; } } # Pass context_definition input to session $conn_overrides_params{"context_definition"} = $self->{context_definition}; $conn_overrides_params{"prompt_username"} = $version_conn_overrides{"prompt_username"} = $prompt_user; $conn_overrides_params{"prompt_password"} = $version_conn_overrides{"prompt_password"} = $prompt_password; # versioning is not using SNMP and hence populate the SNMP related # constructor inputs only in conn overrides for APISet. $conn_overrides_params{'snmp_auth'} = $snmp_auth if (defined $snmp_auth); ## Create the APISet object of appropriate type. ## # Create a package path like "NACL::APISet::Node::CLI::7Mode" my $api_pkg; # For Eseries there is no 'set, hence making the below check if ($self->{category} =~ /Eseries/) { $api_pkg = "NACL::APISet::" . $category . "::" . $interface; } else { $api_pkg = "NACL::APISet::" . $category . "::" . $interface . "::" . $set; } # In the case of an invalid category or interface being passed # the relevant package will not be found. In case there is an error, # an argument exception is thrown. eval "use $api_pkg"; if ($@) { my $error = $@ ; my $package_path = $self->{version_info}->{version_manager}->{build_path}."test/lib/NACL/APISet/${category}/${interface}/${set}.pm"; $Log->comment( sub { "The not found package path is:" . $package_path }) ; $Log->comment( sub { "The not found package name is:" . $api_pkg }) ; if($^O !~ /Win/i){ $Log->comment( sub { "The ls command o/p is :"}); system("ls $package_path"); } $Log->exit(); NATE::Exceptions::Argument->throw('Invalid value provided for ' . "category ('$category'), interface ('$interface') or " . "set ('$set'). $error"); } # $api_set_obj is an object of the actual category, interface and set # $self was originally of type NACL::APISet, now we need to re-bless # it to the type of the actual object created. bless $self, $api_pkg; # Invoke _init_Session which establishes the session and stores the # created session object in APISet object. # At times, especially for Components, the version manager object is # created and a session is established, and then the APISet->new() is # invoked. In such cases, it is better to use the the already established # session object rather than creating a new one again. my $key = lc $interface . "_" . lc $self->{actual_set}; if (!(scalar keys(%session_conn_overrides) || $self->{connection})) { if (defined $self->{version_info}->{version_manager} && $self->{version_info}->{version_manager} ->session_object_exists($key)) { $self->{session} = $self->{version_info}->{version_manager} ->session_object_index($key); } else { $self->_init_Session(%conn_overrides_params); $object_creation_params{session_object}{$key} = $self->{session}; } } else { $self->_init_Session(%conn_overrides_params); } if ($interface eq 'SNMP' || $category eq "Eseries") { # SNMP Session object contains a connection object of type Net::SNMP # Hence reusing the connection only if the user has explicitly # provided the connection object while creating the APISet. $object_creation_params{cli_connection} = $connection if (defined $connection); } elsif (defined $self->{session}->{connection} && !exists $object_creation_params{console_connection} && ($self->{actual_set} ne "Systemshell") && ($self->{shell_type} ne "Vfiler") && ($self->{interface} ne "SOAP") && ($self->{actual_set} ne 'Nodescope')) { my $cli_connection = $self->{session}->{connection}; # If version_manager is passed to the APISet constructor, set the # cli_connection if (defined $self->{version_info}->{version_manager}) { $self->{version_info}->{version_manager} ->cli_connection($cli_connection) unless ($self->{version_info}->{version_manager} ->cli_connection_isset()); } else { $object_creation_params{cli_connection} = $cli_connection; } } ## Create the version manager object, discover the version related ## attributes and then map the version string to appropriate cdef path ## # Always make call to NACL::APISet::Version->new() which will in turn # return an appropriate version manager object based on category, set and # shell_type. # Initiate a Version manager object irrespective of whether an user has # passed CDEF path or not. This will allow them to obtain various version # related attributes, override the values or reload the CDEF based on # updated version attributes. # If the version manager object is already passed by the user, then we # don't have to create one. my ($version_manager, $perform_compatibility); # Compatibility will be performed by default. But if version manager object # creation fails, then compatibility will be disabled. $perform_compatibility = (defined $self->{version_info}->{compatibility}) ? $self->{version_info}->{compatibility} : 1; if (defined $self->{version_info}->{version_manager}) { $version_manager = $self->{version_info}->{version_manager}; NATE::Exceptions::Argument->throw( "Invalid version manager object of" . " type " . ref($version_manager) . " sent.") unless ($version_manager->isa("NACL::APISet::Version")); $Log->debug("Version manager is provided by the user"); $self->{version_manager} = $version_manager; } ## end if (defined $self->{version_info... if ($self->_is_versioning_needed()) { unless (defined $version_manager) { try { # version manager will not be created for the list of category # and shell_type which are not supported by version manager to # avoid the warning in the logs. if (( $object_creation_params{shell_type} !~ /(Firmware|Maintenance|SP|SPShell|Armadillo)/ && ($set !~ /Windows|SMO|SQL|PowerShell|Kerberos|QlogicFC|DellEthernet/ ) ) || ($set =~ /DFM/) ) ## end { $Log->debug("Creating the version manager object"); $version_manager = NACL::APISet::Version->new(%object_creation_params, conn_overrides => \%version_conn_overrides); } } ## end try catch NATE::BaseException with { # catching the exception so that error in creating version object will # not prevent the APISet object creation my $exception = shift; $perform_compatibility = 0; my $message = "Error in creating the version object: " . $exception->text() . "\nBut still continuing with APISet object " . "creation. "; $message .= "Also compatibility will not be performed." if (($interface eq "CLI") && ($set eq "CMode")); $Log->warn($message); }; } ## end unless (defined $version_manager) } ##end if (!$isvmapi) # set the version manager object in apiset object $self->{version_manager} = $version_manager; $self->{version_info} = $version_info; $self->{version_info}->{compatibility} = $perform_compatibility; $Log->debug("After creation of APIset object, perform compatibility" . " status(0/1): " . $perform_compatibility); # At this point, we would have created version object. If cdef_path # override is provided, don't do any discovery. if ($self->_need_to_load_cdefs()) { my @cdef_paths; my $path = NATE::Inc::find_file( $self->{cdef_path} ) if (defined $cdef_path ); my $path_not_found ; if (! defined $path && (defined param_global->get('CDEFS_FROM_LOCAL') || is_non_netapp_site())) { $path_not_found = 1; $self->{version_info}->{cdefs_from_build} = 0; } if ( ! defined $cdef_path || $path_not_found ){ @cdef_paths = $self->find_cdef_directory(); $cdef_path = join(';', @cdef_paths); $Log->debug("CDEF directory autodiscovered: " . $cdef_path); } $Log->comment("CDEF directory to be loaded: " . $cdef_path); unless (defined $cdef_path) { NATE::Exceptions::Argument->throw("Internal error in APIlayer: " . "CDEF Path couldn't be auto-discovered"); } $self->{cdef_path} = $cdef_path; } # Call _init_API to initialize the APISet $self->_init_API(%conn_overrides_params); $self->timeout_scaling_factor( Tharn::param("APISET_TIMEOUT_SCALING_FACTOR")) if defined Tharn::param("APISET_TIMEOUT_SCALING_FACTOR"); $Log->exit(); return $self; } # end new() ############################################################################## # Method: _set_context_definition # Objective: Sets the 'context_definition' parameters passed in the APISet # constructor on the appropriate object ############################################################################### sub _set_context_definition { my ($self, @opts) = @_; $Log->enter(); my %args = $self->validate_params( params => \@opts, spec => { actual_set => {type => SCALAR}, prompt_user => {type => SCALARREF | UNDEF, optional => 1}, prompt_password => {type => SCALARREF | UNDEF, optional => 1}, } ); my $actual_set = $args{actual_set}; my $prompt_user = $args{prompt_user}; my $prompt_password = $args{prompt_password}; if ( (!defined $self->{context_definition}) || (scalar(keys %{$self->{context_definition}}) == 0)) { if (($actual_set eq "Vfiler") || ($actual_set eq "Vserver")) { $self->{shell_type} = $actual_set; # The "name" parameter should be overriden to "" or else it will # take the hostid of shell host and prefix it with the commands # which will fail the commands when its directly connected to a # vfiler or vserver. $self->{context_definition}->{name} = ""; } if ($actual_set eq "Nodescope") { if ($self->{interface} eq "CLI") { # Before we assign hostobj as schema_hostobj by default, set the # name of the node as "local". Burt446959 $self->{context_definition}->{name} = "local"; } } ## end if ($actual_set eq "Nodescope") } ## end if ((!defined $self->{... # If context_definition hash is not defined, then it implies that # both shell_host and schema_host are the same. if ( (!defined $self->{context_definition}) || (scalar(keys %{$self->{context_definition}}) == 0)) { $self->{context_definition}->{schema_hostobj} = $self->hostobj(); } else { # Get the prompt_username and prompt_password now so that we can # leave the job of assigning defaults to those fields to connection # layer if context_definition is not specified. if ($actual_set eq "Systemshell" || $actual_set eq "Kerberos") { my $schema_host = $self->{context_definition}->{schema_hostobj}; if (defined($schema_host)) { $$prompt_user = $schema_host->default_username(); $$prompt_password = $schema_host->default_password(); } # If overrides are passed, use them for prompt_username and # prompt_password if (defined($self->{context_definition}->{username})) { $$prompt_user = $self->{context_definition}->{username}; } if (defined($self->{context_definition}->{password})) { $$prompt_password = $self->{context_definition}->{password}; } } ## end if ($actual_set eq "Systemshell") } $Log->exit(); } ## end sub _set_context_definition sub get_default_cdef_dir_list { $Log->enter(); my $pkg_or_obj = shift(); my $is_optional = (ref $pkg_or_obj) ? 1 : 0; my %args = $pkg_or_obj->validate_params( params => \@_, spec => { category => {type => SCALAR, optional => $is_optional}, interface => {type => SCALAR, optional => $is_optional}, set => {type => SCALAR, optional => $is_optional}, } ); my $get_value = sub { my $param = shift; return (defined $args{$param}) ? lc($args{$param}) : lc($pkg_or_obj->{$param}); }; my $category = $get_value->('category'); my $interface = $get_value->('interface'); my $set = $get_value->('set'); # Get the XPath object my $libxml_obj = $pkg_or_obj->_load_version_xml(); my @cdef_dir = $pkg_or_obj->_read_default_cdef_dir( category => $category, interface => $interface, set => $set, libxml_obj => $libxml_obj, ); return @cdef_dir; } ## end sub get_default_cdef_dir_list sub _read_default_cdef_dir_spec { return { category => {type => SCALAR,}, interface => {type => SCALAR,}, set => {type => SCALAR,}, libxml_obj => {type => SCALARREF,}, }; } ## end sub _read_default_cdef_dir_spec sub _read_default_cdef_dir { $Log->enter(); my $pkg_or_obj = shift(); my %args = $pkg_or_obj->validate_params( params => \@_, spec => $pkg_or_obj->_read_default_cdef_dir_spec, ); # This is the base class definition for the APISets which don't have # their customized definition of this method which finds the default # cdef dir which would be the choice of CDEF discovery logic if there is # no versioning info. my $cdef_dir = $args{libxml_obj}->find( "/version/$args{category}/$args{interface}/$args{set}/default_cdef_dir" )->string_value; $Log->exit(); return ($cdef_dir); } ## end sub _read_default_cdef_dir sub _read_shared_cdef_dir { my ($pkg_or_obj, %args) = @_; $Log->enter(); my $libxml_obj = $args{libxml_obj}; my @cdef_paths; # Get cdefs common to INTERFACE my $cdefs_common_to_interface = $libxml_obj->find( "/version/$args{category}/$args{interface}/default_cdef_dir") ->string_value; if ($cdefs_common_to_interface ne "") { push(@cdef_paths, $cdefs_common_to_interface); } # Get cdefs common to Unix if ($args{set} =~ /Linux|Solaris|Freebsd|HPUX|AIX/i) { my $cdefs_common_to_unix = $libxml_obj->find( "/version/$args{category}/$args{interface}/unix")->string_value; if ($cdefs_common_to_unix ne "") { push(@cdef_paths, $cdefs_common_to_unix); } } # Get cdefs common to SET my $cdefs_common_to_set = $libxml_obj->find( "/version/$args{category}/$args{interface}/$args{set}/default_cdef_dir" )->string_value; if ($cdefs_common_to_set ne "") { push(@cdef_paths, $cdefs_common_to_set); } # Get cdefs common to OS Major revision if (defined($pkg_or_obj->{version_manager}) && $pkg_or_obj->{version_manager}->can("_find_os_revision")) { $pkg_or_obj->{version_manager} ->get_version_attribute(attribute => "os_revision"); my $major = (defined $pkg_or_obj->{version_manager}->{os_revision}->{major}) ? lc($pkg_or_obj->{version_manager}->{os_revision}->{major}) : ""; my $minor = (defined $pkg_or_obj->{version_manager}->{os_revision}->{minor}) ? lc($pkg_or_obj->{version_manager}->{os_revision}->{minor}) : ""; if ($major ne "") { my $path_major = $libxml_obj->find( "/version/$args{category}/$args{interface}/$args{set}/$major/default_cdef_dir" )->string_value; if ($path_major ne "") { push(@cdef_paths, $path_major); } # Get cdefs common to OS Minor revision if ($minor ne "") { $minor = "$major.$minor"; my $path_minor = $libxml_obj->find( "/version/$args{category}/$args{interface}/$args{set}/$major/$minor" )->string_value; if ($path_minor ne "") { push(@cdef_paths, $path_minor); } } } } $Log->debug("CDEF directories found are:\n" . Dumper(\@cdef_paths)); $Log->exit(); # Paths are listed in the order of precedence as the schema will not # overwrite the entry which is already present return @cdef_paths; } ## end sub _read_shared_cdef_dir ############################################################################### # Method: _find_cdef_directory # Objective: To find the various version related attributes for discovering # CDEF directory # Details: This method gets the information of various version related # attributes which will vary depending on the category and set and returns a # hash whose keys are the attribute names and whose values are the corresponding # values for those attributes. This method will be invoked by the # find_cdef_directory() method defined in the subclasses ############################################################################### sub _find_cdef_directory { $Log->enter(); my $self = shift(); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => { required_attributes => {type => ARRAYREF, optional => 0}, set_lowercase => {type => BOOLEAN, optional => 0, default => 0}, } ); my @attributes = @{$args{required_attributes}}; my %info; # Discover the required attributes foreach my $attribute (@attributes) { try { my $attr = $self->{version_manager} ->get_version_attribute(attribute => $attribute); $info{$attribute} = ($args{set_lowercase}) ? lc($attr) : $attr; $Log->debug("Discovery: $attribute => $info{$attribute}"); } catch NATE::BaseException with { # catch all the exceptions so that we can carry on with asking # version to find other attributes if any. my $exception = shift; $Log->comment( "Versioning has failed while trying to discover the attribute" . " '$attribute'."); }; } ## end foreach my $attribute (@attributes) $Log->exit(); return \%info; } ## end sub _find_cdef_directory ############################################################################### # Method Name: get_name # Objective: Return stored resource name # Details: See POD documentation at the end of this file. ############################################################################### sub get_name { $Log->enter(); my $self = shift; $Log->exit(); return $self->hostobj->id(); } ## end sub get_name ############################################################################### # Method Name: get_cdef_path # Objective: Return the cdef dir path used by the APISet object # Details: See POD documentation at the end of this file. ############################################################################### sub get_cdef_path { $Log->enter(); my $self = shift(); unless (defined $self->{cdef_path}) { # If APISet object is created successfully without populating CDEF # path, then it implies that the APISet object doesn't need CDEF for # its operation $Log->exit(); NATE::BaseException->throw( "CDEF path is not supported for " . ref($self)); } my $path = $self->{cdef_path}; my @paths; unless (ref $path) { @paths = ($path); } else { @paths = @{$path}; } $Log->exit(); return @paths; } ## end sub get_cdef_path ############################################################################## # Method: set_return_option # Objective: To set the return option for execute_raw_command of ZAPI & SNMP # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_return_option { $Log->enter(); my $self = shift(); NATE::BaseException->throw("Return option for execute_raw_command can " . "only be set for ZAPI or SNMP") if ($self->{interface} !~ /^(ZAPI|SNMP)$/); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {'return-response-object' => {type => SCALAR, optional => 0}} ); $self->{'return-response-object'} = ($args{'return-response-object'}) ? 1 : 0; $Log->exit(); } ## end sub set_return_option ############################################################################## # Method: get_return_option # Objective: To get the return option for execute_raw_command of ZAPI & SNMP # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_return_option { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "get_return_option() can only be invoked on a ZAPI or SNMP " . "APISet object") if ($self->{interface} !~ /^(ZAPI|SNMP)$/); my $opt = (defined $self->{'return-response-object'}) ? $self->{'return-response-object'} : 0; $Log->exit(); return $opt; } ## end sub get_return_option ############################################################################## # Method: clear_return_option # Objective: To set the defaults for return_option of execute_raw_command in # ZAPI & SNMP # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_return_option { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "clear_return_option() can only be invoked on " . "a ZAPI or SNMP APISet object") if ($self->{interface} !~ /^(ZAPI|SNMP)$/); $self->{'return-response-object'} = 0; $Log->exit(); } ## end sub clear_return_option ############################################################################## # Method: reinit # Objective: To reinit the teared down session because of rebooting # Details: See POD documentation at the end of this file. ############################################################################## sub reinit { my ($self, %args) = @_; $Log->enter(); $self->{session}->prep_service(); $Log->exit(); } ## end sub reinit ############################################################################## # Method: api_is_session_alive # Objective: To find out if the current session is alive # (applicable only for persistent connections - CLI ) # Details: See POD documentation at the end of this file. ############################################################################## sub api_is_session_alive { my ($self) = @_; $Log->enter(); my $is_alive = 1; # the connectrec object if ($self->{interface} eq 'CLI') { my $c = $self->get_connection(); $is_alive = $c->is_connected(); # is_connected is not enough to detect whether a filer is # in usable state or not. Hence we check for the prompts also. if ($is_alive) { eval { $c->execute(command => " "); }; if ($@) { $is_alive = 0; } } } $Log->exit(); return $is_alive; } ## end sub api_is_session_alive ############################################################################## # Method: api_reconnect_session # Objective: Reestablish session # Details: See POD documentation at the end of this file. ############################################################################## sub api_reconnect_session { $Log->enter(); my ($self, @args) = @_; my %opts = validate_with( params => \@args, spec => { max_reconnect => {type => SCALAR, optional => 1}, max_reconnect_timewait => {type => SCALAR, optional => 1}, } ); if ($self->{interface} eq 'CLI') { my $conn = $self->{session}->{connection}; $self->{session}->_reconnect( max_reconnect => $opts{max_reconnect}, max_reconnect_timewait => $opts{max_reconnect_timewait} ); ref($self->{session})->new(connection => $conn); # so that the service is back to the same privilege level # that existed before api_reconnect_session was called $self->set_privilege('privilege-level' => $self->get_privilege()) if $self->can('set_privilege'); } $Log->exit(); } ## end sub api_reconnect_session ## end sub api_reconnect_session sub cleanup_APISet { $Log->warn('Usage of cleanup_APISet is deprecated. Cleanup of the ' . 'APISet is handled automatically, so this call should be removed' ); } ############################################################################## # Method: get_command_definition # Objective: To obtain the command definition object of a particular command # Details: See POD documentation at the end of this file. ############################################################################## sub get_command_definition { my ($self, %args) = @_; $Log->enter(); my $cdef = $self->get_schema_obj() ->get_command_definition(command => $args{command}); $Log->exit(); return $cdef; } ## end sub get_command_definition ############################################################################## # Method: get_connection # Objective: To obtain the connection object created by the APISet # Details: See POD documentation at the end of this file. ############################################################################## sub get_connection { my ($self, %args) = @_; $Log->enter(); my $conn = $self->{session}->{connection}; unless (defined $conn) { my $error = "Failed to get connection object. "; $error .= "Connection object could be obtained only for CLI interface." if ($self->{interface} ne "CLI"); $Log->exit(); NATE::BaseException->throw($error); } $Log->exit(); return $conn; } ## end sub get_connection ############################################################################## # Method: validate_params # Objective: Validate the passed parameters # Details: This is an APISet-specific wrapper around # Params::Validate::validate_with(). It returns the validated # parameters. If one or more of the parameters are found to be # invalid, it throws an appropriate exception. ############################################################################## sub validate_params { $Log->enter(); my ($class, %args) = @_; my $allow_extra = defined($args{allow_extra}) ? $args{allow_extra} : 1; $Log->exit(); return validate_with(%args, allow_extra => $allow_extra,); } ## end sub validate_params ############################################################################## # Method: clear_timeout # Objective: Sets timeout to the default value (currently 60s) # Details: See POD documentation at the end of this file. ############################################################################## sub clear_timeout { my $self = shift; $Log->enter(); $self->{session}->clear_timeout(); $Log->debug("Timeout set to default"); $Log->exit(); } ## end sub clear_timeout ############################################################################## # Method: get_schema_obj # Objective: Return the Schema object # Details: See POD documentation at the end of this file. ############################################################################## sub get_schema_obj { my ($self, %args) = @_; $Log->enter(); $Log->exit(); # Throw an exception if we don't have a schema object NACL::APISet::Exceptions::MissingSchema->throw( "Failed to get schema object") unless ($self->{schema}); return $self->{schema}; } ## end sub get_schema_obj ############################################################################## # Method: get_timeout # Objective: Retrieve the current timeout value # Details: See POD documentation at the end of this file. ############################################################################## sub get_timeout { my $self = shift; $Log->enter(); $Log->exit(); return $self->{session}->get_timeout(); } ## end sub get_timeout ############################################################################## # Method: set_timeout # Objective: Set timeout to a new value (in seconds) # Details: See POD documentation at the end of the file. ############################################################################## sub set_timeout { my ($self, %args) = @_; $Log->enter(); $self->{session}->set_timeout(%args); $Log->exit(); } ## end sub set_timeout ############################################################################## # Method: get_version_manager # Objective: Retrieve the created version object # Details: See POD documentation at the end of this file. ############################################################################## sub get_version_manager { my $self = shift; $Log->enter(); my $version_manager = $self->{version_manager}; unless (defined $version_manager) { NACL::APISet::Exceptions::MissingVersionManager->throw( "Version object cannot be found"); } $Log->exit(); return $version_manager; } ## end sub get_version_manager ############################################################################## # Method: set_transport_type # Objective: To set the transport type for ZAPI execution # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_transport_type { $Log->enter(); my $self = shift(); NATE::BaseException->throw("Transport type can only be set for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"type" => {type => SCALAR, optional => 0}} ); my $t = $args{"type"}; NATE::Exceptions::Argument->throw( "Valid transport types are HTTP and " . "HTTPS") if ($t !~ /^HTTP[s]?$/i); $self->{session}->{transport_type} = $t; $Log->exit(); } ## end sub set_transport_type ############################################################################## # Method: set_ssl_cert_verification # Objective: To set the user's certificate for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_ssl_cert_verification { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "ssl_cert_verification can only be done for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"ssl_cert_verification" => {type => SCALAR, optional => 0}} ); $self->{session}->ssl_cert_verification($args{"ssl_cert_verification"}); $Log->exit(); } ## end sub set_ssl_cert_verification ############################################################################## # Method: set_hostname_verification # Objective: To set the user's certificate for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_hostname_verification { $Log->enter(); my $self = shift(); NATE::BaseException->throw("SSL Host cert file is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"hostname_verification" => {type => SCALAR, optional => 0}} ); $self->{session}->hostname_verification($args{"hostname_verification"}); $Log->exit(); } ## end sub set_hostname_verification ############################################################################## # Method: set_key_password # Objective: To set the user's certificate for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_key_password { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "SSL Host key password file is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"key_password" => {type => SCALAR, optional => 0}} ); $self->{session}->key_password($args{"key_password"}); $Log->exit(); } ## end sub set_key_password ############################################################################## # Method: set_ca_cert_file # Objective: To set the user's certificate for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_ca_cert_file { $Log->enter(); my $self = shift(); NATE::BaseException->throw("SSL server cert file is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"ca_cert_file" => {type => SCALAR, optional => 0}} ); $self->{session}->ca_cert_file($args{"ca_cert_file"}); $Log->exit(); } ## end sub set_ca_cert_file ############################################################################## # Method: set_key_file # Objective: To set the user's certificate for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_key_file { $Log->enter(); my $self = shift(); NATE::BaseException->throw("SSL Host private key is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"key_file" => {type => SCALAR, optional => 0}} ); $self->{session}->key_file($args{"key_file"}); $Log->exit(); } ## end sub set_key_file ############################################################################## # Method: set_cert_file # Objective: To set the user's certificate for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_cert_file { $Log->enter(); my $self = shift(); NATE::BaseException->throw("SSL Host cert file is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"cert_file" => {type => SCALAR, optional => 0}} ); $self->{session}->cert_file($args{"cert_file"}); $Log->exit(); } ## end sub set_cert_file ############################################################################## # Method: set_originator_id # Objective: To set originator id for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_originator_id { $Log->enter(); my $self = shift(); NATE::BaseException->throw("SSL Host cert file is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"originator_id" => {type => SCALAR, optional => 0}} ); $self->{session}->originator_id($args{"originator_id"}); $Log->exit(); } ## end sub set_originator_id ############################################################################## # Method: set_trace_threshold # Objective: To set trace threshold value for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_trace_threshold { $Log->enter(); my $self = shift(); NATE::BaseException->throw("SSL Host cert file is only needed for ZAPI") if ($self->{interface} ne "ZAPI"); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => {"trace_threshold" => {type => SCALAR, optional => 0}} ); $self->{session}->trace_threshold($args{"trace_threshold"}); $Log->exit(); } ## end sub set_trace_threshold ############################################################################## # Method: get_cert_file # Objective: To get the user cert file for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_cert_file { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->cert_file; } ## end sub get_cert_file ############################################################################## # Method: get_key_file # Objective: To get the user cert file for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_key_file { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->key_file; } ## end sub get_key_file ############################################################################## # Method: get_ca_cert_file # Objective: To get the user cert file for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_ca_cert_file { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->ca_cert_file; } ## end sub get_ca_cert_file ############################################################################## # Method: get_key_password # Objective: To get the user cert file for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_key_password { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->key_password; } ## end sub get_key_password ############################################################################## # Method: get_ssl_cert_verification # Objective: To get the user cert file for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_ssl_cert_verification { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->ssl_cert_verification; } ## end sub get_ssl_cert_verification ############################################################################## # Method: get_hostname_verification # Objective: To get the user cert file for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_hostname_verification { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->hostname_verification; } ## end sub get_hostname_verification ############################################################################## # Method: get_originator_id # Objective: To get the originator id for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_originator_id { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->originator_id; } ## end sub get_originator_id ############################################################################## # Method: get_trace_threshold # Objective: To get the trace threshold value for SSL authentication # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_trace_threshold { $Log->enter(); my $self = shift(); $Log->exit(); return $self->{session}->trace_threshold; } ## end sub get_trace_threshold ############################################################################## # Method: clear_cert_file # Objective: Will reset user's certificate file # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_cert_file { $Log->enter(); my $self = shift(); $self->{session}->cert_file_reset(); $Log->exit(); } ## end sub clear_cert_file ############################################################################## # Method: clear_key_file # Objective: Will reset user's private key file # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_key_file { $Log->enter(); my $self = shift(); $self->{session}->key_file_reset(); $Log->exit(); } ## end sub clear_key_file ############################################################################## # Method: clear_ca_cert_file # Objective: Will reset server's certificate file # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_ca_cert_file { $Log->enter(); my $self = shift(); $self->{session}->ca_cert_file_reset(); $Log->exit(); } ## end sub clear_ca_cert_file ############################################################################## # Method: clear_key_password # Objective: Will reset user's private key password # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_key_password { $Log->enter(); my $self = shift(); $self->{session}->key_password_reset(); $Log->exit(); } ## end sub clear_key_password ############################################################################## # Method: clear_ssl_cert_verification # Objective: Will reset value of ssl_cert_verification # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_ssl_cert_verification { $Log->enter(); my $self = shift(); $self->{session}->ssl_cert_verification_reset(); $Log->exit(); } ## end sub clear_ssl_cert_verification ############################################################################## # Method: clear_hostname_verification # Objective: Will reset hostname verification # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_hostname_verification { $Log->enter(); my $self = shift(); $self->{session}->hostname_verification_reset(); $Log->exit(); } ## end sub clear_hostname_verification ############################################################################## # Method: clear_originator_id # Objective: To reset the originator id # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_originator_id { $Log->enter(); my $self = shift(); $self->{session}->originator_id_reset(); $Log->exit(); } ## end sub clear_originator_id ############################################################################## # Method: clear_trace_threshold # Objective: To reset the trace threshold # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_trace_threshold { $Log->enter(); my $self = shift(); $self->{session}->trace_threshold_reset(); $Log->exit(); } ## end sub clear_trace_threshold ############################################################################## # Method: get_transport_type # Objective: To get the current transport type for ZAPI # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_transport_type { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "get_transport_type() can be invoked on a ZAPI" . " APISet object only") if ($self->{interface} ne "ZAPI"); my $t = (defined $self->{session}->{transport_type}) ? $self->{session}->{transport_type} : $self->_default_transport_type(); $Log->exit(); return $t; } ## end sub get_transport_type ############################################################################## # Method: clear_transport_type # Objective: To set the defaults for transport type in ZAPI # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_transport_type { $Log->enter(); my $self = shift(); NATE::BaseException->throw("clear_transport_type() can be invoked on a " . "ZAPI APISet object only") if ($self->{interface} ne "ZAPI"); $self->{session}->{transport_type} = undef; $Log->exit(); } ## end sub clear_transport_type ############################################################################## # Method: get_port # Objective: To get the current port number for ZAPI # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_port { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "get_port() can be invoked on a ZAPI" . " APISet object only") if ($self->{interface} ne "ZAPI"); my $p = (defined $self->{session}->{port}) ? $self->{session}->{port} : ""; $Log->exit(); return $p; } ## end sub get_port ############################################################################## # Method: clear_port # Objective: To set the defaults for port number in ZAPI # Details: Refer to POD documentation at the end of the file. ############################################################################## sub clear_port { $Log->enter(); my $self = shift(); NATE::BaseException->throw( "clear_port() can be invoked on a " . "ZAPI APISet object only") if ($self->{interface} ne "ZAPI"); $self->{session}->{port} = undef; $Log->exit(); } ## end sub clear_port ############################################################################## # Method: set_server_cert_verification # Objective: To set server certificate verification # Details: Refer to POD documentation at the end of the file. ############################################################################## sub set_server_cert_verification { $Log->enter(); my $self = shift(); NATE::BaseException->throw( 'Server authentication is applicable only to ZAPI APISets') if ($self->{interface} ne 'ZAPI'); my %args = NACL::APISet::validate_params( $self, params => \@_, spec => { server_cert_verify => {type => SCALAR, optional => 0, default => 1} } ); $self->{session}->server_cert_verify($args{server_cert_verify}); $Log->exit(); # Keeps Perl::Critic happy return; } ## end sub set_server_cert_verification # ############################################################################## # Method: get_validation_spec # Objective: Returns the validation specifications of the parameters # accepted by the APISet constructor # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_validation_spec { $Log->enter(); my %validation_spec = ( category => {type => SCALAR}, interface => {type => SCALAR}, set => {type => SCALAR}, connection => {type => OBJECT, isa => 'Connectrec', optional => 1}, hostobj => {type => OBJECT, isa => 'Hostrec', optional => 1}, restobj => {type => OBJECT, isa => 'Hostrec', optional => 1}, cdef_path => {type => SCALAR | UNDEF, optional => 1}, shell_type => {type => SCALAR, optional => 1}, context_definition => {type => HASHREF, optional => 1}, version_info => {type => HASHREF, optional => 1}, snmp_auth => {type => HASHREF, optional => 1}, username => {type => SCALAR, optional => 1}, password => {type => SCALAR, optional => 1}, connid => {type => SCALAR, optional => 1}, conntype => {type => SCALAR, optional => 1}, ipaddress => {type => SCALAR, optional => 1}, raw_output_is_like => {type => SCALAR, optional => 1}, name => {type => SCALAR, optional => 1}, 'privilege-level' => {type => SCALAR | UNDEF, optional => 1}, port => {type => SCALAR | UNDEF, optional => 1}, url => {type => SCALAR | UNDEF, optional => 1}, base_path => {type => SCALAR | UNDEF, optional => 1}, include_credential => {type => SCALAR | UNDEF, optional => 1}, no_set_command => {type => SCALAR, optional => 1}, login_to_console => {type => SCALAR, optional => 1}, credential => {type => OBJECT, isa => 'NATE::SOAP::Data', optional => 1}, ); $Log->exit(); return wantarray ? %validation_spec : \%validation_spec; } ## end sub get_validation_spec ## end sub get_validation_spec ############################################################################## # Method: get_conn_override_fields # Objective: Returns the connection override fields # Details: Refer to POD documentation at the end of the file. ############################################################################## sub get_conn_override_fields { $Log->enter(); my ($self) = @_; my @conn_overrides = qw(username password conntype connid ipaddress); $Log->exit(); return @conn_overrides; } ## end sub get_conn_override_fields ############################################################################## # Private Methods ############################################################################## ############################################################################## # Method: _init_API # Objective: Initialize the API Set # Details: Initializes the API Set. This method drives the workflow needed # to make the API Set ready for work. This is accomplished by # creating a new schema object and loading it with CDEFs from the # appropriate path. For APISets which do not require this # initialization, this method does nothing. ############################################################################## sub _init_API { $Log->enter(); # Do nothing. $Log->exit(); } ## end sub _init_API ############################################################################## # Method: _populate_hash # Objective: Populate hash with specific arguments # Details: Provided as input is the list of keys which we'd like to store # in another hash. If any of these are defined in self, we copy # them into the hash and return this hash. ############################################################################## sub _populate_hash { my ($self, @keys) = @_; $Log->enter(); my %hash; foreach my $key (@keys) { if (defined($self->{$key})) { $hash{$key} = $self->{$key}; } } $Log->exit(); return %hash; } ## end sub _populate_hash ############################################################################## # Method: _find_shell_type # Objective: Finds the shell type to which the user want to connect to # Details: This method sets the appropriate shell_type if its not been passed # by the user. ############################################################################## sub _find_shell_type { my ($self, %args) = @_; $Log->enter(); my $shell_host = $self->hostobj(); my $schema_host = $self->{context_definition}->{schema_hostobj} || $shell_host; # Find the shell_type from the shell host(the one with which we connect to) # if not specified by the user. # In mixed mode(RR), this way of determining shell_type based on hosttype is # unreliable. my $hosttype; unless (defined($self->{shell_type})) { $hosttype = $shell_host->hosttype(); if ($hosttype =~ /filer/) { # Firmware APISet is only for Nodes if ($self->{actual_set} eq 'Firmware') { $self->{shell_type} = 'Firmware'; } elsif ($self->{actual_set} eq 'Maintenance') { $self->{shell_type} = 'Maintenance'; } elsif ($self->{actual_set} eq 'SP') { $self->{shell_type} = 'SP'; } elsif ($self->{actual_set} eq 'SPShell') { $self->{shell_type} = 'SPShell'; } elsif ($hosttype =~ /\-ng/) { $self->{shell_type} = "CMode"; } else { $self->{shell_type} = "7Mode"; } } elsif ($hosttype =~ /solaris/) { $self->{shell_type} = 'Solaris'; } elsif ($hosttype =~ /freebsd/) { $self->{shell_type} = 'Freebsd'; } elsif ($shell_host->is_unix()) { # add cygwin support when required $self->{shell_type} = 'Linux'; } elsif ($hosttype =~ /windows/i) { $self->{shell_type} = 'Windows'; } elsif ($hosttype =~ /switch/) { $self->{shell_type} = 'Switch'; } elsif ($hosttype =~ /armadillo-bridge/) { $self->{shell_type} = 'Switch'; } elsif ($hosttype eq 'svp') { $self->{shell_type} = ''; } elsif ($hosttype eq 'flashray') { # For flashray shell_type matches with actual_set if ($self->{actual_set} =~ /MarsNormal|MarsMaint|MarsRoot/) { $self->{shell_type} = $self->{actual_set}; } } elsif ($hosttype eq 'ava') { # For ava shell_type matches with actual_set if ($self->{actual_set} =~ /AVAAdmin|AVARoot/) { $self->{shell_type} = $self->{actual_set}; } } elsif ($hosttype =~ /ontap-select-deploy/i) { $self->{shell_type} = 'ONTAPSelectDeploy'; } else { NATE::Exceptions::Argument->throw( "Could not automatically figure " . "out the shell type for Hosttype: $hosttype. Perhaps you need to " . "explicitly specify shell_type in the constructor"); } # If vfiler context has been requested for and if both shell_host and # schema_host are vfiler (i.e., directly connecting to vfiler), then # shell_type should be "Vfiler". if ( ($self->{actual_set} eq "Vfiler") || ($self->{actual_set} eq "Vserver")) { my $schema_name = defined($self->{context_definition}->{name}) ? $self->{context_definition}->{name} : $schema_host->hostname(); if ($shell_host->hostname() eq $schema_name) { $self->{shell_type} = $self->{actual_set}; } } ## end if (($self->{actual_set... # TODO: Logic for determining whether or not directly connected to # vserver shell. Basically required for versioning. Burt 421982 } ## end unless (defined($self->{shell_type... $Log->debug("Shell_type is found as $self->{shell_type} " . "from the hosttype $hosttype "); $Log->exit(); } ## end sub _find_shell_type sub _print_deprecated_warning_cdef { my $pkg = shift; my $old_param = shift; my $new_param = shift; $Log->warn("Using the " . $old_param . " param is deprecated. " . "Please use " . $new_param . "param instead"); } ## end sub _print_deprecated_warning_cdef ############################################################################## # Method: _get_connectrec_or_hostrec # Objective: Sets either the connectrec or hostrec in the arguments. # Details: This method is used by the _init_Session routine, to either set # the connection object, or the host object, whichever is defined. ############################################################################### sub _get_connectrec_or_hostrec { my ($self, $args) = @_; $Log->enter(); if (defined $self->{connection}) { $args->{connection} = $self->{connection}; } elsif (defined $self->{hostobj}) { $args->{hostobj} = $self->{hostobj}; } $Log->exit(); } ## end sub _get_connectrec_or_hostrec sub DESTROY { } sub xlate_execute_raw_command { $Log->enter(); $Log->exit(); NATE::BaseException->throw( 'xlate cannot be used with execute_raw_command'); } ## end sub xlate_execute_raw_command sub _determine_cdef_path { my $self = $_[0]; $Log->enter(); # Retrieve the information from environment variable, command line # arguments, parameters specified in .ntest file using param() # The parameter to pass is APISET___CDEF_PATH. For the # information what the values INTERFACE and SET can have, please check # the POD section. For example, for CMode filer and CLI/ZAPI interface # the parameter to set is # APISET_CLI_CMODE_CDEF_PATH=/x/eng/localtest/noarch/dev/lib/NACL/APISet/Node/CLI/CMode/main # APISET_ZAPI_CMODE_CDEF_PATH=/x/eng/localtest/noarch/dev/lib/NACL/APISet/Node/ZAPI/CMode/main # For vserver context use CLI/ZAPI # APISET_CLI_VSERVER_CDEF_PATH=/x/eng/localtest/noarch/dev/lib/NACL/APISet/Node/CLI/CMode/main # APISET_ZAPI_VSERVER_CDEF_PATH=/x/eng/localtest/noarch/dev/lib/NACL/APISet/Node/ZAPI/CMode/main # The parameter to pass is APISET___CDEFS_FROM_BUILD=1, eg # APISET_CLI_CMODE_CDEFS_FROM_BUILD=1 for CMode CLI # APISET_ZAPI_CMODE_CDEFS_FROM_BUILD=1 for CMode ZAPI # APISET_CLI_VSERVER_CDEFS_FROM_BUILD=1 for Vserver CLI # APISET_ZAPI_VSERVER_CDEFS_FROM_BUILD=1 for Vserver ZAPI # Order of precedence for CDEF PATH # 1) Constructor input argument 'cdef_path' # 2) Environment variable, .ntest file, command line inputs # 3) CDEF PATH from tharnhost file # 4) Load directly from build root - this input is also supported in # all the above mentioned ways. # 5) Auto-discovery of cdef_path (default if none of the above is # specified) # If (1), (2), (3), (4) are not set or set to empty string, then # autodiscovery (5) will be performed. if ($self->{interface} eq "GUI") { #overriding cdef path through apiset since it is N/A for GUI $self->{cdef_path} = "NotApplicable"; } if (defined $self->{cdef_path}) { $Log->debug("CDEF path override from APISet constructor"); } $self->_read_cdef_provided_as_test_param() if !defined $self->{cdef_path}; $self->_read_cdef_path_from_hostrec() if !defined $self->{cdef_path}; # CDEF_PATH input will override cdefs_from_build option if ($self->{cdef_path}) { $Log->debug("CDEF Path override is obtained as " . $self->{cdef_path} . ". Hence cdefs_from_build option will be disabled"); $self->{version_info}->{cdefs_from_build} = 0; } elsif ($self->{category} !~ /Eseries/i) { $Log->debug( "Looking for cdefs_from_build option from various sources"); if (defined $self->{version_info}->{cdefs_from_build}) { $Log->debug("cdefs_from_build is set in APISet constructor"); } else { $self->_read_cdef_path_from_build(); } } ## end else [ if ($self->{cdef_path}) # Loading CDEFs directly from the build root is supported only for CMode # CLI/ZAPI and 7Mode/DBlade ZAPI. Throw Exception if the option is specified # for any other APISets. if ( (defined $self->{version_info}->{cdefs_from_build}) && ($self->{version_info}->{cdefs_from_build})) { NATE::Exceptions::Argument->throw("CDEFs cannot be loaded directly" . " from the build root for $self->{actual_set} $self->{interface}" . " APISet") unless (($self->{set} eq "CMode" && $self->{interface} eq "CLI") || ($self->{interface} eq "ZAPI")); } $Log->exit(); } ## end sub _determine_cdef_path sub _read_cdef_provided_as_test_param { my $self = $_[0]; $Log->enter(); my $hobj = $self->hostobj(); my $parameter = Tharn::param('APISET_' . $self->{interface} . '_' . uc $self->{actual_set} . '_CDEF_PATH'); if (defined $parameter) { $self->{cdef_path} = $parameter; $Log->debug( "CDEF path override from APISET___CDEF_PATH parameter" ); } elsif (defined Tharn::param("APISET_CDEF_PATH")) { $self->{cdef_path} = Tharn::param("APISET_CDEF_PATH"); $Log->debug("CDEF path override from APISET_CDEF_PATH parameter"); $self->_print_deprecated_warning_cdef('APISET_CDEF_PATH', 'APISET___CDEF_PATH'); } elsif ( defined Tharn::param( 'APISET_ESERIES_' . uc $self->{interface} . '_CDEF_PATH' ) ) { $self->{cdef_path} = Tharn::param( 'APISET_ESERIES_' . uc $self->{interface} . '_CDEF_PATH'); $Log->debug( "CDEF path override from APISET_ESERIES__CDEF_PATH parameter" ); } $Log->exit(); } ## end sub _read_cdef_provided_as_test_param sub _read_cdef_path_from_hostrec { my $self = $_[0]; $Log->enter(); my $hobj = $self->hostobj(); my $parameter_with_interface_and_set = 'NACL_' . $self->{interface} . '_' . uc $self->{actual_set} . '_CDEF_PATH'; my $parameter_with_interface = 'NACL_' . $self->{interface} . '_CDEF_PATH'; if ( defined $hobj->{$parameter_with_interface} || defined $hobj->{$parameter_with_interface_and_set}) { if (defined $hobj->{$parameter_with_interface_and_set}) { $self->{cdef_path} = $hobj->{$parameter_with_interface_and_set}; $Log->debug( "NACL___CDEF_PATH override from tharnhost"); } else { $self->{cdef_path} = $hobj->{$parameter_with_interface}; $Log->debug("NACL_INTERFACE_CDEF_PATH override from tharnhost"); $self->_print_deprecated_warning_cdef('NACL_INTERFACE_CDEF_PATH', 'NACL___CDEF_PATH'); } } elsif ( defined Tharn::param( 'NACL_ESERIES_' . uc $self->{interface} . '_CDEF_PATH')) { $self->{cdef_path} = Tharn::param( 'NACL_ESERIES_' . uc $self->{interface} . '_CDEF_PATH'); $Log->debug( "NACL_ESERIES__CDEF_PATH override from tharnhost"); } $Log->exit(); } ## end sub _read_cdef_path_from_hostrec sub _read_cdef_path_from_build { my $self = $_[0]; $Log->enter(); my $hobj = $self->hostobj(); my $apiset_parameter_with_interface_and_set = Tharn::param('APISET_' . $self->{interface} . '_' . uc $self->{actual_set} . '_CDEFS_FROM_BUILD'); my $nacl_parameter_with_interface_and_set = 'NACL_' . $self->{interface} . '_' . uc $self->{actual_set} . '_CDEFS_FROM_BUILD'; my $nacl_parameter_with_interface = 'NACL_' . $self->{interface} . '_CDEFS_FROM_BUILD'; if (defined $apiset_parameter_with_interface_and_set) { $self->{version_info}->{cdefs_from_build} = $apiset_parameter_with_interface_and_set; $Log->debug("cdefs_from_build option is specified in " . "APISET___CDEFS_FROM_BUILD parameter"); } elsif (defined Tharn::param("APISET_CDEFS_FROM_BUILD")) { $self->{version_info}->{cdefs_from_build} = Tharn::param("APISET_CDEFS_FROM_BUILD"); $Log->debug("cdefs_from_build option is specified in " . "APISET_CDEFS_FROM_BUILD parameter"); $self->_print_deprecated_warning_cdef('APISET_CDEFS_FROM_BUILD', 'APISET___CDEFS_FROM_BUILD'); } elsif (defined $hobj->{$nacl_parameter_with_interface_and_set}) { $self->{version_info}->{cdefs_from_build} = $hobj->{$nacl_parameter_with_interface_and_set}; $Log->debug( "__cdefs_from_build option is specified in tharnhost" ); } elsif (defined $hobj->{$nacl_parameter_with_interface}) { $self->{version_info}->{cdefs_from_build} = $hobj->{$nacl_parameter_with_interface}; $Log->debug( "_cdefs_from_build option is specified in tharnhost"); $self->_print_deprecated_warning_cdef( 'NACL__CDEFS_FROM_BUILD', 'NACL___CDEFS_FROM_BUILD' ); } $Log->debug("cdefs_from_build option is obtained to be " . $self->{version_info}->{cdefs_from_build}) if (defined $self->{version_info}->{cdefs_from_build}); $Log->exit(); } ## end sub _read_cdef_path_from_build sub _is_versioning_needed { my ($self) = @_; $Log->enter(); $Log->exit(); return ( !( $self->{interface} =~ /VMAPI|XAPI/ || $self->{category} =~ /Eseries|Flashray|AVA/ || ($self->{set} =~ /SMTT/ && $self->{interface} =~ /GUI/) || $self->{set} =~ /VPserver/i ) ); } ## end sub _is_versioning_needed sub _need_to_load_cdefs { my ($self) = @_; $Log->enter(); $Log->exit(); return ( !( $self->{interface} =~ /VMAPI|XAPI|Webapi|SOAP/ || $self->{set} =~ /MarsNormal|MarsMaint|AVAAdmin|AVARoot/i ) ); } ## end sub _need_to_load_cdefs 1; ############################################################################## # POD here ############################################################################## =head1 NAME NACL::APISet - API Set base class =head1 SYNOPSIS use NACL::APISet; =head1 DESCRIPTION A C contains data and methods common to all API Sets. Inherit from this class when creating new API Sets. Acts as a factory class to create usable API sets. =head1 EXCEPTIONS =over =item NATE::BaseException =item NATE::Exceptions::Argument =item NACL::APISet::Exceptions::MissingSchema =item NACL::APISet::Exceptions::ConnectionFailedException =item NACL::APISet::Exceptions::MissingVersionManager =back =head1 CONSTRUCTOR =head2 new Returns a reference to a newly created API set. This is a factory class that will create an appropriate API set based on given arguments. =over =item Synopsis $api = $class->SUPER::new( [hostobj => $host,] [name => $name,] category=>$category, interface=>$interface, set=>$set [, restobj => $resthost] [, connection => $connection] [, cdef_path => $cdef_path] [, username => $username] [, password => $password] [, connid => $connid] [, conntype => $conntype] [, shell_type => $shell_type] [, context_definition => \%context_definition] [, no_set_command => 1/0] [, version_info => \%version_info]); =item Arguments =over =item hostobj (Optional) The hostrec object created for the resource. This parameter cannot be provided if 'connection' is provided. =item name (Optional) The name of the resource to which we would like to establish a connection. Note that either of name or connection can be provided, but not both. =item category (Mandatory) The category to use. Valid values include 'Node', 'Host', 'Switch', 'ESeries', 'Flashray', 'AVA'. =item interface (Mandatory) The interface to use. Valid values include 'CLI', 'ZAPI', 'Webapi'. =item set (Mandatory) The API set to use. Valid values include "CMode", "7Mode", "SP", "SPShell", "Vfiler", "Systemshell", "Freebsd", "Nodescope", "Linux", "Windows","HPUX", "AIX", "Powershell", "Kerberos", "SMO", "SQL", "Solaris", "DFM", "SystemshellNGSH", "NodescopeNGSH", "BrocadeFC", "CiscoFC", "Armadillo", "NetAppNetwork", "CiscoNetwork", "VPserver". "MarsNormal", "MarsRoot", "MarsMaint", "AVAAdmin", "AVARoot", Not applicable for "Eseries" APISets. This should correspond to the context of the commands to be executed. For Eg, when running nodesope commands from a cluster shell, the context is nodescope (7Mode commands) though we had connected to a CMode shell. set in this case should be 7Mode. =item restobj (Optional) The restrec object created for the REST server. Typically will be used for EF-Series testing using 'Webapi'. =item connection (Optional) A pre-existing NATE::Connectrec object used for establishing connection to the external service. Either connection or name can be provided, not both. =item cdef_path (Optional) The path to the directory containing CDEFs (Command Definition Files). The cdef_path tells the APISet where to find CDEFs. If not provided, an APISet-defined default CDEF path is used automatically. =item username (Optional) Username used to log into the resource. This will be ignored if a connection object is passed. If no value is provided, the connection layer will get this value from the host record. =item password (Optional) Password used to log into the resource. This will be ignored if a connection object is passed. If no value is provided, the connection layer will get this value from the host record. =item connid (Optional) Connection ID to be used to connect to the resource. This will be ignored if a connection object is passed. If no value is provided, API layer will select a best default based on the type of the host. Note that 'console' is a special value and should only be used for console connection. Naming non-console connections as 'console' should strictly be avoided as the libraries try to reuse/share existing console connections based on the connid. Eg: specifying connid => 'console', conntype => 'libssh-persist' would actually create a libssh-persist connection but it will name the connection as 'console' which will end up confusing the libraries and should be avoided. =item conntype (Optional) Method of connecting to the resource. This will be ignored if a connection object is passed. If no value is provided, the connection layer will get this value from the host record. =item shell_type (Optional) The refers to the type of the shell host sent through 'hostobj' input parameter. This determines the session type incase if the context of the commands to be executed is different from what it is connected to. For Eg: Running Nodescope commands(context) from cluster shell(shell with which we connect to) Shell type can be 7Mode, CMode, Vfiler or Vserver for category being Node. If not passed, then shell host will be used to determine the session type. For all other categories except Node, shell_type is not expected. =item context_definition (Optional) This takes the input as a reference to hash structure which contains information about schema host(context), username and password if any required to enter into the context and any other additional information apart from what can be obtained from schema host. For ZAPI Nodescope context, this field is mandatory. schema_hostobj- The hostrec object corresponding to schema. Eg: When running Nodescope commands from cluster shell, schema is 7Mode and hence a hostrec object corresponding to 7Mode equivalent should be sent. username,password- These will act as overrides for the default_username and default_password in the schema hostrec object. Eg: Used when entering into system shell(freebsd) context from a 7Mode/CMode shell. name- The name of the vfiler for set being "Vfiler" or the name of the node for set being "Nodescope" =item no_set_command (Optional) This command is used to supress the '"set" is not a recognized command' error which comes while using customised apiset object.By setting no_set_command => 1 we can supress this error. =item version_info (Optional) This takes the input as a reference to hash structure which contains information about whether to load the CDEFs from the build root (cdefs_from_build), add compatibility support or not (compatibility). The following are the supported hash keys. cdefs_from_build - Boolean option. Takes 0/1. It defaults to 0. To load CDEFs directly from the build root, set this option to 1. compatibility - Boolean option. Takes 0/1. By default compatibility will be performed. Set it to 0 if you want to disable compatibility. This option will be ignored for APISets other than CMode CLI. =item snmp_auth (Optional) This takes the input as a reference to hash structure which contains information about version (possible values are 1, 2c ,3), community (for SNMP v1 and SNMPv2c), username, security_level, authprotocol, authkey, authpassword, privprotocol, privkey and privpassword for SNMPv3. =item raw_output_is_like (Optional) This options is used to specify whether the output is like 7Mode or CMode Valid values are: CMode,7Mode default: 7Mode Applicable for set: NodescopeNGSH =item port (Optional) This is the port to be used for the SOAP APISet connection. This will be ignored if the url value is overriden. Applicable for interface: SOAP =item url (Optional) This is the full connection url to use for the SOAP APISet connection. If this is not provided, this will be created automatically from the Hostrec passed to the APISet->new() call. Applicable for interface: SOAP =item base_path (Optional) This is the base_path to use for the SOAP APISet url for connection. This will be used to create the url if the url value is not provided. Valid values are formatted like: 'services/vasa-public_latest' Applicable for interface: SOAP =item include_credential (Optional) This option specifies that the credential object should be included as a parameter for every call to the APIset. Valid values are: 0,1 default: 1 Applicable for set: VPserver =item credential (Optional) This options is used to specify the object to use as a credential for VPserver. If this is not provided, the credential will be automatically created, based on the values from the Hostrec. Applicable for set: VPserver =back =item Returns A reference to a new API Set. =back =head1 Methods =head2 reinit This method is used to reinit the session incase if the session is lost because of rebooting and preparatory service for setting up the session again needs to be done. =over =item Synopsis $Api_Set_Obj->reinit(); =item Arguments None. =item Returns Nothing. =back =head2 api_is_session_alive This method is used to check if the current CLI connection (persistent) is still active. It does b check if the service is up or not. Does not do any checking for non CLI interfaces =over =item Synopsis $schema = $Api_Set_Obj->api_is_session_alive(); =item Arguments None. =item Returns False if the CLI connection is dead. True otherwise. =back =head2 api_reconnect_session This method is to be used to reconnect a previously lost connection being used by the APISet (applicable for persistent CLI connections only) It is recommended that api_reconnect_session should not be used in cases when testbed is undergoing any disruptive testing. The disruptive testing can be any of the following: =over =item * reboot =item * system power_cycle =item * upgrade/revert In this case not only would the connection have gotten lost but the OS version being run on the host would have also changed. =item * passing the command_interface to a subtest Certain persistent connections might become unusable in a subtest (such as c-login, since the socket connection established is inherently unsharable across processes) =item * disconnect being explicitly called on the connection object for all of the above cases it is recommended to use Component layer method: $command_interface->refresh_command_interface() =back =over =item Synopsis $schema = $Api_Set_Obj->api_reconnect_session(); =item Arguments =over =item max_reconnect (Optional) The number of times to retry on connection failure =item max_reconnect_timewait (Optional) The number of seconds to sleep between each retry when max_reconnect is set =back =item Returns Nothing. =back =head2 clear_timeout This method resets the timeout to the default value. (Currently 60 seconds) =over =item Synopsis $Api_Set_Obj->clear_timeout(); =item Arguments None. =item Returns Nothing. =back =head2 get_schema_obj This method returns the stored schema object. If not schema object could be retrieved, it throws a MissingSchema exception. =over =item Synopsis $schema = $Api_Set_Obj->get_schema_obj(); =item Arguments None. =item Returns Schema object. =back =head2 get_name Returns the name of the resource =over =item Synopsis $name = $Api_Set_Obj->get_name(); =item Arguments None. =item Returns (Scalar) Name of the resource. =back =head2 get_version_manager This method returns the stored version object. If not version object could be retrieved, it throws a MissingVersionManager exception. =over =item Synopsis $version_object = $Api_Set_Obj->get_version_manager(); =item Arguments None. =item Returns Version object. =back =head2 get_timeout This method returns the curent timeout value. The actual implementation is present in Session, this method internally calls the method defined in Session. =over =item Synopsis $timeout = $Api_Set_Obj->get_timeout(); =item Arguments None. =item Returns (Scalar) The current timeout value =back =head2 set_timeout Set the timeout to a new value. Timeout is a Session-specific value, so internally this method calls the set_timeout method defined in Session. =over =item Synopsis $Api_Set_Obj->set_timeout("connectrec-timeout" => $timeout); =item Arguments =over =item connectrec-timeout The new timeout value (in seconds) =back =item Returns Nothing. =back =head2 get_connection To get the connection object created by the APISet. =over =item Synopsis $connection = $Api_Set_Obj->get_connection(); =item Arguments Nothing =item Returns Connection object of type "Connectrec". =back =head2 set_cert_file This method sets user's certificate to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->set_cert_file('cert_file' => ""); =item Arguments =over =item cert_file Optional Specify location of certificate file =back =item Returns Nothing. =back =head2 set_key_file This method sets user's private key to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->set_key_file('key_file' => ""); =item Arguments =over =item key_file Optional Specify location of private key file =back =item Returns Nothing. =back =head2 set_ca_cert_file This method sets server's certificate to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->set_ca_cert_file('ca_cert_file' => ""); =item Arguments =over =item ca_cert_file Optional Specify location of server's certificate file =back =item Returns Nothing. =back =head2 set_key_password This method sets password for user's private key to use SSL authentication for ZAPI execution. This password will be used if users private key is password protected =over =item Synopsis $Api_Set_Obj->set_key_password('key_password' => ""); =item Arguments =over =item cert_key_password Optional Specify location of password_file of user's private key =back =item Returns Nothing. =back =head2 set_ssl_cert_verification This method sets whether or not to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->set_cert_file('ssl_cert_verification' => 1); =item Arguments =over =item ssl_cert_verification Optional set 1 to enable, 0 to disable =back =item Returns Nothing. =back =head2 set_hostname_verification This method sets whether or not to verify hostname while using SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->set_hostname_verification('hostname_verification' => 0); =item Arguments =over =item hostname_verification Optional set 1 to enable, 0 to disable =back =item Returns Nothing. =back =head2 get_cert_file This method returns user's certificate to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->get_cert_file(); =item Arguments Nothing. =item Returns Location of users certificate file =back =head2 get_key_file This method returns user's private key to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->get_key_file(); =item Arguments Nothing. =item Returns Location of private key file =back =head2 get_ca_cert_file This method returns server's certificate to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->get_ca_cert_file(); =item Arguments Nothing. =item Returns Location of server's certificate file =back =head2 get_key_password This method returns password for user's private key to use SSL authentication for ZAPI execution. This password will be used if users private key is password protected =over =item Synopsis $Api_Set_Obj->get_key_password(); =item Arguments Nothing. =item Returns Location of password_file of user's private key =back =head2 get_ssl_cert_verification This method returns whether or not to use SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->get_ssl_cert_verification(); =item Arguments Nothing. =item Returns 0 or 1. =back =head2 get_hostname_verification This method returns whether or not to verify hostname while using SSL authentication for ZAPI execution. =over =item Synopsis $Api_Set_Obj->get_hostname_verification(); =item Arguments Nothing =item Returns 0 or 1. =back =head2 clear_cert_file This method clears value of cert_file location =over =item Synopsis $Api_Set_Obj->clear_cert_file(); =item Arguments Nothing. =item Returns Nothing. =back =head2 clear_key_file This method clears value of key_file location =over =item Synopsis $Api_Set_Obj->clear_key_file(); =item Arguments Nothing. =item Returns Nothing. =back =head2 clear_ca_cert_file This method clears value of ca_cert_file location =over =item Synopsis $Api_Set_Obj->clear_ca_cert_file(); =item Arguments Nothing. =item Returns Nothing =back =head2 clear_key_password This method clears value of key_password file location. =over =item Synopsis $Api_Set_Obj->clear_key_password(); =item Arguments Nothing. =item Returns Nothing. =back =head2 clear_ssl_cert_verification This method sets ssl_cert_verification to undef. =over =item Synopsis $Api_Set_Obj->clear_ssl_cert_verification(); =item Arguments Nothing. =item Returns Nothing. =back =head2 clear_hostname_verification This method sets hostname_verification to undef. =over =item Synopsis $Api_Set_Obj->clear_hostname_verification(); =item Arguments Nothing. =item Returns Nothing. =back =head2 set_transport_type This method sets the transport type for ZAPI execution. =over =item Synopsis $Api_Set_Obj->set_transport_type('type' => "HTTPS"); =item Arguments =over =item type Required Transport Type. Valid values are "HTTP" and "HTTPS" and it is case insensitive. =back =item Returns Nothing. =back =head2 get_transport_type This method returns the current transport type used for any ZAPI execution =over =item Synopsis my $transport_type = $Api_Set_Obj->get_transport_type(); =item Arguments Nothing. =item Returns This method returns the transport type. It can be either HTTP or HTTPS and case-insensitive. If not already set or cleared, then it will return "HTTP" as the default transport type. =back =head2 clear_transport_type This method clears the transport type stored in the APISet object. =over =item Synopsis $Api_Set_Obj->clear_transport_type(); =item Arguments Nothing. =item Returns Nothing. =back =head2 get_command_definition This method is used to get the command definition object of a particular command. =over =item Synopsis $Api_Set_Obj->get_command_definition('command' => "volume_show"); =item Arguments =over =item command Required The command for which the command definition is required. The structure of command definition may vary based on the interface, refer to appropriate schema for more information. =back =item Returns The command definition structure of the given command. =back =head2 get_port This method returns the current port number used for any ZAPI execution =over =item Synopsis my $port = $Api_Set_Obj->get_port(); =item Arguments Nothing. =item Returns This method returns the port number used for ZAPI execution. If not already set or cleared, then it will return empty string. =back =head2 clear_port This method clears the port number stored in the APISet object. =over =item Synopsis $Api_Set_Obj->clear_port(); =item Arguments Nothing. =item Returns Nothing. =back =head2 set_server_cert_verification This method is a wrapper around the NaServer SDK's set_server_cert_verification. It can be used to turn on or off the server side certificate authentication. =over =item Synopsis $Api_Set_Obj->set_server_cert_verification(server_cert_verify => 0|1); =item Arguments server_cert_verify Required: A '0' or a '1' indicating whether the server side certificate authentication should be turned off or on. Default: The server side certificate authentication is turned on by default. =item Returns Nothing. =back =head2 set_return_option This method stores the user preference of whether execute_raw_command APIset should return raw XML output or response object. This is a convenience method so that the option need not be specified every time in the call to execute_raw_command(). Should be used on a ZAPI or SNMP APISet object only. =over =item Synopsis $Api_Set_Obj->set_return_option('return-response-object' => "1"); =item Arguments =over =item return-response-object Required If set, response object will be returned for any subsequent invocation of execute_raw_command(). Else raw output will be returned by default. =back =item Returns Nothing. =back =head2 get_return_option This method returns the current user preference of return option for execute_raw_command. Should be used on a ZAPI or SNMP APISet object only. =over =item Synopsis my $option = $Api_Set_Obj->get_return_option(); =item Arguments Nothing. =item Returns Returns 0/1. 0 => execute_raw_command will return raw output 1 => execute_raw_command will return response object =back =head2 clear_return_option This method clears the user preference of return option for execute_raw_command. Should be used on a ZAPI or SNMP APISet object only. =over =item Synopsis $Api_Set_Obj->clear_return_option(); =item Arguments Nothing. =item Returns Nothing. =back =head2 get_cdef_path This method returns the CDEF path from which the CDEF files are loaded. This cdef path could be either auto-discovered by APISets with the help of version manager or it could be the one overridden by the user by means of test parameter or tharnhost file or by specifying in APISet constructor. As of now, APISets use only one CDEF directory and so this method would return an array which has only one CDEF path. We have plans to share common CDEFs in a parent folder especially for the client APISets in which case CDEFs might be loaded from more than one CDEF directories. In such cases, this method would return an array having more than one paths. If the specific APISet doesn.t make use of CDEF path (Eg: NACL::APISet::Host::VMAPI::ESX), then calling this method would throw NATE::BaseException. =over =item Synopsis my @paths = $Api_Set_Obj->get_cdef_path(); =item Arguments Nothing. =item Returns The cdef directory path(s). =back =head2 validate_params This is an APISet-specific wrapper around Params::Validate::validate_with(). It returns the validated parameters. If one or more of the parameters are found to be invalid, it throws an NATE::Exceptions::Argument exception. =over =item Synopsis my %args = $obj->validate_params( params => \@_, spec => { category => { type => SCALAR, optional => $is_optional }, interface => { type => SCALAR, optional => $is_optional }, } ); =item Arguments All the arguments that are taken by Params::Validate::validate_with(). =item Returns Returns a hash with all the parameters specified and defaults if any. =back =head2 timeout_scaling_factor Timeout scaling factor is a real number which is multiplied with the existing timeout value and the product becomes the new timeout value. This parameter can be provided through the command line or through a method call in the script. The value can be set or obtained through accessor methods as described in the Synopsis section. The timeout scaling factor value set from the script will take precdence over the value set through the command line. =over =item Synopsis use NACL::APISet =item From the command line: APISET_TIMEOUT_SCALING_FACTOR = =item In the script: To set the timeout scaling factor: $Api_Set_Obj->timeout_scaling_factor(); To get the value set: my $timeout_scaling_factor = $Api_Set_Obj->timeout_scaling_factor(); =item Arguments For the set method, the argument is a real number. =item Example $Api_Set_Obj->timeout_scaling_factor(1.0); $Api_Set_Obj->('connectrec-timeout' => 10 ); In the above case, timeout value set would be 10 seconds. =back =head2 get_validation_spec() This method returns the validation specification of all the options accepted by the APISet constructor =over =item Arguments Nothing. =item Returns In list context, returns a hash of the validation specifications. In scalar context, returns a hash-reference of the validation specifications. =back =head2 hostobj This method calls returns the hostrec object. =over =item Synopsis $Api_Set_Obj->hostobj() =item Arguments None =item Returns A Hostrec Object =back =head2 COMMAND PROFILING Command profiling is applicable for only CMode CLIs and ZAPIs. A test parameter called PROFILING_ENABLED needs to be set to 1 to enable command profiling. A separate file of the the form _profile.log will be created in a directory called 'Command_profile_data' if the parameter 'SEPARATE_LOG_FOR_PROFILE_DATA' is set to 1. This parameter is 0 by default. By default, the profiling data is logged in the same log file generated by the test script. The directory structure of the 'Command_profile_data' will mimic the log directory structure of the test script. Eg: If x/y/z/01.log is the directory structure produced by the test script, then the directory structure generated when SEPARATE_LOG_FOR_PROFILE_DATA is set to 1 is: Command_profile_data/x/y/z/01_profile.log =over =item Invocation ntest PROFILING_ENABLED=1