# # $Header: has/install/crsconfig/oraClusterwareComp.pm /main/4 2015/04/21 21:44:55 muhe Exp $ # # oraClusterwareComp.pm # # Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. # # NAME # oraClusterwareComp.pm - class to define interfaces for Oracle Clusterware components # # DESCRIPTION # oraClusterwareComp is a base class that defines all needed interfaces # for Oracle Clusterware components. All component classes should inherit # from this base class, and override all interfaces defined in this class. # # NOTES # # # MODIFIED (MM/DD/YY) # muhe 04/12/15 - Add pre check interfaces for upgrade and patch # luoli 12/23/14 - rsc modeling for downgrade/deconfig # xyuan 11/05/14 - Adding SIHA steps # xyuan 07/17/14 - Creation # package oraClusterwareComp; use strict; use English; use Exporter; use Carp; use crsutils; sub new { my $class = shift; my $self = {}; # Pass the component name into the constructor $self->{compName} = shift; bless $self, $class; return $self; } # This can be overrided by derived classes, and called in subclass's # own constructor. # The derived class shall look at the variables it is interested in # and populate its member data. All variables used by a given component # must be clearly documented here. Any further validation of values # received can be done here. sub _initialize { my $self = shift; my $className = ref($self); trace("Initializing ..., the name of the class that " . "the object has been blessed into: $className"); } # # Object accessor methods # # set/get the description name of component sub compName { my $self = shift; if (@_) { $self->{compName} = shift; } return $self->{compName}; } # # The method for configuring the current node for fresh install sub configureCurrentNode { my $self = shift; my $stepIndicator = shift; my $nodeAttr = $CFG->nodeAttributeConfig; if (FIRST_NODE_TO_CONFIG eq $nodeAttr) { $self->configureFirstNode($stepIndicator); } elsif (NONFIRST_NODE_TO_CONFIG eq $nodeAttr) { $self->configureNonFirstNode($stepIndicator); } elsif (SIHA_NODE_TO_CONFIG eq $nodeAttr) { $self->configureSIHA($stepIndicator); } else { # Should not reach here croak "Invalid node attribute for fresh install: $nodeAttr"; } } # # Configure action on current node for fresh install after # the configured stack has been started sub postConfigureCurrentNode { my $self = shift; my $nodeAttr = $CFG->nodeAttributeConfig; if (FIRST_NODE_TO_CONFIG eq $nodeAttr) { $self->postConfigFirstNode(); } elsif (NONFIRST_NODE_TO_CONFIG eq $nodeAttr) { $self->postConfigNonFirstNode(); } elsif (SIHA_NODE_TO_CONFIG eq $nodeAttr) { $self->postConfigureSIHA(); } else { # Should not reach here croak "Invalid node attribute for fresh install: $nodeAttr"; } } # # The method for node-wise local checks before upgrading the node. # The method can be called when local pre checks for related component are needed. # The stack might be up or down when calling this method. sub upgradeCheckCurrentNode { my $self = shift; my $nodeAttr = $CFG->nodeAttributeUpgrade; if (FIRST_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeCheckFirstNode(); } elsif (MIDDLE_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeCheckMiddleNode(); } elsif (LAST_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeCheckLastNode(); } elsif (SIHA_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeCheckSIHA(); } else { # Should not reach here croak "Invalid node attribute for upgrade checks: $nodeAttr"; } } # # The method for configuring the current node for upgrade sub upgradeCurrentNode { my $self = shift; my $stepIndicator = shift; my $nodeAttr = $CFG->nodeAttributeUpgrade; if (FIRST_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeFirstNode($stepIndicator); } elsif (MIDDLE_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeMiddleNode($stepIndicator); } elsif (LAST_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeLastNode($stepIndicator); } elsif (SIHA_NODE_TO_UPGRADE eq $nodeAttr) { $self->upgradeSIHA($stepIndicator); } else { # Should not reach here croak "Invalid node attribute for upgrade: $nodeAttr"; } } # # Upgrade action on current node after the higher version stack # has been started sub postUpgradeCurrentNode { my $self = shift; my $nodeAttr = $CFG->nodeAttributeUpgrade; if (FIRST_NODE_TO_UPGRADE eq $nodeAttr) { $self->postUpgradeFirstNode(); } elsif (MIDDLE_NODE_TO_UPGRADE eq $nodeAttr) { $self->postUpgradeMiddleNode(); } elsif (LAST_NODE_TO_UPGRADE eq $nodeAttr) { $self->postUpgradeLastNode(); } elsif (SIHA_NODE_TO_UPGRADE eq $nodeAttr) { $self->postUpgradeSIHA(); } else { # Should not reach here croak "Invalid node attribute for upgrade: $nodeAttr"; } } # # The method for configuring the current node for downgrade sub downgradeCurrentNode { my $self = shift; my $stepIndicator = shift; my $nodeAttr = $CFG->nodeAttributeDowngrade; if (NONLAST_NODE_TO_DOWNGRADE eq $nodeAttr) { $self->downgradeNonLastNode($stepIndicator); } elsif (LAST_NODE_TO_DOWNGRADE eq $nodeAttr) { $self->downgradeLastNode($stepIndicator); } else { # Should not reach here croak "Invalid node attribute for downgrade: $nodeAttr"; } } # # The method for de-configuring the current node sub deconfigureCurrentNode { my $self = shift; my $stepIndicator = shift; my $nodeAttr = $CFG->nodeAttributeDeconfigure; if (NONLAST_NODE_TO_DECONFIGURE eq $nodeAttr) { $self->deconfigureNonLastNode($stepIndicator); } elsif (LAST_NODE_TO_DECONFIGURE eq $nodeAttr) { $self->deconfigureLastNode($stepIndicator); } else { # Should not reach here croak "Invalid node attribute for deconfiguration: $nodeAttr"; } } # # Interfaces (forced) to be re-implemented in derived classes # # Each Clusterware component, which inherits from this class, should # reimplement (override) the following methods: # # Is the component supported based on platform and user input sub isSupported { my $self = shift; enforcedToBeImplemented(); } # # Which component does this depend on sub dependsOn { my $self = shift; enforcedToBeImplemented(); } # # Has the component already been configured sub isConfigured { my $self = shift; enforcedToBeImplemented(); } # # Methods must be implemented for install # ########################################################################### # Configure action on first node # # If there are multiple steps when configuring the first node, and # those steps need to be executed at different stages (which means # 'configureFirstNode()' needs to be called at different places # during the install flow), the value assigned to the argument # $stepIndicator is considered an indicator of what actions should be # performed, e.g.: # # The following is an example of how configureFirstNode needs to be # implemented by the Clusterware components: # # sub configureFirstNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # # trace("Executing the step [$stepIndicator] to configure $compName ". # "on the first node"); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # configureFirstNode(AAAA) is invoked # # return SUCCESS; # } # elsif (BBBB == $stepIndicator) # { # # The following actions will be performed when # # configureFirstNode(BBBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub configureFirstNode { my $self = shift; enforcedToBeImplemented(); } ########################################################################### # Configure action on other nodes than the first node # # If there are multiple steps when configuring the other nodes than # the first node, and those steps need to be executed at different stages # (which means 'configureNonFirstNode()' needs to be called at different # places during the install folow), the value assigned to the argument # $stepIndicator is considered an indicator of what actions should be # performed, e.g.: # # The following is an example of how configureNonFirstNode needs to be # implemented by the Clusterware components: # # sub configureNonFirstNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # # trace("Executing the step [$stepIndicator] to configure $compName ". # "on the non-first node"); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # configureNonFirstNode(AAAA) is invoked # # return SUCCESS; # } # elsif (BBBB == $stepIndicator) # { # # The following actions will be performed when # # configureNonFirstNode(BBBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub configureNonFirstNode { my $self = shift; enforcedToBeImplemented(); } # Configure action on first node after the configured stack # has been started sub postConfigFirstNode { my $self = shift; enforcedToBeImplemented(); } # Configure action on other nodes than the first node after # the configured stack has been started sub postConfigNonFirstNode { my $self = shift; enforcedToBeImplemented(); } # # Methods must be implemented for upgrade # ########################################################################### # The method for global checks before upgrade # This method is called only on the first node when the stack is up. # # The following is an example of how preUpgradeCheck needs to be # implemented by the Clusterware components: # # sub preUpgradeCheck # { # my $self = shift; # my $compName = $self->compName; # trace("Doing prerequisite checks related to component $compName for upgrade"); # # # calling commands or functions to do the prerequisite checks # if (! isCheckSuccess()) { # # A translated message XXX should be print out if any check fails. # print_error(XXX); # return FAILED; # } # else { # return SUCCESS; # } ########################################################################### sub preUpgradeCheck { my $self = shift; enforcedToBeImplemented(); } ########################################################################### # Upgrade action on first node # # If there are multiple steps when upgrading the first node, and # and those steps need to be executed at different stages (which # means 'upgradeFirstNode()' needs to be called at different places # during the upgrade flow), the value assigned to the argument # $stepIndicator is considered an indicator of what actions should be # performed, e.g.: # # The following is an example of how upgradeFirstNode needs to be # implemented by the Clusterware components: # # sub upgradeFirstNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # trace("Executing the step [$stepIndicator] to upgrade $compName ". # "on the first node"); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # upgradeFirstNode(AAAA) is invoked # # return SUCCESS; # } # elsif (2 == $stepIndicator) # { # # The following actions will be performed when # # upgradeFirstNode(BBBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub upgradeFirstNode { my $self = shift; enforcedToBeImplemented(); } ########################################################################### # Upgrade action on every node other than first and last node # # If there are multiple steps when upgrading the node other than first and # last node, and those steps need to be executed at different stages (which # means 'upgradeMiddleNode()' needs to be called at different places during # the upgrade flow), the value assigned to the argument $stepIndicator is # considered an indicator of what actions should be performed, e.g.: # # The following is an example of how upgradeMiddleNode needs to be # implemented by the Clusterware components: # # sub upgradeMiddleNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # # trace("Executing the step [$stepIndicator] to upgrade $compName ". # "on the middle node"); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # upgradeMiddleNode(AAAA) is invoked # # return SUCCESS; # } # elsif (BBBB == $stepIndicator) # { # # The following actions will be performed when # # upgradeMiddleNode(BBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub upgradeMiddleNode { my $self = shift; enforcedToBeImplemented(); } ########################################################################### # Upgrade action on last node # # If there are multiple steps when upgrading the last node, and # and those steps need to be executed at different stages (which # means 'upgradeLastNode()' needs to be called at different places # during the upgrade flow), the value assigned to the argument # $stepIndicator is considered an indicator of what actions should be # performed, e.g.: # # The following is an example of how upgradeLastNode needs to be # implemented by the Clusterware components: # # sub upgradeLastNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # # trace("Executing the step [$stepIndicator] to upgrade $compName ". # "on the last node"); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # upgradeLastNode(AAAA) is invoked # # return SUCCESS; # } # elsif (BBBB == $stepIndicator) # { # # The following actions will be performed when # # upgradeLastNode(BBBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub upgradeLastNode { my $self = shift; enforcedToBeImplemented(); } # Upgrade action on the first node after the higher version stack # has been started sub postUpgradeFirstNode { my $self = shift; enforcedToBeImplemented(); } # Upgrade action on every node other than first and last node # after the higher version stack has been started sub postUpgradeMiddleNode { my $self = shift; enforcedToBeImplemented(); } # Upgrade action on the last node after the higher version stack # has been started sub postUpgradeLastNode { my $self = shift; enforcedToBeImplemented(); } ########################################################################### # Downgrade action on nodes other than the last node # # If there are multiple steps when downgrading nodes other than the last # node, and those steps need to be executed at different stages (which # means 'downgradeNonLastNode()' needs to be called at different places # during the downgrade flow), the value assigned to the argument # $stepIndicator is considered an indicator of what actions should be # performed, e.g.: # # The following is an example of how downgradeNonLastNode needs to be # implemented by the Clusterware components: # # sub downgradeNonLastNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # # trace("Executing the step [$stepIndicator] to downgrade $compName ". # "on the nodes other than the last node."); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # downgradeNonLastNode(AAAA) is invoked # # return SUCCESS; # } # elsif (BBBB == $stepIndicator) # { # # The following actions will be performed when # # downgradeNonLastNode(BBBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub downgradeNonLastNode { my $self = shift; enforcedToBeImplemented(); } ########################################################################### # Downgrade action on the last node # # If there are multiple steps when downgrading the last node, and # those steps need to be executed at different stages (which # means 'downgradeLastNode()' needs to be called at different places # during the downgrade flow), the value assigned to the argument # $stepIndicator is considered an indicator of what actions should be # performed, e.g.: # # The following is an example of how downgradeLastNode needs to be # implemented by the Clusterware components: # # sub downgradeLastNode # { # my $self = shift; # my $stepIndicator = shift; # my $compName = $self->compName; # # trace("Executing the step [$stepIndicator] to downgrade $compName ". # "on the last node."); # # if (AAAA == $stepIndicator) # { # # The following actions will be performed when # # downgradeLastNode(AAAA) is invoked # # return SUCCESS; # } # elsif (BBBB == $stepIndicator) # { # # The following actions will be performed when # # downgradeLastNode(BBBB) is invoked # # return SUCCESS; # } # ... # ... # else # { # croak "Step indicator out of bounds"; # } # } ########################################################################## sub downgradeLastNode { my $self = shift; enforcedToBeImplemented(); } # # Methods must be implemented for deconfiguration # # Deconfiguration action on nodes other than the last node sub deconfigureNonLastNode { my $self = shift; enforcedToBeImplemented(); } # Deconfiguration action on the last node sub deconfigureLastNode { my $self = shift; enforcedToBeImplemented(); } # # Whether or not the system reboot is needed after configuration sub rebootRequired { my $self = shift; enforcedToBeImplemented(); } # # Interfaces (forced) to be re-implemented in derived classes # - End - # # # Interfaces (optional) to be re-implemented as needed in derived classes # # The way to get the component started sub start { my $self = shift; } # # The way to get the component stopped sub stop { my $self = shift; } # # Dump the diagnositc info for debugging issues sub dumpDiagnostics { my $self = shift; trace("Dumping the diagnositc info ..."); } sub configureSIHA { my $self = shift; trace("Configure the current node in a SIHA environment"); } # The method for local checks before upgrading the first node # It should be implemented in the related component as needed. sub upgradeCheckFirstNode { my $self = shift; trace("Doing component related local checks before upgrading the first node"); } # The method for local checks before upgrading the middle node # It should be implemented in the related component as needed. sub upgradeCheckMiddleNode { my $self = shift; trace("Doing component related local checks before upgrading the middle node"); } # The method for local checks before upgrading the last node # It should be implemented in the related component as needed. sub upgradeCheckLastNode { my $self = shift; trace("Doing component related local checks before upgrading the last node"); } # The method for checks before upgrading a SIHA node sub upgradeCheckSIHA { my $self = shift; trace("Doing upgrade checks before upgrading the current node in a SIHA environment"); } sub upgradeSIHA { my $self = shift; trace("Upgrade the current node in a SIHA environment"); } sub postConfigureSIHA { my $self = shift; trace("Configure a SIHA node after the stack comes up"); } sub postUpgradeSIHA { my $self = shift; trace("Configure a SIHA node after the higher version stack comes up"); } ########################################################################### # The method for checks before patching # # The following is an example of how prePatchCheck needs to be # implemented by the Clusterware components: # # sub prePatchCheck # { # my $self = shift; # my $compName = $self->compName; # trace("Doing prerequisite checks related to component $compName for patching"); # # # calling commands or functions to do the prerequisite checks # if (! isCheckSuccess()) { # # A translated message XXX should be print out if any check fails. # print_error(XXX); # return FAILED; # } # else { # return SUCCESS; # } ########################################################################### sub prePatchCheck { my $self = shift; my $compName = $self->compName; trace("Doing prerequisite checks related to component $compName for patching"); } # # Interfaces (optional) to be re-implemented as needed in derived classes # - End - # sub enforcedToBeImplemented { croak "This method not overridden by the sub classes"; } =head1 NAME oraClusterwareComp - class to define interfaces for Oracle Clusterware components =head1 SYNOPSIS use parent 'oraClusterwareComp'; ################# # class methods # ################# $self = oraClusterwareComp->new("OCR"); ####################### # object data methods # ####################### ### get versions ### $compName = $obj->compName; ### set versions ### $obj->compName("OCR"); ######################## # other object methods # ######################## ### call this to configure the current node during fresh install ### $obj->configureCurrentNode(); ############################################################## # interfaces (forced) to be reimplemented in derived classes # ############################################################## isSupported dependsOn isConfigured configureFirstNode configureNonFirstNode postConfigFirstNode postConfigNonFirstNode preUpgradeCheck upgradeFirstNode upgradeMiddleNode upgradeLastNode postUpgradeFirstNode postUpgradeMiddleNode postUpgradeLastNode downgradeNonLastNode downgradeLastNode deconfigureNonLastNode deconfigureLastNode rebootRequired ######################################################## # interfaces (optional) to be re-implemented as needed # # in derived classes # ######################################################## start stop dumpDiagnostics upgradeCheckFirstNode upgradeCheckMiddleNode upgradeCheckLastNode prePatchCheck configureSIHA upgradeCheckSIHA upgradeSIHA postConfigureSIHA postUpgradeSIHA =head1 DESCRIPTION oraClusterwareComp is a base class that defines all needed interfaces for Oracle Clusterware components. All component classes should inherit from this base class, and override all interfaces defined in this class. =cut 1;