MINI MINI MANI MO
#
# $Header: rdbms/src/client/tools/asmcmd/modules/asmcmdqg.pm /main/4 2016/10/07 07:39:35 diguzman Exp $
#
# asmcmdqg.pm
#
# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
#
# NAME
# asmcmdqg.pm - ASM CoMmanD line interface Quota Group operations
#
# DESCRIPTION
# This module implements the asmcmd for quota group operations.
# 1. mkqg - add quota group to the disk group
# asmcmd> mkqg -G <diskgroup> <quotagroup> [ <property> <value> ]
# 2. rmqg - drop the quota group from the disk group
# asmcmd> rmqg -G <diskgroup> <quotagroup>
# 3. chqg - modify quota group property
# asmcmd> chqg -G <diskgroup> <quotagroup> <property> <value>
# 4. lsqg - list quota groups
# asmcmd> lsqg [-G <diskgroup>] [--quotagroup <quotagroup>]
# [--suppressheader]
# 5. mvfg - move file group to quota group
# asmcmd> mvfg -G <diskgroup> --filegroup <filegroup> <quotagroup>
#
# NOTES
# Project 47340: ASM Flex Disk Group - Quota Group
#
# MODIFIED (MM/DD/YY)
# diguzman 09/29/16 - 22847981: improve mkqg validations
# diguzman 05/30/16 - 19654070: Little change at _no_instance_cmd routine
# jesugonz 08/13/15 - 21507269: Change GB to MB in queries
# hpikkili 12/03/14 - proj47340: asmcmd for quota group
# hpikkili 12/03/14 - Creation
#
#############################################################################
#
############################ Functions List #################################
# asmcmdqg_init
# asmcmdqg_process_cmd
# asmcmdqg_is_cmd
# asmcmdqg_process_lsqg
# asmcmdqg_process_mkqg
# asmcmdqg_process_rmqg
# asmcmdqg_process_chqg
# asmcmdqg_process_mvfg
# asmcmdqg_parse_int_args
# asmcmdqg_get_asmcmd_cmds
# asmcmdqg_is_no_instance_cmd
# asmcmdqg_syntax_error
# asmcmdqg_is_wildcard_cmd
# asmcmdqg_process_help
#############################################################################
package asmcmdqg;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(asmcmdqg_init
);
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];
####################### ASMCMDQG Global Constants ######################
# ASMCMD Column Header Names:
# Below are the names of the column headers for lsqg. These headers are the
# ASMCMD equivalent of the columns of v$asm_quotagroup.
our (%asmcmdqg_lsqg_header) = ('group_number' , 'Group_Num',
'quotagroup_number' , 'Quotagroup_Num',
'name' , 'Quotagroup_Name',
'incarnation' , 'Incarnation',
'used_quota_mb' , 'Used_Quota_MB',
'quota_limit_mb' , 'Quota_Limit_MB'
);
####################### ASMCMDQG Global Variables ######################
#
# The following list is primarily used for is_cmd callback.
# All other data comes from XML.
#
our (%asmcmdqg_cmds) = (mkqg => {},
rmqg => {},
chqg => {},
lsqg => {},
mvfg => {}
);
sub is_asmcmd
{
return 1;
}
#############################################################################
# NAME
# asmcmdqg_init
#
# DESCRIPTION
# This function initializes the asmcmdqg module. For now it merely
# 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, \&asmcmdqg_process_cmd);
push (@asmcmdglobal_help_callbacks, \&asmcmdqg_process_help);
push (@asmcmdglobal_command_list_callbacks, \&asmcmdqg_get_asmcmd_cmds);
push (@asmcmdglobal_is_command_callbacks, \&asmcmdqg_is_cmd);
push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdqg_is_wildcard_cmd);
push (@asmcmdglobal_syntax_error_callbacks, \&asmcmdqg_syntax_error);
push (@asmcmdglobal_no_instance_callbacks, \&asmcmdqg_is_no_instance_cmd);
%asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdqg_cmds);
#Perform ASMCMD consistency check if enabled
if ($asmcmdglobal_hash{'consistchk'} eq 'y')
{
if (!asmcmdshare_check_option_consistency(%asmcmdqg_cmds))
{
exit 1;
}
}
}
#############################################################################
# NAME
# asmcmdqg_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 asmcmdqg module; 0 otherwise.
#
# NOTES
# Only asmcmdcore_shell() calls this routine.
#############################################################################
sub asmcmdqg_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) = ( mkqg => \&asmcmdqg_process_mkqg ,
rmqg => \&asmcmdqg_process_rmqg ,
chqg => \&asmcmdqg_process_chqg ,
lsqg => \&asmcmdqg_process_lsqg ,
mvfg => \&asmcmdqg_process_mvfg );
if (defined ( $cmdhash{ $cmd } ))
{ # If user specifies a known command, then call routine to process it. #
$cmdhash{ $cmd }->($dbh);
$succ = 1;
}
return $succ;
}
#############################################################################
# NAME
# asmcmdqg_is_cmd
#
# DESCRIPTION
# This routine checks if a user-entered command is one of the known ASMCMD
# internal commands that belong to the ASMCMDQG module.
#
# PARAMETERS
# arg (IN) - user-entered command name string.
#
# RETURNS
# True if $arg is one of the known commands, false otherwise.
#############################################################################
sub asmcmdqg_is_cmd
{
my ($arg) = shift;
return defined ( $asmcmdqg_cmds{ $arg } );
}
#############################################################################
# NAME
# asmcmdqg_process_lsqg
#
# DESCRIPTION
# This function processes the asmcmd command lsqg.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdqg_process_cmd() calls this function.
#############################################################################
sub asmcmdqg_process_lsqg
{
my ($dbh) = shift;
my (%args);
my ($ret);
my (@what , @from, $sth, $qry, @where, @order, @tmp_cols);
my ($k, $v, $row, $h);
my (@qglist) = ();
my ($qgname);
my ($gnum);
my (%min_col_wid, $print_format, $print_string, @what_print);
# Get option parameters, if any.
$ret = asmcmdqg_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
if (defined($args{'G'}))
{
$gnum = asmcmdshare_get_gnum_from_gname($dbh, $args{'G'});
if (!defined ($gnum))
{
my (@eargs) = ($args{'G'});
asmcmdshare_error_msg(8001, \@eargs);
return;
}
}
if (defined($args{'quotagroup'}))
{
$qgname = $args{'quotagroup'};
$qgname =~ tr/a-z/A-Z/;
}
@what_print = ();
if ($gnum && $qgname)
{
push (@what, 'v$asm_quotagroup.quotagroup_number');
push (@what, 'v$asm_quotagroup.incarnation');
push (@what, 'v$asm_quotagroup.used_quota_mb');
push (@what, 'v$asm_quotagroup.quota_limit_mb');
push (@where, "v\$asm_quotagroup.group_number = $gnum");
push (@where, "v\$asm_quotagroup.name = \'$qgname\'");
push (@what_print, $asmcmdqg_lsqg_header{'quotagroup_number'});
push (@what_print, $asmcmdqg_lsqg_header{'incarnation'});
push (@what_print, $asmcmdqg_lsqg_header{'used_quota_mb'});
push (@what_print, $asmcmdqg_lsqg_header{'quota_limit_mb'});
}
elsif ($gnum)
{
push (@what, 'v$asm_quotagroup.quotagroup_number');
push (@what, 'v$asm_quotagroup.name');
push (@what, 'v$asm_quotagroup.incarnation');
push (@what, 'v$asm_quotagroup.used_quota_mb');
push (@what, 'v$asm_quotagroup.quota_limit_mb');
push (@where, "v\$asm_quotagroup.group_number = $gnum");
push (@what_print, $asmcmdqg_lsqg_header{'quotagroup_number'});
push (@what_print, $asmcmdqg_lsqg_header{'name'});
push (@what_print, $asmcmdqg_lsqg_header{'incarnation'});
push (@what_print, $asmcmdqg_lsqg_header{'used_quota_mb'});
push (@what_print, $asmcmdqg_lsqg_header{'quota_limit_mb'});
}
elsif ($qgname)
{
push (@what, 'v$asm_quotagroup.group_number');
push (@what, 'v$asm_quotagroup.quotagroup_number');
push (@what, 'v$asm_quotagroup.incarnation');
push (@what, 'v$asm_quotagroup.used_quota_mb');
push (@what, 'v$asm_quotagroup.quota_limit_mb');
push (@where, "v\$asm_quotagroup.name = \'$qgname\'");
push (@order, 'v$asm_quotagroup.group_number');
push (@what_print, $asmcmdqg_lsqg_header{'group_number'});
push (@what_print, $asmcmdqg_lsqg_header{'quotagroup_number'});
push (@what_print, $asmcmdqg_lsqg_header{'incarnation'});
push (@what_print, $asmcmdqg_lsqg_header{'used_quota_mb'});
push (@what_print, $asmcmdqg_lsqg_header{'quota_limit_mb'});
}
else
{
push (@what, 'v$asm_quotagroup.group_number');
push (@what, 'v$asm_quotagroup.quotagroup_number');
push (@what, 'v$asm_quotagroup.name');
push (@what, 'v$asm_quotagroup.incarnation');
push (@what, 'v$asm_quotagroup.used_quota_mb');
push (@what, 'v$asm_quotagroup.quota_limit_mb');
push (@order, 'v$asm_quotagroup.group_number');
push (@what_print, $asmcmdqg_lsqg_header{'group_number'});
push (@what_print, $asmcmdqg_lsqg_header{'quotagroup_number'});
push (@what_print, $asmcmdqg_lsqg_header{'name'});
push (@what_print, $asmcmdqg_lsqg_header{'incarnation'});
push (@what_print, $asmcmdqg_lsqg_header{'used_quota_mb'});
push (@what_print, $asmcmdqg_lsqg_header{'quota_limit_mb'});
}
push (@from, 'v$asm_quotagroup');
push (@order, 'v$asm_quotagroup.quotagroup_number');
$sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where,
\@order);
@tmp_cols = @{$sth->{NAME}};
@what = ();
foreach (@tmp_cols)
{
push (@what, "\L$_");
}
%min_col_wid = ();
#initialize the min_col_wid array
foreach (@what)
{
$min_col_wid{$_} = length($asmcmdqg_lsqg_header{$_});
}
#get the rows
while (defined($row = asmcmdshare_fetch($sth)))
{
my (%info) = ();
while (($k,$v) = each(%{$row}))
{
$k =~ tr/[A-Z]/[a-z]/;
$info{$k} = $v;
$min_col_wid{$k} = max($min_col_wid{$k}, length($v));
}
push (@qglist, \%info);
}
asmcmdshare_finish($sth);
#create print format
$print_format = '';
foreach (@what)
{
$print_format .= "%-" . $min_col_wid{$_} . "s ";
}
$print_format .= "\n";
#print header if not suppressed and if #rows >= 1
if (defined ($args{'suppressheader'}) || ($#qglist lt 0))
{
@what_print = ();
}
else
{
$print_string = sprintf($print_format, @what_print);
asmcmdshare_print($print_string);
}
#print rows
foreach $h (@qglist)
{
@what_print = ();
foreach (@what)
{
push (@what_print, $h->{$_});
}
$print_string = sprintf($print_format, @what_print);
asmcmdshare_print($print_string);
}
return;
}
#############################################################################
# NAME
# asmcmdqg_process_mkqg
#
# DESCRIPTION
# This function processes the asmcmd command mkqg.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdqg_process_cmd() calls this function.
#############################################################################
sub asmcmdqg_process_mkqg
{
my $dbh = shift;
my $trim = 1;
my %args;
my $ret;
my $qry;
my $dgname;
my $qgname;
my $property;
my $value;
my $set;
# Get option parameters, if any.
$ret = asmcmdqg_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
# If there is an error with the generated SQL statement, avoid printing
# details regarding it unless trace level is set to 'debug'
undef $trim if ($asmcmdglobal_hash{'verbose'} =~ /^debug$/);
# get the disk group name
$dgname = uc($args{'G'});
# get the quota group name and any specified property
($qgname, $property, $value) = @{$args{'mkqg'}};
$qgname = uc($qgname);
$qry = "ALTER DISKGROUP $dgname ADD QUOTAGROUP $qgname";
if (defined($property))
{
$qry .= " SET $property = ";
$qry .= "$value" if (defined ($value));
}
$ret = asmcmdshare_do_stmt($dbh, $qry, $trim);
asmcmdshare_print "Diskgroup altered.\n" ;
}
#############################################################################
# NAME
# asmcmdqg_process_rmqg
#
# DESCRIPTION
# This function processes the asmcmd command rmqg.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdqg_process_cmd() calls this function.
#############################################################################
sub asmcmdqg_process_rmqg
{
my ($dbh) = @_;
my (%args);
my ($ret);
my ($qry);
my ($dgname, $qgname);
# Get option parameters, if any.
$ret = asmcmdqg_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
# get the disk group name
$dgname = $args{'G'};
$dgname =~ tr/[a-z]/[A-Z]/;
# get the quota group name
($qgname) = @{$args{'rmqg'}};
$qgname =~ tr/[a-z]/[A-Z]/;
$qry = "ALTER DISKGROUP " . $dgname . " DROP QUOTAGROUP " . $qgname;
$ret = asmcmdshare_do_stmt($dbh, $qry);
asmcmdshare_print "Diskgroup altered.\n" ;
}
#############################################################################
# NAME
# asmcmdqg_process_chqg
#
# DESCRIPTION
# This function processes the asmcmd command chqg.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdqg_process_cmd() calls this function.
#############################################################################
sub asmcmdqg_process_chqg
{
my ($dbh) = @_;
my (%args);
my ($ret);
my ($qry);
my ($dgname, $qgname, $property, $value);
# Get option parameters, if any.
$ret = asmcmdqg_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
# get the disk group name
$dgname = $args{'G'};
$dgname =~ tr/[a-z]/[A-Z]/;
# get the quota group name and any specified property
($qgname, $property, $value) = @{$args{'chqg'}};
$qgname =~ tr/[a-z]/[A-Z]/;
$qry = "ALTER DISKGROUP " . $dgname . " MODIFY QUOTAGROUP " . $qgname;
if (defined($property))
{
$qry .= " SET $property = ";
if (defined ($value))
{
$qry .= $value;
}
}
$ret = asmcmdshare_do_stmt($dbh, $qry);
asmcmdshare_print "Diskgroup altered.\n" ;
}
#############################################################################
# NAME
# asmcmdqg_process_mvfg
#
# DESCRIPTION
# This function processes the asmcmd command mvfg.
#
# PARAMETERS
# dbh (IN) - initialized database handle, must be non-null.
#
# RETURNS
# Null.
#
# NOTES
# Only asmcmdqg_process_cmd() calls this function.
#############################################################################
sub asmcmdqg_process_mvfg
{
my ($dbh) = @_;
my (%args);
my ($ret);
my ($qry);
my ($dgname, $qgname, $filegroup);
# Get option parameters, if any.
$ret = asmcmdqg_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
return unless defined ($ret);
# get the disk group name
$dgname = $args{'G'};
$dgname =~ tr/[a-z]/[A-Z]/;
# get the file group name
$filegroup = $args{'filegroup'};
$filegroup =~ tr/[a-z]/[A-Z]/;
# get the quota group name and any specified property
($qgname) = @{$args{'mvfg'}};
$qgname =~ tr/[a-z]/[A-Z]/;
$qry = "ALTER DISKGROUP " . $dgname . " MOVE FILEGROUP " . $filegroup;
$qry .= " TO " . $qgname;
$ret = asmcmdshare_do_stmt($dbh, $qry);
asmcmdshare_print "Diskgroup altered.\n" ;
}
#############################################################################
# NAME
# asmcmdqg_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 asmcmdqg_parse_int_args
{
my ($cmd, $args_ref) = @_;
my ($key);
my (@string);
#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 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))
{
# Print correct command format if syntax error. #
asmcmdqg_syntax_error($cmd);
return undef;
}
return 0;
}
#############################################################################
# NAME
# asmcmdqg_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 asmcmdqg_get_asmcmd_cmds
{
return asmcmdshare_filter_invisible_cmds(%asmcmdqg_cmds);
}
#############################################################################
# NAME
# asmcmdqg_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
#
#############################################################################
sub asmcmdqg_is_no_instance_cmd
{
my ($arg) = shift;
my ($rc);
return 1 unless defined($asmcmdqg_cmds{$arg});
$rc = asmcmdshare_get_cmd_noinst($arg);
if ($rc eq "true")
{
return 1;
}
elsif ($rc eq "undef")
{
return -1;
}
return 0;
}
#############################################################################
# NAME
# asmcmdqg_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 asmcmdqg_syntax_error
{
my ($cmd) = shift;
my ($cmd_syntax); # Correct syntax for $cmd. #
my ($succ) = 0;
# display syntax only for commands from this module.
if (asmcmdqg_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
# asmcmdqg_is_wildcard_cmd
#
# DESCRIPTION
# This routine determines if an ASMCMDQG 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 asmcmdqg_is_wildcard_cmd
{
my ($arg) = shift;
return (defined ($asmcmdqg_cmds{ $arg }) &&
(asmcmdshare_get_cmd_wildcard($arg) eq "true"));
}
#############################################################################
# NAME
# asmcmdqg_process_help
#
# DESCRIPTION
# This function is the help function for the asmcmdqg module.
#
# PARAMETERS
# command (IN) - display the help message for this command.
#
# RETURNS
# 1 if command found; 0 otherwise.
#############################################################################
sub asmcmdqg_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 (asmcmdqg_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;
}
1;
OHA YOOOO