MINI MINI MANI MO

Path : /opt/oracle/product/18c/dbhomeXE/lib/
File Upload :
Current File : //opt/oracle/product/18c/dbhomeXE/lib/asmcmdtmpl.pm

# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
#    NAME
#      asmcmdtmpl - ASM CoMmanD line interface TEMPLATE operations
#
#    DESCRIPTION
#      This module contains the code for ASMCMD/ASM template-related
#      operations, such as listing the contents of v$asm_template.
#
#    NOTES
#      usage: asmcmdcore [-p] [command]
#
#    MODIFIED  (MM/DD/YY)
#    diguzman   05/30/16 - 19654070: Little change at _no_instance_cmd routine
#    ykatada    10/03/14 - #19617921: use bind variables to SELECTs
#    pvenkatr   02/01/13 - Using asmcmdshare_filter_invisible_cmds
#    pvenkatr   10/07/11 - Removed asmcmdtmpl_get_cmd_syntax - unused function.
#    pvenkatr   08/24/11 - Removed flags hash table - using from XML
#    adileepk   06/20/11 - Connection Pooling.
#    adileepk   10/12/10 - Changes made to integrate the parser module with
#                          asmcmd.
#    adileepk   09/01/10 - Bug 8693719 - Added validation for diskgroup name.
#    moreddy    05/06/10 - bug 8667038 NLS for error messages
#    amitroy    04/21/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/18/10 - Adding tracing messages
#    pvenkatr   09/03/09 - Help message from xml file
#    sanselva   06/17/09 - correct check for --primary and --secondary
#    sanselva   04/06/09 - ASMCMD long options and consistency
#    heyuen     10/14/08 - use dynamic modules
#    heyuen     07/28/08 - use command properties array
#    heyuen     05/27/08 - remove entry_number field
#    heyuen     04/15/08 - rename zones to regions
#    heyuen     07/23/07 - creation
#
#############################################################################
#
############################ Functions List #################################
# asmcmdtmpl_init
# asmcmdtmpl_process_cmd 
# asmcmdtmpl_process_lstmpl
# asmcmdtmpl_process_mktmpl
# asmcmdtmpl_process_chtmpl
# asmcmdtmpl_process_rmtmpl
# asmcmdtmpl_is_cmd 
# asmcmdtmpl_is_no_instance_cmd 
# asmcmdtmpl_parse_int_args
# asmcmdtmpl_syntax_error 
# asmcmdtmpl_process_help 
# asmcmdtmpl_get_asmcmd_cmds 
#############################################################################

package asmcmdtmpl;
require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(asmcmdtmpl_init
                 %asmcmdtmpl_cmds
                );

use strict;
use DBI qw(:sql_types);
use Getopt::Long qw(:config no_ignore_case bundling);
use asmcmdglobal;
use asmcmdshare;
use asmcmdparser;

use List::Util qw[min max];

####################### ASMCMDTMPL Global Constants ######################
# ASMCMD Column Header Names:
# Below are the names of the column headers for lstmpl.
our (%asmcmdtmpl_lstmpl_header) = ('inst_id'      , 'Inst_Id',
                                   'group_name'   , 'Group_Name',
                                   'name'         , 'Name',
                                   'stripe'       , 'Stripe',
                                   'system'       , 'Sys',
                                   'redundancy'   , 'Redund',
                                   'group_number' , 'Group_Num',
                                   'primary_region' , 'PriReg',
                                   'mirror_region'  , 'MirrReg'
                                  );

our (%asmcmdtmpl_cmds) = (lstmpl => {},
                          mktmpl => {},
                          chtmpl => {},
                          rmtmpl => {}
                         );

####################### ASMCMDTMPL Global Variables ######################

sub is_asmcmd
{
  return 1;
}

########
# NAME
#   asmcmdtmpl_init
#
# DESCRIPTION
#   This function initializes the asmcmdtmpl 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
{
  push (@asmcmdglobal_command_callbacks, \&asmcmdtmpl_process_cmd);
  push (@asmcmdglobal_help_callbacks, \&asmcmdtmpl_process_help);
  push (@asmcmdglobal_command_list_callbacks, \&asmcmdtmpl_get_asmcmd_cmds);
  push (@asmcmdglobal_is_command_callbacks, \&asmcmdtmpl_is_cmd);
  push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdtmpl_is_wildcard_cmd);
  push (@asmcmdglobal_syntax_error_callbacks, \&asmcmdtmpl_syntax_error);
  push (@asmcmdglobal_no_instance_callbacks, \&asmcmdtmpl_is_no_instance_cmd);
  %asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdtmpl_cmds);

  #Perform ASMCMD consistency check if enabled
  if($asmcmdglobal_hash{'consistchk'} eq 'y')
  {
     if(!asmcmdshare_check_option_consistency(%asmcmdtmpl_cmds))
     {
       exit 1;
     }
  }

}


