# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. # # NAME # asmcmdattr - ASM CoMmanD line interface ATTRIBUTE operations # # DESCRIPTION # This module contains the code for ASMCMD/ASM attribute-related # operations, such as listing the contents of v$asm_attribute. # # NOTES # usage: asmcmdcore [-p] [command] # # MODIFIED (MM/DD/YY) # moreddy 01/13/11 - Backport moreddy_bug-8667038 from main # amitroy 04/20/10 - BUG 8933243 - USE DIFFERENT CHARACTER IN ASMCMD TO # "HIDE COLUMN DETAILS" INSTEAD OF -H # pvenkatr 03/31/10 - Syntax, description, example - all from XML # moreddy 03/22/10 - Adding more tracing # moreddy 01/08/10 - Adding trace messages # pvenkatr 09/03/09 - Help message from xml file. # sanselva 04/06/09 - ASMCMD long options and consistency # heyuen 10/14/08 - use dynamic modules # heyuen 09/10/08 - hide template attributes # heyuen 08/02/08 - display dgname in lsattr # heyuen 07/28/08 - use command properties array # heyuen 05/12/08 - remove attribute number and incarnation from lsattr # heyuen 04/22/08 - add order in lsattr # heyuen 04/15/08 - reorder help messages # heyuen 03/31/08 - add parameter check in lsattr # heyuen 02/12/08 - change help messages # heyuen 01/31/08 - fix unitialized variable untaint # heyuen 07/23/07 - creation # ############################################################################# # ############################ Functions List ################################# # asmcmdattr_init # asmcmdattr_process_cmd # asmcmdattr_is_cmd # asmcmdattr_process_lsattr # asmcmdattr_process_setattr # asmcmdattr_parse_int_args # asmcmdattr_get_asmcmd_cmds # asmcmdattr_is_no_instance_cmd # asmcmdattr_syntax_error # asmcmdattr_process_help ############################################################################# package asmcmdattr; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(asmcmdattr_init ); use strict; use Getopt::Long qw(:config no_ignore_case bundling); use asmcmdglobal; use asmcmdshare; use List::Util qw[min max]; ####################### ASMCMDATTR Global Constants ###################### # ASMCMD Column Header Names: # Below are the names of the column headers for lsattr. our (%asmcmdattr_lsattr_header) = ('group_name' , 'Group_Name', 'group_number' , 'Group_Num', 'attr_name' , 'Name', 'value' , 'Value', 'read_only' , 'RO', 'system_created' , 'Sys' ); ####################### ASMCMDATTR Global Variables ###################### our (%asmcmdattr_cmds) = (lsattr => {wildcard => 'True', no_instance => 'True', flags => {'m'=>'moreInformation', 'l'=>'longListing', 'G=s'=>'diskGroup', 'suppressheader'=> 'suppressHeaders'} }, setattr => {no_instance => 'True', flags => {'G=s'=>'diskGroup'} } ); sub is_asmcmd { return 1; } ######## # NAME # asmcmdattr_init # # DESCRIPTION # This function initializes the asmcmdattr module. For now it simply # registers its callbacks with the asmcmdglobal module. # # PARAMETERS # None # # RETURNS # Null # # NOTES # Only asmcmdcore_main() calls this routine. ######## sub init { # All of the arrays defined in the asmcmdglobal module must be # initialized here. Otherwise, an internal error will result. push (@asmcmdglobal_command_callbacks, \&asmcmdattr_process_cmd); push (@asmcmdglobal_help_callbacks, \&asmcmdattr_process_help); push (@asmcmdglobal_command_list_callbacks, \&asmcmdattr_get_asmcmd_cmds); push (@asmcmdglobal_is_command_callbacks, \&asmcmdattr_is_cmd); push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdattr_is_wildcard_cmd); push (@asmcmdglobal_syntax_error_callbacks, \&asmcmdattr_syntax_error); push (@asmcmdglobal_no_instance_callbacks, \&asmcmdattr_is_no_instance_cmd); %asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdattr_cmds); #Perform ASMCMD consistency check if enabled if($asmcmdglobal_hash{'consistchk'} eq 'y') { if(!asmcmdshare_check_option_consistency(%asmcmdattr_cmds)) { exit 1; } } } ######## # NAME # asmcmdattr_process_cmd # # DESCRIPTION # This routine calls the appropriate routine to process the command # specified by $asmcmdglobal_hash{'cmd'}. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # 1 if command is found in the asmcmdattr module; 0 if not. # # NOTES # Only asmcmdcore_shell() calls this routine. ######## sub asmcmdattr_process_cmd { my ($dbh) = @_; my ($succ) = 0; # Get current command from global value, which is set by # asmcmdtemplate_parse_asmcmd_args()and by asmcmdcore_shell(). my ($cmd) = $asmcmdglobal_hash{'cmd'}; # Declare and initialize hash of function pointers, each designating a # routine that processes an ASMCMDTEMPLATE command. my (%cmdhash) = ( lsattr => \&asmcmdattr_process_lsattr , setattr => \&asmcmdattr_process_setattr ); if (defined ( $cmdhash{ $cmd } )) { # If user specifies a known command, then call routine to process it. # $cmdhash{ $cmd }->($dbh); $succ = 1; } return $succ; } ######## # NAME # asmcmdattr_is_cmd # # DESCRIPTION # This routine checks if a user-entered command is one of the known # ASMCMD internal commands that belong to the ASMCMDATTR module. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # True if $arg is one of the known commands, false otherwise. ######## sub asmcmdattr_is_cmd { my ($arg) = shift; return defined ( $asmcmdattr_cmds{ $arg } ); } ######## # NAME # asmcmdattr_process_lsattr # # DESCRIPTION # This function processes the asmcmd command lsattr. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdattr_process_cmd() calls this function. ######## sub asmcmdattr_process_lsattr { my ($dbh) = shift; my (%args); my ($ret); my ($header, $pattern); my (@dgroups, %dgnmap); my (@what , @from, $sth, $qry, @where, @order, @tmp_cols); my ($k, $v, $row, $h); my (@attr_list); my (%x); my ($dgname, $meta, $vals); my (@cols); my (@select); my (%as); my ($gnum); my (%min_col_wid, $print_format, $printf_code, @what_print); # Get option parameters, if any. $ret = asmcmdattr_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); #Set the correct options if deprecated options were used and print WARNING. asmcmdshare_handle_deprecation($asmcmdglobal_hash{'cmd'},\%args); # get disk group names @dgroups = asmcmdshare_get_dg($dbh); foreach (@dgroups) { $dgnmap{$_->{'group_number'}} = $_->{'name'}; } if (defined($args{'G'})) { $dgname = $args{'G'}; $dgname =~ tr/a-z/A-Z/; $gnum = asmcmdshare_get_gnum_from_gname($dbh, $args{'G'}); if (!defined ($gnum)) { my (@eargs) = ($args{'G'}); asmcmdshare_error_msg(8001, \@eargs); return; } push (@where, "v\$asm_diskgroup_stat.name = '". $dgname . "'"); } # check if -m is specified $meta = defined($args{'m'}); # check if -l is specified $vals = defined($args{'l'}); # check if pattern is specified if (defined($ARGV[0])) { $pattern = $ARGV[0]; $pattern =~ s,$ASMCMDGLOBAL_WCARD_CHARS,\%,g; } @what = ('v$asm_attribute.name as attr_name'); if ($vals) { push (@what, 'v$asm_attribute.value'); } if ($meta) { @what = ('v$asm_diskgroup_stat.name as group_name', @what); push (@what, 'v$asm_attribute.read_only'); push (@what, 'v$asm_attribute.system_created'); } push (@from, 'v$asm_attribute'); push (@from, 'v$asm_diskgroup_stat'); push (@where, 'v$asm_diskgroup_stat.group_number = v$asm_attribute.group_number'); if ($pattern) { push (@where, 'v$asm_attribute.name LIKE \'%' . $pattern . '%\' '); } push (@where, 'v$asm_attribute.name not like \'template%\''); push (@order, 'v$asm_diskgroup_stat.name'); push (@order, 'v$asm_attribute.name'); $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where, \@order); asmcmdshare_trace(1, $DBI::errstr, 'y', 'y') unless defined ($sth); @tmp_cols = @{$sth->{NAME}}; @what = (); foreach (@tmp_cols) { push (@what, "\L$_"); } #initialize the min_col_wid array foreach(@what) { $min_col_wid{$_} = 0; } #get the rows while (defined($row = asmcmdshare_fetch($sth))) { my (%attr_info) = (); while(($k,$v) = each(%{$row})) { $k =~ tr/[A-Z]/[a-z]/; $attr_info{$k} = $v; $min_col_wid{$k} = max($min_col_wid{$k}, length($v)); } push (@attr_list, \%attr_info); } asmcmdshare_finish($sth); #get the header length foreach (@what) { $min_col_wid{$_} = max($min_col_wid{$_}, length($asmcmdattr_lsattr_header{$_})); } #create print format $print_format = ''; foreach (@what) { $print_format .= "%-$min_col_wid{$_}s "; } $print_format .= "\\n"; #print header if (!defined ($args{'suppressheader'}) ) { $printf_code = "printf \"$print_format\", "; @what_print = (); foreach (@what) { push (@what_print, "\'" . $asmcmdattr_lsattr_header{$_} . "\'"); } $printf_code .= "(" . join (", ", @what_print) . ")"; eval $printf_code; } #print rows foreach $h (@attr_list) { $printf_code = "printf \"$print_format\", "; @what_print = (); foreach (@what) { push (@what_print, "\'" . $h->{$_} . "\'"); } $printf_code .= "(" . join (", ", @what_print) . ")"; eval $printf_code; } return; } ######## # NAME # asmcmdattr_process_mkattr # # DESCRIPTION # This function processes the asmcmd command mkattr. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdattr_process_cmd() calls this function. ######## sub asmcmdattr_process_setattr { my ($dbh) = @_; my (%args); my ($ret); my ($sth, $qry, $dgname); my ($attr_name, $attr_val); # Get option parameters, if any. $ret = asmcmdattr_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); # get the diskgroup name if (!defined($args{'G'})) { asmcmdattr_syntax_error($asmcmdglobal_hash{'cmd'}); return; } $dgname = $args{'G'}; $dgname =~ tr/[a-z]/[A-Z]/; if (!defined($ARGV[0])) { asmcmdattr_syntax_error($asmcmdglobal_hash{'cmd'}); return; } if (!defined($ARGV[1])) { asmcmdattr_syntax_error($asmcmdglobal_hash{'cmd'}); return; } $attr_name = $ARGV[0]; $attr_val = $ARGV[1]; $qry = "ALTER DISKGROUP " . $dgname . " SET ATTRIBUTE "; $qry .= '\''. $attr_name . "\' = \'" . $attr_val . '\''; $ret = asmcmdshare_do_stmt($dbh, $qry); asmcmdshare_trace(1, $DBI::errstr, 'y', 'y') unless defined ($ret); } ######## # NAME # asmcmdattr_parse_int_args # # DESCRIPTION # This routine parses the arguments for flag options for ASMCMD internal # commands. # # PARAMETERS # cmd (IN) - user-entered command name string. # args_ref (OUT) - hash of user-specified flag options for a command, # populated by getopts(). # # RETURNS # Zero on success; undefined on error. # # NOTES # $cmd must already be verified as a valid ASMCMD internal command. ######## sub asmcmdattr_parse_int_args { my ($cmd, $args_ref) = @_; my ($key); my (@string); #build the list of options to parse using GetOptions if($asmcmdattr_cmds{ $cmd }{ flags }) { foreach $key(keys %{$asmcmdattr_cmds{ $cmd }{ flags }}) { push(@string, $key); } } #include deprecated options if any if($asmcmdglobal_deprecated_options{ $cmd }) { foreach my $key(keys %{$asmcmdglobal_deprecated_options{ $cmd }}) { push(@string, $asmcmdglobal_deprecated_options{$cmd}{$key}[0]); } } # Use GetOptions() from the Getopt::Long package to parse arguments for # internal commands. These arguments are stored in @ARGV. if (!GetOptions($args_ref,@string)) { # Print correct command format if syntax error. # asmcmdattr_syntax_error($cmd); return undef; } return 0; } ######## # NAME # asmcmdattr_get_asmcmd_cmds # # DESCRIPTION # This routine constructs a string that contains a list of the names of all # ASMCMD internal commands and returns this string. # # PARAMETERS # None. # # RETURNS # A string contain a list of the names of all ASMCMD internal commands. # # NOTES # Used by the help command and by the error command when the user enters # an invalid internal command. ######## sub asmcmdattr_get_asmcmd_cmds { return asmcmdshare_print_cmds(sort(keys %asmcmdattr_cmds)); } ######## # NAME # asmcmdattr_is_no_instance_cmd # # DESCRIPTION # This routine determines if a command can run without an ASM instance. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # True if $arg is a command that can run without an ASM instance # or does not exist, false otherwise. # # NOTES # ######## sub asmcmdattr_is_no_instance_cmd { my ($arg) = shift; return !defined ($asmcmdattr_cmds{ $arg }) || !defined ($asmcmdattr_cmds{ $arg }{ no_instance }); } ######## # NAME # asmcmdattr_syntax_error # # DESCRIPTION # This routine prints the correct syntax for a command to STDERR, used # when there is a syntax error. If the command with bad syntax is asmcmd # itself, then asmcmdbase_syntax_error also calls exit() to quit out. # # PARAMETERS # cmd (IN) - user-entered command name string. # # RETURNS # Exits if cmd is "asmcmd" or "asmcmd_no_conn_str"; 1 if another command # that belongs to this module; 0 if command not found. # # NOTES # These errors are user-errors and not internal errors. They are of type # record, not signal. Thus, even if exit() is called, the exit value is # zero. ######## sub asmcmdattr_syntax_error { my ($cmd) = shift; my ($cmd_syntax); # Correct syntax for $cmd. # my ($succ) = 0; # display syntax only for commands from this module. if (asmcmdattr_is_cmd($cmd)) { $cmd_syntax = asmcmdshare_get_help_syntax($cmd); # Get syntax for $cmd. # $cmd_syntax = asmcmdshare_trim_str ($cmd_syntax); if (defined ($cmd_syntax)) { print STDERR 'usage: ' . $cmd_syntax . "\n"; print STDERR 'help: help ' . $cmd . "\n"; $succ = 1; } } return $succ; } ######## # NAME # asmcmdattr_is_wildcard_cmd # # DESCRIPTION # This routine determines if an ASMCMDATTR command allows the use # of wild cards. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # True if $arg is a command that can take wildcards as part of its argument, # false otherwise. ######## sub asmcmdattr_is_wildcard_cmd { my ($arg) = shift; return defined ($asmcmdattr_cmds{ $arg }) && defined ($asmcmdattr_cmds{ $arg }{ wildcard }); } ######## # NAME # asmcmdattr_process_help # # DESCRIPTION # This function is the help function for the asmcmdattr module. # # PARAMETERS # command (IN) - display the help message for this command. # # RETURNS # 1 if command found; 0 otherwise. ######## sub asmcmdattr_process_help { my ($command) = shift; # User-specified argument; show help on $cmd. # my ($desc); # Command description for $cmd. # my ($succ) = 0; # 1 if command found, 0 otherwise. # if (asmcmdattr_is_cmd ($command)) { # User specified a command name to look up. # $desc = asmcmdshare_get_help_desc($command); print "$desc\n"; $succ = 1; } return $succ; } 1;