#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2000,2019 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # sccsid = "@(#)09 1.49 src/rsct/rmc/cli/bin/chrsrc.perl, rmccli, rsct_rady, rady2035a 11/12/15 16:30:51" ###################################################################### # # # Module: chrsrc # # # # Purpose: # # chrsrc - Changes the persistent attribute values of a resource # # or resource class. # # # # Syntax: # # To change the persistent attribute values of a resource or # # resource class (-c flag), using data entered on the # # command line: # # chrsrc [-h] -s "selection_string" [-v] [-a] [-T] [-V] # # Resource_class Attr=value... # # chrsrc [-h] -r [-v] [-a] [-T] [-V] Resource_handle Attr=value... # # chrsrc [-h] -c [-v] [-a] [-T] [-V] Resource_class Attr=value... # # chrsrc [-h] -C Peer_domain_names [-v] [-T] [-V] # # Resource_class Attr=value... # # # # To change the persistent attribute values of a resource or # # resource class (-c flag), using data predefined in an # # input file: # # chrsrc [-h] -f Resource_data_input_file -s "Selection_string" # # [-v] [-a] [-T] [-V] Resource_class # # chrsrc [-h] -f Resource_data_input_file -r # # [-v] [-a] [-T] [-V] Resource_handle # # chrsrc [-h] -f Resource_data_input_file -c # # [-v] [-a] [-T] [-V] Resource_class # # chrsrc [-h] -f Resource_data_input_file -C Peer_domain_names # # [-v] [-T] [-V] Resource_class # # # # Flags: # # -h Help. Writes the command's usage statement to stdout. # # -c Class. Changes the resource class persistent attribute # # values. By default, the resource persistent attributes # # are changed. Use this flag if you want to change the # # resource class persistent attributes. # # -C Peer_domain_names Class. Changes the resource class # # persistent attribute values for peer domains in a # # management domain. Specify one or more peer domain names # # separated by a comma. To specify all peer domains in the# # management domain, use -c with -a. # # -r Resource Handle. Change the specific resource that # # matches the specified Resource_handle. # # -s Selection_string All selection strings must be enclosed # # within either double or single quotation marks. If the # # selection string contains double quotation marks, # # enclose the entire selection string in single # # quotation marks. For example: # # -s 'Name == "testing"' # # -s 'Name ?= "test"' # # Only persistent attributes may be listed in a selection # # string. # # -f Resource_data_input_file File input. Specifies the name of # # the file which contains resource attribute information. # # PersistentResourceAttributes:: # # attr1 = value # # attr2 = value # # - or - # # PersistentResourceClassAttributes:: # # attr1 = value # # attr2 = value # # -v Verify. Verifies that all of the specified attributes # # are valid persistent attribute names that do not have a # # "read_only" property. The chrsrc command cannot verify # # that all of the attributes specified on the command line # # or in the input file can be changed. The underlying # # resource manager that controls the specified resource # # determines which attributes can be changed. After this # # command is run (without the -v flag), any attribute name # # that could not be changed is included in an error # # message. This command does not actually change the attr. # # -a All nodes. The chrsrc command applies to all nodes in # # the cluster. The cluster scope is determined by the # # environment variable CT_MANAGEMENT_SCOPE. If it is not # # set, first the management domain scope is used, then # # peer domain scope, and then local scope is used until # # the scope is a valid scope for the command. The command # # will run once for the first valid scope found. # # If -a is used with -c, it applies to all peer domains in # # the management domain. # # -T Trace. Writes the command's trace messages to standard # # error. For your software-service organization use only. # # -V Verbose. Writes this command's verbose messages to # # standard output. # # # # Operands: # # Resource_class A resource class name. Enter the lsrsrcdef # # command for a list of defined resource class # # names. # # # # Resource_handle The specific resource handle that is associated # # with the resource that you wish to change. Use # # the lsrsrc command to obtain valid resource # # handles. The resource handle must be enclosed # # by double quotation marks. An example is: # # "0x4017 0x0001 0x00000000 0x0069684c 0x0d4715b0 # # 0xe963f69" # # # # Attr=value Enter one or more attribute value pairs. If the # # -f flag is specified, Attr=value pair operands # # should not be entered on the command line. Attr # # is any defined persistent attribute name. Use # # the lsrsrcdef command to get a list of the # # defined persistent attributes and their data # # types for the specified resource class. The # # value entered must be the appropriate data type # # for the specified attribute. For example, if # # NodeNumber is defined as a uint32 data type, # # enter a positive numeric value. # # # # Description: # # The chrsrc command changes the persistent attribute values for # # a resource or resource class. # # # # By default, this command changes the resource persistent # # attributes. If you wish to change the resource class peristent # # attributes, specify the -c flag. # # # # Only persistent attributes that do not have a "read_only" # # property can be changed. # # # # Use the -v flag to verify that the attribute names specified by # # the command line or resource data input file are valid # # persistent attributes for the specified resource and that these # # attributes do not have a property of "read_only". When chrsrc is # # run with the -v flag, the specified attributes are not changed. # # # # After the chrsrc command is run without the -v flag, if any # # specified attribute could not be changed, it is noted in an # # error message. If a particular attribute passes when the # # chrsrc -v command is run, this does not ensure that the # # attribute can be changed. The underlying Resource Manager # # controls which attributes can be changed. # # # # To change the persistent attributes for a resource, use the -r # # flag to change just the resource linked with the specified # # Resource_handle, or use the -s flag to change all the resources # # that match the specified "Selection_string". # # # # Exit Values: # # 0 MC_CLI_SUCCESS Command completed successfully. # # 1 MC_CLI_RMC_ERROR Command terminated due to an underlying # # RMC error. # # 2 MC_CLI_ERROR Command terminated due to an underlying # # error in the command script. # # 3 MC_CLI_BAD_FLAG Command terminated due to user # # specifying an invalid flag. # # 4 MC_CLI_BAD_OPERAND Command terminated due to user # # specifying a bad operand. # # 5 MC_CLI_USER_ERROR Command terminated due to a user error. # # For example specifying an undefined # # Resource name as the Resource operand. # # 6 MC_CLI_NO_RSRC_FOUND No resources were found that matched # # the specified selection string. # # # # Examples: # # chrsrc -s "NodeNumber == 1" IBM.Foo Name=c175n05 # # chrsrc -r -f IBM.Foo.chresource # # "0x4000 0x0001 0x00000000 0x0069684c 0x0d450f64 0xb8dfee2f" # # # # Man Page: # # For the most current detailed description of this command see # # the mkrsrc man page in /opt/rsct/man. # # # #--------------------------------------------------------------------# # Inputs: # # /opt/rsct/msgmaps/mccli.chrsrc.map - message mapping # # /opt/rsct/msgmaps/mccli.mccli.map - message mapping # # # # Outputs: # # stdout - any verbose messages. # # stderr - any error message. # # # # External Ref: # # Commands: ctdspmsg # # Modules: MC_cli_utils.pm, MC_cli_display_utils.pm, MC_cli_rc.pm # # CT_cli_utils.pm, CT_cli_input_utils.pm, # # CT_cli_display_utils.pm # # Extensions: CT::MC, CT::MCerr, CT::CT, CT::CU # # Perl library routines: Getopt::Long # # # # Tab Settings: # # 4 and tabs should be expanded to spaces before saving this file. # # in vi: (:set ts=4 and :%!expand -4) # # # # Change Activity: # # 000315 SAB 60910: Initial design & write. # # 001115 GTM 67900: Add -c, -r support # # 010311 SAB 63852: Prepared for GA. # # 010406 SAB 71892: Support new MC_CLI_NO_RSRC_FOUND return code. # # 020717 JAC 84819: Add -a to mean change all nodes in cluster. # # 020801 JAC 85417: Update usage message. # # 020925 JAC 87393: Change CT_cli_display_utils to .._displayext.. # # 021203 JAC 88085: Make changes to remove perl extensions. # # 021209 JAC 89902: Fix index used in setup_chrsrc. # # 030404 JAC 92787: Don't allow -s "" for selection string. # # 040111 JAC 100165: Add -C processing for peer domain class in DM.# # 040121 JAC 103355: Some fixes for -C flag. # # 040407 JAC 105863: Use escape_chars for "\" searches. # # 040426 JAC 108105: Fix a typo. # # 051116 JAC 131200: Check for multiple non-array attributes. # # 061024 JAC 140150: Fix help message. # # 080104 JAC 148342: Fix output of error message. # ###################################################################### #--------------------------------------------------------------------# # General Program Flow/Logic: # # # # A. Parse command line flags and operands, determine which flavor # # of this command we are actually invoking. # # This command allows a user to change attribute values for # # * Resources # # * Resource Classes # # The Attribute=Value pairs can be specified via the command line # # or via an input files (see -f flag). # # # # When resource attributes are being changed, the default, # # the resources that get changed are all of the resources that # # match the specified selection string (-s "selection_string" # # flag). # # # # If a resource handle is specified (-r flag & operand is a # # resource handle), then only the attributes for that specific # # resource will be changed. # # # # When resource class attributes are being changed (-c flag) # # only the resource class instance will be changed. # # # # B. Initialize a session with RMC. # # C. If a resource handle was specified we need to determine which # # resource class it belongs to. So we can get the data types. # # D. Get the data types for the persistent attributes for the # # specified resource or resource class. # # E. To change resource attributes with selection string # # call underlying mc_set_select_bp # # To change resource attributes for specified resource handle # # call underlying mc_set_handle_bp # # To change resource class attributes # # call underlying mc_class_set_bp # # F. Display any attributes that couldn't be set # # underlying Resource Manager actually controls which attributes # # can and cannot be changed / set for the resource classes that # # it controls. # # G. Cleanup. # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Included Libraries and Extensions # #--------------------------------------------------------------------# use lib "/opt/rsct/pm"; use locale; use Getopt::Long; use autouse CT_cli_utils => qw( printIMsg printEMsg ); use autouse CT_cli_input_utils => qw( process_input_file process_cmdline_input string_to_rsrc_handle escape_chars check_input_file ); use autouse CT_cli_displayext_utils => qw( rsrc_handle_to_string ); use MC_cli_rc qw(:return_codes); use autouse MC_cli_utils => qw( build_HoAttr error_exit printCEMsg validate_rsrc_hndl get_class_from_rsrc_hndl_api get_p_attr_defs_api get_sd_defs_api convert_input_value_api process_exit_code process_api_error remove_api_error read_from_Stdin ); #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# Getopt::Long::Configure ("bundling", "no_auto_abbrev", "no_ignore_case", "require_order", "prefix_pattern=(--|-)"); $TRUE = 1; $FALSE = 0; $Verbose = $FALSE; # default - verbose turned off # By default output, attribute name value pairs should be entered # via the command line. Attr=value e.g. Name=c175n06 NodeNumber=1 $Opt_File_Input = $FALSE; # default - see -f (file form) $Opt_Ch_Class = $FALSE; # default - see -c (rsrc class) $Opt_Ch_Class_DM = $FALSE; # default - see -C (rsrc class) $Opt_Class = $FALSE; # set to true if -c or -C used $Opt_RSRC_Handle = $FALSE; # default - see -r (rsrc hndle) $Opt_Verify = $FALSE; # default - see -v (verify) $Opt_Cmd_Cluster = $FALSE; # -a all nodes $Opt_Node_File= $FALSE; # default - see -N $Opt_Stdin= $FALSE; # default - see -N with Stdin $PROGNAME = "chrsrc"; # Program Name for messages $MSGCAT = "mccli.cat"; # msg catalogue for this cmd $CTDIR = "/opt/rsct"; # RSCT root directory $CTBINDIR = "$CTDIR/bin"; # Cluster Bin directory path $LSMSG = "$CTBINDIR/ctdspmsg"; # list / display message rtn. $ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps"; # msg maps used by $LSMSG #--------------------------------------------------------------------# # Variables # #--------------------------------------------------------------------# %HoPAttrDefs = (); %HoSDAttrDefs = (); my $badrc = 0; my $rsrc_class_id = 0; my @chrsrcapi_parms = (); # parameters to send to chrsrcapi my $node_file_name; # to hold node filename $DELIMITER = "tvrtvrtvr"; # delimiter for chrsrc-api $CMD_LIMIT = 20000; # chrsrc-api cmd limit #--------------------------------------------------------------------# # Main Code # #--------------------------------------------------------------------# # parse the command line, exit if there are errors my ($rc, $resource, $r_rsrc_handle, $filename, $select_str, $node_file_name, $peer_domains)= &parse_cmd_line; ($rc == 0) || error_exit($rc); # if -a was specified for all nodes, make sure CT_MANAGEMENT_SCOPE # is set. If it isn't, set it to 4, DM/SR/Local if (($Opt_Cmd_Cluster || $Opt_Node_File) && !defined $ENV{CT_MANAGEMENT_SCOPE}) { $ENV{CT_MANAGEMENT_SCOPE} = 4; } # if -C was specified for peer domains in a management domain, # make sure CT_MANAGEMENT_SCOPE is set to DM scope. if ($Opt_Ch_Class_DM) { $ENV{CT_MANAGEMENT_SCOPE} = 3; } # set $Opt_Class if either $Opt_Ch_Class or $Opt_Ch_Class_DM is set if ($Opt_Ch_Class_DM || $Opt_Ch_Class) { $Opt_Class = $TRUE; } # Determine which resource class this resource handle is # associated with. if ($Opt_RSRC_Handle) { $r_rsrc_handle = $resource; ($rc, $resource) = get_class_from_rsrc_hndl_api($r_rsrc_handle); ($rc == 0) || error_exit($rc); } # Get the persistent attribute definitions for this resource # and build a hash indexed using the persistent attribute program # name that will allow easy access to each attributes id, # data type and property definitions. # To change a resource attribute value that attribute must not # have a "read_only" property. my $req_properties = 0xFFFF; my @req_attributes = (); $rc = get_p_attr_defs_api($resource, $Opt_Class, $req_properties, \@req_attributes, \@LoPAttr, \%HoPAttrDefs); ($rc == 0) || error_exit($rc); # get_p_attr_defs only supports filtering/selecting the required # attributes. Here we need to only select attributes that do not # have the MC_RSRC_PATTR_READ_ONLY property, so delete the attributes # we cannot change (the ones with read_only properties). foreach $attribute (@LoPAttr) { ($HoPAttrDefs{$attribute}{at_properties} =~ /read_only/) && delete $HoPAttrDefs{$attribute}; } my @sd_attr_names = (); # scan through the Hash of Persistent Attributes checking # to see if any are SDs or SDArrays my @pattr_names = keys %HoPAttrDefs; foreach $attr_name (@pattr_names) { $dtype = $HoPAttrDefs{$attr_name}{at_dtype}; if ( ($dtype =~ /^CT_SD_PTR$/) || ($dtype =~ /^CT_SD_PTR_ARRAY$/) ) { # Add these SD attributes to array of all SD attr names push @sd_attr_names, $attr_name; } } # If we found any persistent attributes that are SD get their # definition from RMC if (scalar(@sd_attr_names) > 0) { # Get the SD data and # Format the Query Definition Structured Data attributes # and elements into a form suitable for quick look up by # attribute name the for the element data_types. get_sd_defs_api($resource, $Opt_Class, \@sd_attr_names, \%HoSDAttrDefs); } # Process either the attr=value pairs from the command line or # from the input file if -f flag was used ($rc, $rLoRsrcData) = process_input($Opt_File_Input, $filename, $Opt_Class, \@ARGV); ($rc == 0) || error_exit($rc); # Merge the attr=value pairs you got from the user with the # resources actual attribute definitions to build a Hash of # Persistent Attributes which contains the equivalent data as # the mc_attribute_t structure ({at_name} {at_dtype} {at_value}) # The data you need to actually change the resource - also # check that the user did not supply any read_only attributes foreach $new_resource (@$rLoRsrcData) { ($rc, $rHoPAttr) = build_resource($resource, $new_resource, \%HoPAttrDefs, \%HoSDAttrDefs); if ($rc != 0) { # Do not continue if fatal RMC error ($rc == MC_CLI_USER_ERROR) || error_exit($rc); $badrc = $rc; next; } # If running in Verify mode, skip to next resource $Opt_Verify && next; # Build parameters for chrsrc-api command @chrsrcapi_parms = setup_chrsrcapi(\@chrsrcapi_parms, $resource, $r_rsrc_handle, $Opt_RSRC_Handle, $Opt_Ch_Class, $Opt_Ch_Class_DM, $peer_domains, $select_str, $rHoPAttr); } # end foreach $new_resource # Change the resource. $rc = change_resource(@chrsrcapi_parms); if ($rc != 0) { # Do not continue if fatal RMC error ($rc == MC_CLI_USER_ERROR) || error_exit($rc); $badrc = $rc; } ($badrc == 0) || error_exit($badrc); exit $rc; #--------------------------------------------------------------------# # End Main Code # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # parse_cmd_line - Parse the command line for options and operands. # # Set appropriate global variables as outlined below, make sure we # # have a valid combination of arguments / options. # # # # Return: # # $rc 0 Command line parsed fine, no problem. # # SR_CLI_BAD_FLAG Command line contained a bad flag. # # $resource Resource Class Name. # # $rsrc_file Name of file that contains rsrc data # # $select_str Selection String # # # # Global Variables Modified: # # $Opt_Ch_Class output True (-c) change resource class # # instead of changing the resource # # $Opt_Ch_Class_DM output True (-C) change resource class # # in peer domain. # # $Opt_RSRC_Handle output True (-r) operand will be a # # resource handle not a resource # # name. No -s or -c when -r. # # $Opt_File_Input output True (-f) read rsrc data from file. # # $Opt_Verify output True (-v) verify cmd line or file # # input is valid format. # # $Opt_Cmd_Cluster output True (-a) all nodes. # # $Verbose output True (-V) turn Verbose mode on. # # $Trace output True (-T) turn Trace mode on. # #--------------------------------------------------------------------# sub parse_cmd_line { my(@original_argv) = @ARGV; my $resource = ""; my $r_rsrc_handle = (); my $rsrc_file = ""; my $select_str = ""; my $peer_domains = ""; my $node_file_name= ""; my $rc; my %opts = (); # Process the command line... if (!GetOptions(\%opts, 'h|help|version' , 'a' , 'c' , 'r' , 'T' , 'v' , 'V' , 'C=s' , 'f=s' , 'N=s' , 's=s' )) { &print_usage; # display proper usage return MC_CLI_BAD_FLAG; # return bad rc - bad flag } # Always accept the -h help flag regardless of other flags or operands if (defined $opts{h}) { # -h, help request &print_usage; # print usage statement exit(0); # all done with good return! } # mkrsrc requires at a minimum the resource class name as an # operand. # Get the arguments... if ($#ARGV >= 0) { $resource = shift @ARGV; # user specified resource or # resource handle if -r } else { if (defined $opts{r}) { # Print Missing Resource Handle Operand message printCEMsg("EMsgMCcliMissingRsrcHandle"); } else { # Print Missing Resource Class Name Operand message printCEMsg("EMsgMCcliMissingRsrcClass"); } &print_usage; # display proper usage return MC_CLI_BAD_OPERAND; # return bad rc - bad operand } # Get the flags... if (defined $opts{c}) { # -c, change resource class $Opt_Ch_Class = $TRUE; } if (defined $opts{C}) { # -C, change resource class if (defined $opts{c}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-c", "-C"); &print_usage; return MC_CLI_BAD_FLAG; } $Opt_Ch_Class_DM = $TRUE; $peer_domains = $opts{C}; # input peer domain names } if (defined $opts{f}) { # -f, filename for rsrc data $Opt_File_Input = $TRUE; $rsrc_file = $opts{f}; # input rsrc file name if ($#ARGV >= 0) { # Print Too many operands message printCEMsg("EMsgMCcliTooManyOperands"); &print_usage; return MC_CLI_BAD_OPERAND; } } elsif (!defined $opts{r} && $#ARGV < 0) { # expecting some Attr=value pairs printCEMsg("EMsgMCcliMissingAttrAndValue"); &print_usage; return MC_CLI_BAD_OPERAND; } if (defined $opts{a}) { # -a, all nodes $Opt_Cmd_Cluster = $TRUE; } if (defined $opts{v}) { # -v, verify rsrc data input $Opt_Verify = $TRUE; } if (defined $opts{r}) { # -r, Resource Handle operand $Opt_RSRC_Handle = $TRUE; ($rc, $r_rsrc_handle) = string_to_rsrc_handle($resource); if ($rc != 0) { printCEMsg("EMsgMCcliBadRsrcHandle", $resource); &print_usage; return MC_CLI_BAD_OPERAND; $resource = ""; } if (defined $opts{c}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-c", "-r"); &print_usage; return MC_CLI_BAD_FLAG; } if (defined $opts{C}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-C", "-r"); &print_usage; return MC_CLI_BAD_FLAG; } } if (defined $opts{s}) { # -s, selection string $select_str = $opts{s}; # don't allow empty selection string if ($select_str =~ /^$/) { printCEMsg("EMsgMCcliSelectStrError"); &print_usage; return MC_CLI_BAD_OPERAND; } # A selection string cannot be specified with the -c or -r flags. if (defined $opts{c}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-s", "-c" ); &print_usage; return MC_CLI_BAD_FLAG; } if (defined $opts{r}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-s", "-r"); &print_usage; return MC_CLI_BAD_FLAG; } if (defined $opts{C}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-s", "-C"); &print_usage; return MC_CLI_BAD_FLAG; } } elsif (!defined $opts{c} && !defined $opts{r} && !defined $opts{C}) { # A selection string is required when changing a resource printCEMsg("EMsgMCcliMissingSelectionStr"); &print_usage; return MC_CLI_BAD_FLAG; } if (defined $opts{N}) { # -N, node file name if (!defined $opts{s}) { # A selection string is required when using -N printCEMsg("EMsgMCcliMissingSelectionStr"); &print_usage; return MC_CLI_BAD_FLAG; } elsif (defined $opts{r}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-N", "-r"); &print_usage; return MC_CLI_BAD_FLAG; } elsif (defined $opts{c}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-N", "-c" ); &print_usage; return MC_CLI_BAD_FLAG; } elsif (defined $opts{C}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-N", "-C" ); &print_usage; return MC_CLI_BAD_FLAG; } elsif (defined $opts{a}) { printCEMsg("EMsgMCcliImproperUsageCombination", "-N", "-a" ); &print_usage; return MC_CLI_BAD_FLAG; } elsif ($opts{N} eq "-") { $Opt_Stdin= $TRUE; } else { $node_file_name= $opts{N}; $rc= check_input_file($node_file_name); if ($rc) { return MC_CLI_BAD_OPERAND; } } $Opt_Node_File= $TRUE; } if (defined $opts{T}) { # -T, turns tracing on $Trace = $TRUE; } if (defined $opts{V}) { # -V, turns verbose on $Verbose = $TRUE; } return(0, $resource, $r_rsrc_handle, $rsrc_file, $select_str, $node_file_name, $peer_domains);# success } # end parse_cmd_line #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # # See this command's prologue syntax section for current usage. # #--------------------------------------------------------------------# sub print_usage { printIMsg("IMsgchrsrcUsage5"); } # end print_usage #--------------------------------------------------------------------# # get_sd_element_dtypes - for the specified attribute name return # # and array of this SDs element's data types in element index # # order. # # # # Parameters: # # %$rHoSDAttrDefs input Reference to a hash of persistent # # structured data attributes. # # key = attribute name # # data = array of hashes, each hash # # represents one of this SDs elements # # $attr_name input Attribute name. # # # # Return: # # @sd_element_dtypess Returns a reference to an array of # # the SD element data types in element # # index order for this attribute. # # # # Global References: # # None. # #--------------------------------------------------------------------# sub get_sd_element_dtypes { my ($rHoSDAttrDefs, $attr_name) = @_; my @sd_element_dtypes; my %index_to_dtype = (); my $element; my $element_cnt = 0; my @elements = keys %{ $rHoSDAttrDefs->{$attr_name} }; foreach $element (@elements) { $index = $rHoSDAttrDefs->{$attr_name}{$element}->{sd_index}; $index_to_dtype{$index} = $rHoSDAttrDefs->{$attr_name}{$element}->{sd_dtype}; $element_cnt++; } for ($i = 0; $i < $element_cnt; $i++) { push @sd_element_dtypes, $index_to_dtype{$i}; } return (@sd_element_dtypes); } # end get_sd_element_dtypes #--------------------------------------------------------------------# # process_input - process the attr=value pairs that are used to # # define this resource and were input by the user on the command # # line or via an input file. # # # # Parameters: # # $Opt_Input_File input True - input should come from file. # # False - input should come from command # # line. # # $filename input Name of file if $Opt_Input_File = TRUE # # $Opt_Ch_Class input True if looking for ResourceClass # # stanza in the input file. # # @$r_cmdline input Reference to attr=value pairs via # # command line and ARGV. # # # # Return: # # $rc return code. # # # # Global References: # # None. # #--------------------------------------------------------------------# sub process_input { my ($Opt_Input_File, $filename, $Opt_Ch_class, $r_cmdline) = @_; my $rc = 0; my $rLoRsrcData; if ($Opt_File_Input) { # Set the name of the stanza that should be in the input file my $file_stanza; if ($Opt_Ch_Class) { $file_stanza = "PersistentResourceClassAttributes"; } else { $file_stanza = "PersistentResourceAttributes"; } ($rc, $rLoRsrcData) = process_input_file($filename, $file_stanza); if ($rc != 0) { # Print Error processing input file msg # process_input_file will write a more detailed error message printEMsg("EMsgchrsrcInputFileError", $filename); return(MC_CLI_USER_ERROR); } } else { ($rc, $rLoRsrcData) = process_cmdline_input($r_cmdline); if ($rc != 0) { # Print Command Line Error Attr=value error msg printEMsg("EMsgchrsrcCmdLineError", "\"@$r_cmdline\""); return(MC_CLI_BAD_OPERAND); } } if ($Verbose) { my ($attribute, $value, $entry, $row_header); foreach $entry (@$rLoRsrcData) { $row_header = $entry->[0]; foreach $element (@{$entry->[1]}) { $attribute = $element->[0]; $value = $element->[1]; print "$attribute = \"$value\"\n"; } } } return ($rc, $rLoRsrcData); } # end process_input #--------------------------------------------------------------------# # build_resource - function to build up the hash of persistent attr # # to be used in defining the resource. Merging the {at_name}, # # {at_value}, {at_dtype} all into one structure and validating # # the input data as its processed. # # # # Parameters: # # $resource input Resource name. # # $rRsrcData input Reference to array of attr,value pairs.# # $rHoPAttrDefs input Reference to hash of all the required # # and optional attribute definitions # # for this resource. # # $rHoSDAttrDefs input Reference to hash of all the required # # and optional SD attribute definitions # # for this resource. # # # # Return: # # $rc return code. # # # # Global References: # # None. # #--------------------------------------------------------------------# sub build_resource { my ($resource, $rRsrcData, $rHoPAttrDefs, $rHoSDAttrDefs) = @_; my %HoPAttr = (); my @required_attributes = (); my ($new_attr, $dtype); my $badrc = 0; my $resource_def; foreach $new_attr (@{$rRsrcData->[1]}) { $attr_name = $new_attr->[0]; # first check to make sure this is a valid attribute name if (!defined($$rHoPAttrDefs{$attr_name})) { if ($Opt_File_Input) { $resource_def= $rRsrcData->[0]; $resource_def=~ s/^\s+//; $resource_def=~ s/\s+$//; printEMsg("EMsgchrsrcAttrNotDefForSet3", $attr_name, $resource, $resource_def); } else { printEMsg("EMsgchrsrcAttrNotDefForSet2", $attr_name, $resource); } $badrc = MC_CLI_USER_ERROR; next; # continue validating rest of input } # next check to make sure the value is of the right type # SDs require some special handling... $dtype = $$rHoPAttrDefs{$attr_name}{at_dtype}; if ( ($dtype =~ /^CT_SD_PTR$/) || ($dtype =~ /^CT_SD_PTR_ARRAY$/) ) { @r_sd_element_dtypes = get_sd_element_dtypes($rHoSDAttrDefs, $attr_name); ($rc, $attr_value) = convert_input_value_api($dtype, $new_attr->[1], \@r_sd_element_dtypes); } else { ($rc, $attr_value) = convert_input_value_api($dtype, $new_attr->[1]); } if ($rc != 0) { printCEMsg("EMsgMCcliBadAttrValue", $attr_name, $new_attr->[1]); if ($badrc == 0) {$badrc = $rc; } next; } %elements = (); $elements{at_name} = $attr_name; $elements{at_dtype} = $$rHoPAttrDefs{$attr_name}{at_dtype}; $elements{at_value} = $attr_value; # for 2 non-array values specified in a row, save the last value 131200 if (($#$attr_value >0) && ($dtype !~ /ARRAY/)) { $elements{at_value} = $$attr_value[$#$attr_value]; } # save original SD value if ( ($dtype =~ /^CT_SD_PTR$/) || ($dtype =~ /^CT_SD_PTR_ARRAY$/) ) { $elements{at_SD_value} = $new_attr->[1]; } $HoPAttr{$attr_name} = { %elements }; } return($badrc, \%HoPAttr); } # end build_resource #--------------------------------------------------------------------# # setup_chrsrcapi - function to add a parameter specification to be # # used later for chrsrc-api. # # # # Parameters: # # $chrsrcapi_parm in/out Name of the string variable that has # # any previous resource definition. # # $rsrc_class input Name of the resource class to which we # # want to change the resource. # # $res_handle input Resource handle to change. # # $handle_flag input True means resource handle used. # # $class_flag input True mean class attribute. # # $class_DM_flag input True mean class attribute for DM (-C). # # $pd_names input peer domain names for -C. # # $sel_str input Selection string. # # %$rHoAttr input Reference to complex hash of attribute # # names and value pairs. # # # # Return: # # $rc return code. # # # # Global References: # # Trace input Trace call & return of extension. # # Verbose input Print newly defined rsrc handle. # #--------------------------------------------------------------------# sub setup_chrsrcapi { my ($chrsrcapi_parm, $rsrc_class, $res_handle, $handle_flag, $class_flag, $class_DM_flag, $pd_names, $sel_str, $rHoAttr) = @_; my $newparms= ""; my $tmpparms= ""; my $i=0; my $j=0; my $comma = ""; # format being created: # -c ClassName::::::::::::::::::::{$attr}->{at_value}}); for ($j=0; $j<$i; $j++){ $tmpparms .= $comma . $rHoAttr->{$attr}->{at_value}[$j]; $comma = ","; } $tmpparms .= "}"; $comma = ""; $newparms .= $DELIMITER . $attr . $DELIMITER . $tmpparms; } else { $newparms .= $DELIMITER . $attr . $DELIMITER . $$rHoAttr{$attr}{at_value}; } } # check for any null attribute values # should be ok but chrsrc-api doesn't like it now $newparms =~ s/${DELIMITER}${DELIMITER}/${DELIMITER}''${DELIMITER}/g; $newparms =~ s/${DELIMITER}$/${DELIMITER}''/; # going to put double quotes around the whole thing so # escape any inner quotes $newparms = escape_chars($newparms); # now put quotes around the whole thing $newparms =~ s/^-s /-s \"/; $newparms =~ s/^-r /-r \"/; $newparms =~ s/^-c /-c \"/; $newparms =~ s/^-C /-C \"/; $newparms =~ s/^-w /-w \"/; $newparms =~ s/$/\"/; # append the new parameters to the existing one $i = $#$chrsrcapi_parm; if ( ($i<0) || (length($$chrsrcapi_parm[$i]) > $CMD_LIMIT) ) { $$chrsrcapi_parm[$i+1] .= " " . $newparms; } else { $$chrsrcapi_parm[$i] .= " " . $newparms; } return (@$chrsrcapi_parm); } # end setup_chrsrcapi #--------------------------------------------------------------------# # change_resource - function to call the chrsrc-api command to # # change one or more resources. # # # # Parameters: # # @parms input Parameter string to send to chrsrc-api.# # # # Return: # # $rc return code. # # # # Global References: # # Trace input Trace call & return of extension. # # Verbose input Print newly defined rsrc handle. # #--------------------------------------------------------------------# sub change_resource { my @parms = @_; my $rc = 0; my $i = 0; my @ch_out = (); for ($i=0; $i<=$#parms;$i++){ #$Verbose && printIMsg("IMsgmkrsrcDefiningRsrc", $rsrc_class); if ($main::Trace) { print STDERR "Calling chrsrc-api:\n"; print STDERR "chrsrc-api parameters:"; print STDERR "@parms\n"; } @ch_out = `$CTBINDIR/chrsrc-api -I $DELIMITER -D $DELIMITER $parms[$i] 2>&1`; # remove temp node file if from STDIN if ($Opt_Stdin) { unlink($node_file_name); } # capture the return code from chrsrc-api $rc = $?; $rc = process_exit_code($rc); if ($main::Trace) { print STDERR "chrsrc-api results:\n"; print STDERR "chrsrc-api returned $rc \n"; print STDERR "@ch_out"; print STDERR "Return from chrsrc-api\n"; } # show any errors if there was a bad rc if ($rc != 0) { process_api_error($DELIMITER,$rc,@ch_out); } } return $rc; } # end change_resource #--------------------------------------------------------------------# # error_check - checks the return code from the RMC function and # # the error response return code. If an error is detected # # appropriate error messages will be displayed. # # # # Parameters: # # $rmc_function in Name of the rmc function that was # # called and whose error code we are # # checking. # # $rmc_class in The rmc class name. # # $response in RMC response. # # $rmc_rc in The rmc function return code. # # $error in The error response. # # # # Return: # # $rc return code. # # # # Global References: # # None. # #--------------------------------------------------------------------# sub error_check { my ($rmc_function, $rmc_class, $response, $rmc_rc, $error) = @_; my $rc = 0; my $err_rc = $error->errnum(); # TODO: be able to handle resource handle from here too if ($rmc_rc != 0) { printEMsg("EMsgchrsrcChRsrcError", $rmc_class); my $rmc_rc_hex = sprintf "0x%8.8lx", $rmc_rc; printCEMsg("EMsgMCcliMCFunctionFailure", $rmc_function, $rmc_rc, $rmc_rc_hex); $rc = MC_CLI_RMC_ERROR; return $rc; } # Check the errnum in each of the RMC responses for (my $r = 0; $r < $response->array_count; $r++) { # get the error that goes with the specific response if ($r > 0) { $response->error($error, $r); $err_rc = $error->errnum(); } if ($err_rc != 0) { if ($err_rc == RMC_ECLASSNOTDEFINED) { printCEMsg("EMsgMCcliClassNotDef", $rmc_class); $rc = MC_CLI_USER_ERROR; } elsif ($err_rc == RMC_EBADRSRCHANDLE) { printEMsg("EMsgchrsrcBadRsrcHandle"); print STDERR $error->error_msg; $rc = MC_CLI_USER_ERROR; } elsif ($err_rc == RMC_ENORSRCSFOUND) { printCEMsg("EMsgMCcliNoRsrcFound"); $rc = MC_CLI_NO_RSRC_FOUND; } elsif ($err_rc == RMC_EACCESS) { print STDERR $error->error_msg; $rc = MC_CLI_USER_ERROR; } elsif ($err_rc >= 0x60000 && $err_rc <= 0x6ffff) { # Selection string errors are in this range printCEMsg("EMsgMCcliSelectStrError"); print STDERR $error->error_msg; $rc = MC_CLI_USER_ERROR; } else { printEMsg("EMsgchrsrcChRsrcError", $rmc_class); my $err_rc_hex = sprintf "0x%8.8lx", $err_rc; printCEMsg("EMsgMCcliMCFunctionFailure", $rmc_function, $err_rc, $err_rc_hex); print STDERR $error->error_msg; $rc = MC_CLI_RMC_ERROR; } } # end if } # end for return $rc; } # end error_check