########
# NAME
#   asmcmdtmpl_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 asmcmdtmpl module; 0 if not.
#
# NOTES
#   Only asmcmdcore_shell() calls this routine.
########
sub asmcmdtmpl_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) = ( lstmpl      => \&asmcmdtmpl_process_lstmpl,
                    mktmpl      => \&asmcmdtmpl_process_mktmpl,
                    chtmpl      => \&asmcmdtmpl_process_chtmpl,
                    rmtmpl      => \&asmcmdtmpl_process_rmtmpl );

  if (defined ( $cmdhash{ $cmd } ))
  {    # If user specifies a known command, then call routine to process it. #
    $cmdhash{ $cmd }->($dbh);
    $succ = 1;
  }

  return $succ;
}


########
# NAME
#   asmcmdtmpl_process_lstmpl
#
# DESCRIPTION
#   This function processes the asmcmd command lstmpl.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdtmpl_process_cmd() calls this function.
########
sub asmcmdtmpl_process_lstmpl
{
  my ($dbh) = shift;

  my (%args);
  my ($qry, $ret);
  my (@what , @from, $sth, @where, @order, @binds);
  my (@cols, @dgroups, %dgnmap);
  my ($dgname, $dgnum, $meta, $vals);
  my ($header, $pattern);
  my (%as);
  my (@tmpl_list);
  my ($row, $k, $v, $h);
  my (@eargs);

  my (%min_col_wid, $print_format, $print_string, @what_print);

  # Get option parameters, if any.
  $ret = asmcmdtmpl_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 disk group is specified, filter out
  if (defined($args{'G'}))
  {
    $dgname = $args{'G'};
    $dgname =~ tr/[a-z]/[A-Z]/;
    $dgnum = asmcmdshare_get_gnum_from_gname($dbh, $dgname);
    if (!defined($dgnum))
    {  
      @eargs = ($dgname);
      asmcmdshare_error_msg(8001, \@eargs);
      return;
    }
  }

  # check if -l is specified
  $vals   = defined($args{'l'});

  # check if pattern is specified
  if (defined($args{'lstmpl'}))
  {
    ($pattern) = @{$args{'lstmpl'}};
    $pattern =~ s,$ASMCMDGLOBAL_WCARD_CHARS,\%,g;
  }

  push (@what, 'group_number');
  push (@what, 'name');

  push (@order, 'group_number');
  push (@order, 'name');

  # add extra columns if specified
  if ($vals)
  {
    push (@what, 'stripe');
    push (@what, 'system');
    push (@what, 'redundancy');
    push (@what, 'primary_region');
    push (@what, 'mirror_region');
  }

  # filter out template name
  if ($pattern)
  {
    my ($like_pattern);

    $pattern =~ tr/[a-z]/[A-Z]/;
    $like_pattern = '%' . $pattern . '%';

    push (@where, 'name LIKE ?');
    push (@binds, [$like_pattern, SQL_VARCHAR]);
  }

  # filter out diskgroup
  if (defined($dgnum))
  {
    push (@where, 'group_number = ?');
    push (@binds, [$dgnum, SQL_INTEGER]);
  }

  push (@from, 'v$asm_template');

  $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where,
                                         \@order, \@binds);

  #initialize the min_col_wid array
  foreach(@what)
  {
    $min_col_wid{$_} = 0;
  }
  $min_col_wid{'group_name'} = 0;

  #get the rows
  while (defined($row = asmcmdshare_fetch($sth)))
  {
    my(%tmpl_info) = ();

    while(($k, $v) = each(%{$row}))
    {
      $k =~ tr/[A-Z]/[a-z]/;
      $tmpl_info{$k} = $v;

      $min_col_wid{$k} = max($min_col_wid{$k}, length($v));
    }

    if (defined($tmpl_info{'group_number'}))
    {
      $tmpl_info{'group_name'} = $dgnmap{$tmpl_info{'group_number'}};

      $min_col_wid{'group_name'} = max( $min_col_wid{'group_name'},
                                        length($tmpl_info{'group_name'}));
    }

    push (@tmpl_list, \%tmpl_info);
  }
  asmcmdshare_finish($sth);

  # add the group_name column at the beginning, we do this because it was not
  # part of the query
  unshift @what, "group_name";

  #get the header length
  foreach (@what)
  {
    $min_col_wid{$_} = max($min_col_wid{$_}, 
                           length($asmcmdtmpl_lstmpl_header{$_}));
  }

  #create print format
  $print_format = '';

  foreach (@what)
  {
    $print_format .= "%-" . $min_col_wid{$_} . "s  ";
  }
  $print_format .= "\n";

  #print header
  if (!defined ($args{'suppressheader'}) )
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $asmcmdtmpl_lstmpl_header{$_} );
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }

  #print rows
  foreach $h (@tmpl_list)
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $h->{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }
}

########
# NAME
#   asmcmdtmpl_process_mktmpl
#
# DESCRIPTION
#   This function processes the asmcmd command mktmpl.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdtmpl_process_cmd() calls this function.
########
sub asmcmdtmpl_process_mktmpl
{
  my ($dbh) = shift;

  my (%args);
  my ($qry, $ret);
  my ($redun, $pri_zn, $sec_zn, $dgname);
  my ($name);
  my (@attrs);

  # Get option parameters, if any.
  $ret = asmcmdtmpl_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); 
  return unless defined ($ret);

  $dgname = $args{'G'};

  ($name) = @{$args{'mktmpl'}};

  #striping
  if (defined($args{'striping'}))
  {
    push (@attrs, 'COARSE') if ($args{'striping'} eq 'coarse');
    push (@attrs, 'FINE')   if ($args{'striping'} eq 'fine');
  }

  #redundancy
  if (defined($args{'redundancy'}))
  {
    $redun = $args{'redundancy'};
    push (@attrs, 'UNPROTECTED') if ($redun eq 'unprotected');
    push (@attrs, 'MIRROR')      if ($redun eq 'mirror');
    push (@attrs, 'HIGH')        if ($redun eq 'high');
  }

  #pri-zone
  if (defined($args{'primary'}))
  {
    $pri_zn = $args{'primary'};
    if($pri_zn eq 'hot')
    {
      push (@attrs, 'HOT');
    }
    elsif($pri_zn eq 'cold')
    {
      push (@attrs, 'COLD');
    }
  }

  #sec zone
  if (defined($args{'secondary'}))
  {
    $sec_zn = $args{'secondary'};
    if($sec_zn eq 'hot')
    {
      push (@attrs, 'MIRRORHOT');
    }
    elsif($sec_zn eq 'cold')
    {
      push (@attrs, 'MIRRORCOLD');
    }
  }

  $qry = "ALTER DISKGROUP " . $dgname . " ADD TEMPLATE " . $name;

  if (@attrs)
  {
    $qry .= ' ATTRIBUTES(' .join(' ', @attrs) . ')';
  }

  $ret= asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdtmpl_process_chtmpl
#
# DESCRIPTION
#   This function processes the asmcmd command chtmpl.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdtmpl_process_cmd() calls this function.
########
sub asmcmdtmpl_process_chtmpl
{
  my ($dbh) = @_;
  my (%args);
  my ($qry, $ret);
  my ($redun, $pri_zn, $sec_zn, $dgname);
  my ($name);
  my (@attrs);

  # Get option parameters, if any.
  $ret = asmcmdtmpl_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); 
  return unless defined ($ret);

  # get the diskgroup name
  $dgname = $args{'G'};

  # get the template name
  ($name) = @{$args{'chtmpl'}};

  $qry = "ALTER DISKGROUP " . $dgname . " MODIFY TEMPLATE " . $name;

  #striping
  if (defined($args{'striping'}))
  {
      push (@attrs, 'COARSE') if ($args{'striping'} eq 'coarse');
      push (@attrs, 'FINE')   if ($args{'striping'} eq 'fine');
  }

  #redundancy
  if (defined($args{'redundancy'}))
  {
      $redun = $args{'redundancy'};
      push (@attrs, 'UNPROTECTED')  if ($redun eq 'unprotected');
      push (@attrs, 'MIRROR')       if ($redun eq 'mirror');
      push (@attrs, 'HIGH')         if ($redun eq 'high');
  }

  #pri-zone
  if (defined($args{'primary'}))
  {
      $pri_zn = $args{'primary'};
      if($pri_zn eq 'hot')
      {
        push (@attrs, 'HOT');
      }
      elsif($pri_zn eq 'cold')
      {
        push (@attrs, 'COLD');
      }
 }

  #sec zone
  if (defined($args{'secondary'}))
  {
      $sec_zn = $args{'secondary'};
      if($sec_zn eq 'hot')
      {
        push (@attrs, 'MIRRORHOT');
      }
      elsif($sec_zn eq 'cold')
      {
        push (@attrs, 'MIRRORCOLD');
      }
  }

  if (@attrs)
  {
    $qry .= ' ATTRIBUTES(' .join(' ', @attrs) . ')';
  }

  $ret= asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdtmpl_process_rmtmpl
#
# DESCRIPTION
#   This function processes the asmcmd command rmtmpl.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdtmpl_process_cmd() calls this function.
########
sub asmcmdtmpl_process_rmtmpl
{
  my ($dbh) = shift;

  my (%args);
  my ($qry, $ret);
  my ($dgname, $name);

  # Get option parameters, if any.
  $ret = asmcmdtmpl_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); 
  return unless defined ($ret);

  # get the diskgroup name
  $dgname = $args{'G'};

  # get the template name
  ($name) = @{$args{'rmtmpl'}};

  $qry = "ALTER DISKGROUP " . $dgname . " DROP TEMPLATE " . $name;

  $ret= asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdtmpl_is_cmd
#
# DESCRIPTION
#   This routine checks if a user-entered command is one of the known
#   ASMCMD internal commands that belong to the ASMCMDTMPL module.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   True if $arg is one of the known commands, false otherwise.
########
sub asmcmdtmpl_is_cmd 
{
  my ($arg) = shift;

  return defined ( $asmcmdtmpl_cmds{ $arg } );
}


########
# NAME
#   asmcmdtmpl_is_wildcard_cmd
#
# DESCRIPTION
#   This routine determines if an ASMCMDTMPL 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 asmcmdtmpl_is_wildcard_cmd 
{
  my ($arg) = shift;

  return defined ($asmcmdtmpl_cmds{ $arg }) &&
         (asmcmdshare_get_cmd_wildcard($arg) eq "true");
}


########
# NAME
#   asmcmdtmpl_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
#   1 if $arg is a command that can run without an ASM instance or it does not
#   belong to this module
#   0 if $arg is a command that needs to connect to an ASM instance
#   -1 if $arg is a command that may use an ASM instance.
#
# NOTES
#   The asmcmdtmpl module currently supports only the help as a command
#   that does not require an ASM instance.
########
sub asmcmdtmpl_is_no_instance_cmd 
{
  my ($arg) = shift;
  my ($rc);

  return 1 unless defined($asmcmdtmpl_cmds{$arg});

  $rc = asmcmdshare_get_cmd_noinst($arg);
  if ($rc eq "true")
  {
    return 1;
  }
  elsif ($rc eq "undef")
  {
    return -1;
  }

  return 0;
}


########
# NAME
#   asmcmdtmpl_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 asmcmdtmpl_parse_int_args
{
  my ($cmd, $args_ref) = @_;
  my @string;
  my $key;

  #include deprecated options if any
  if($asmcmdglobal_deprecated_options{ $cmd })
  {
    foreach $key(keys %{$asmcmdglobal_deprecated_options{ $cmd }})
    {
      push(@string, $asmcmdglobal_deprecated_options{$cmd}{$key}[0]);
    }
  }

  # Use asmcmdparser_parse_issued_command() from the asmcmdparser package to parse arguments for
  # internal commands.  These arguments are stored in @ARGV.
  # if (!asmcmdparser_parse_issued_command($cmd, $args_ref, \@string))
  if (!asmcmdparser_parse_issued_command($cmd, $args_ref, \@string))
  {
    # Print correct command format if syntax error. #
    asmcmdtmpl_syntax_error($cmd);
    return undef;
  }

  return 0;
}


########
# NAME
#   asmcmdtmpl_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
#   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 asmcmdtmpl_syntax_error 
{
  my ($cmd) = shift;
  my ($cmd_syntax);                               # Correct syntax for $cmd. #
  my ($succ) = 0;

  if (asmcmdtmpl_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))
    {
       asmcmdshare_printstderr 'usage: ' . $cmd_syntax . "\n";
       asmcmdshare_printstderr 'help:  help ' . $cmd . "\n";
       $succ = 1;
    }
  }

  return $succ;
}



########
# NAME
#   asmcmdtmpl_process_help
#
# DESCRIPTION
#   This function is the help function for the asmcmdtmpl module.
#
# PARAMETERS
#   command     (IN) - display the help message for this command.
#
# RETURNS
#   1 if command found; 0 otherwise.
########
sub asmcmdtmpl_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 (asmcmdtmpl_is_cmd ($command)) 
  {                              # User specified a command name to look up. #
    $desc = asmcmdshare_get_help_desc($command);
    asmcmdshare_print "$desc\n";
    $succ = 1;
  }

  return $succ;
}


########
# NAME
#   asmcmdtmpl_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 asmcmdtmpl_get_asmcmd_cmds 
{
  return asmcmdshare_filter_invisible_cmds(%asmcmdtmpl_cmds);
}
1;

OHA YOOOO