#!/usr/local/bin/perl # # $Header: has/install/crsconfig/oraacfs.pm /st_has_11.2.0/6 2011/07/27 08:44:13 agraves Exp $ # # oraacfs.pm # # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. # # NAME # oraacfs.pm - Library module for ACFS root install functions. # # DESCRIPTION # oraacfs.pm - Contains initial installation and deinstallation # routines for ACFS. # # NOTES # # MODIFIED (MM/DD/YY) # agraves 07/25/11 - Change FAILED return code when acfsroot to SUCCESS # for NOT_SUPPORTED. # xyuan 07/11/11 - Fix bug 12701521 # anjiwaji 06/24/11 - Backport anjiwaji_bug-12644077_main from main # josmith 05/18/11 - Don't modify replication types if no replication # resources were found # josmith 04/20/11 - Add ACFS replication upgrade functions # agraves 03/07/11 - Initial Creation # =head1 NAME oraacfs.pm Oracle clusterware ACFS component configuration/startup package =head1 DESCRIPTION This package contains functions required for initial configuration and startup of the ACFS component of Oracle clusterware =cut package oraacfs; use strict; use English; use File::Temp qw/ tempfile /; use File::Spec::Functions; use File::Find (); use crsconfig_lib; use strict; use Exporter; use vars qw(@ISA @EXPORT @EXPORT_OK); @ISA = qw(Exporter); my @exp_func = qw(add_acfs_registry is_acfs_registry_running start_acfs_registry upgrade_acfs_registry installUSMDriver isACFSSupported acfsrepl_updateResources acfsrepl_lastNode); # This should export ACFS SUPPORTED constants. #my @exp_const = qw(CSS_EXCL_SUCCESS CSS_EXCL_FAIL # CSS_EXCL_FAIL_CLUSTER_ACTIVE); push @EXPORT, @exp_func; #, @exp_const; # OSD API definitions # TODO: We'll need this for acfs if there are OSD sections. #use s_oraacfs; =head2 add_acfs_registry Creates or updates ACFS Registry resource =head3 Parameters None =head3 Returns TRUE - ACFS Registry configuration was created or updated FALSE - ACFS Registry configuration was not created or updated =head3 Notes =cut sub add_acfs_registry { if (! isACFSSupported()) { return TRUE; } my $ORA_CRS_HOME = $CFG->ORA_CRS_HOME; my $owner = $CFG->SUPERUSER; my $asmgrp = $CFG->params('ORA_ASM_GROUP'); my $crsctl = catfile ($ORA_CRS_HOME, "bin", "crsctl"); my $rc = TRUE; if ($CFG->platform_family eq "windows") { if (is_dev_env()) { $owner = $CFG->params('ORACLE_OWNER'); } else { $owner = ''; } } # check if acfs registry type exists my @cmd = ($crsctl, 'status', 'type', 'ora.registry.acfs.type'); my @out = system_cmd_capture(@cmd); my $checkrc = shift @out; # if type doesn't exist, add it. # CRS-2560 = Resource type xxx does not exist if ((defined($out[0])) && ($out[0] =~ m/CRS-2560/)) { # add type ora.registry.acfs.type my @cmd = ($crsctl, 'add', 'type', 'ora.registry.acfs.type', '-basetype', 'ora.local_resource.type', '-file', "$ORA_CRS_HOME/crs/template/registry.acfs.type"); trace ("Invoking: @cmd"); my $status = system_cmd(@cmd); if (0 == $status) { trace ("add ora.registry.acfs.type ... success"); } else { error ("add ora.registry.acfs.type ... failed"); return FALSE; } } else { trace ("ora.registry.acfs.type already exists.... skipping type add"); } # check if acfs registry exists my @cmd = ($crsctl, 'status', 'resource', 'ora.registry.acfs'); my @out = system_cmd_capture(@cmd); my $checkrc = shift @out; # if registry doesn't exist, add it. # CRS-2613 = Could not find resource if (defined($out[0]) && ($out[0] =~ m/CRS-2613/ )) { # add resource ora.registry.acfs my @cmd = ($crsctl, "add", "resource", "ora.registry.acfs", "-attr", "\"ACL='owner:$owner:rwx,pgrp:$asmgrp:rwx,other::r--'\"", "-type", "ora.registry.acfs.type", "-f"); if (! is_dev_env() && ($CFG->platform_family eq "windows")) { push @cmd, '-buildowner'; } my $status = system_cmd(@cmd); if (0 == $status) { trace ("add resource ora.registry.acfs ... success"); } else { error ("add resource ora.registry.acfs ... failed"); return FALSE; } } else { trace ("ora.registry.acfs already exists ... skipping"); } return $rc; } =head2 is_acfs_registry_running Verifies that the acfs registry is running. =head3 Parameters None =head3 Returns TRUE - ACFS Registry is ONLINE FALSE - ACFS Registry is OFFLINE =head3 Notes =cut sub is_acfs_registry_running { # return TRUE if ora.registry.acfs is running. Otherwise return FALSE. my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my @cmd = ($crsctl, 'status', 'resource', 'ora.registry.acfs'); my $grep_val = "STATE=ONLINE"; my @out = system_cmd_capture(@cmd); my $rc = shift @out; my @cmdout = grep(/$grep_val/, @out); # if scalar(@cmdout) > 0, we found the msg we were looking for if (scalar(@cmdout) > 0) { trace("ora.registry.acfs is online"); return TRUE; } else { trace("ora.registry.acfs is not online"); return FALSE; } } =head2 start_acfs_registry Starts the ACFS registry on specified nodes. =head3 Parameters arg[0] - Nodes to start on. =head3 Returns TRUE - ACFS Registry is ONLINE FALSE - ACFS Registry is OFFLINE =head3 Notes =cut sub start_acfs_registry { if ((! isACFSSupported()) || (is_acfs_registry_running())) { return TRUE; } # need to check for fresh install if ((! $CFG->UPGRADE) && (! $CFG->ASM_STORAGE_USED)) { return TRUE; } my $nodes_to_start_ref = shift; trace ("starting acfs_registry..."); trace ("nodes_to_start=@$nodes_to_start_ref"); my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my $rc = TRUE; # start resource ora.acfs foreach my $node (@$nodes_to_start_ref) { my @cmd = ($crsctl, 'start', 'res', 'ora.registry.acfs', '-n', $node); my $status = system_cmd(@cmd); if (0 == $status) { trace ("@cmd ... success"); } else { trace ("@cmd ... failed"); $rc = FALSE; last; } } return $rc; } =head2 upgrade_acfs_registry Upgrades the ACFS Registry =head3 Parameters None =head3 Returns TRUE - ACFS Registry successfully upgraded. (Note that one or more attribute updates may fail, and success will still be returned.) FALSE - ACFS Registry not successfully upgraded. =head3 Notes =cut sub upgrade_acfs_registry { # check if acfs resource exists my $owner = $CFG->SUPERUSER; my $asmgrp = $CFG->params('ORA_ASM_GROUP'); my $crsctl = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my @cmd = ($crsctl, 'status', 'resource', 'ora.registry.acfs'); my @out = system_cmd_capture(@cmd); my $rc = shift @out; # if registry doesn't exist, add it. # CRS-2613 = Could not find resource if (defined($out[0]) && ($out[0] !~ m/CRS-2613/ )) { add_acfs_registry(); my @nodes = split (/,/, $CFG->params('NODE_NAME_LIST')); # Set attributes to 11.2.0.3 values. my @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs','-attr', "\"ACL='owner:$owner:rwx,pgrp:$asmgrp:rwx,other::r--'\""); if (! is_dev_env() && ($CFG->platform_family eq "windows")) { push @cmd, '-buildowner'; } my @out = system_cmd_capture(@cmd); my $rc = shift @out; if ($rc != 0) { trace ("Setting registry.acfs ACL failed"); } my @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs', '-attr', '"SCRIPT_TIMEOUT=120"'); my @out = system_cmd_capture(@cmd); my $rc = shift @out; if ($rc != 0) { trace ("Setting registry.acfs SCRIPT_TIMEOUT failed"); } @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs', '-attr', '"START_TIMEOUT=180"'); @out = system_cmd_capture(@cmd); $rc = shift @out; if ($rc != 0) { trace ("Setting registry.acfs START_TIMEOUT failed"); } @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs', '-attr', '"STOP_TIMEOUT=900"'); @out = system_cmd_capture(@cmd); $rc = shift @out; if ($rc != 0) { trace ("Setting registry.acfs STOP_TIMEOUT failed"); } @cmd = ($crsctl, 'modify', 'resource', 'ora.registry.acfs', '-attr', '"CHECK_TIMEOUT=600"'); @out = system_cmd_capture(@cmd); $rc = shift @out; if ($rc != 0) { trace ("Setting registry.acfs CHECK_TIMEOUT failed"); } start_acfs_registry(\@nodes); } else { trace ("Previous install does not have ora.registry.acfs, adding it...."); if (isACFSSupported()) { add_acfs_registry(); } } } =head2 isACFSSupported Determines if this platform is an ACFS supported platform by calling 'acfsdriverstate supported'. =head3 Parameters None =head3 Returns TRUE - ACFS Supported FALSE - ACFS Not Supported =head3 Notes =cut sub isACFSSupported { my $ACFS_supported = FALSE; my $acfsdriverstate; if ($CFG->platform_family eq 'windows') { $acfsdriverstate = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsdriverstate.bat'); } else { $acfsdriverstate = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsdriverstate'); } # check if acfs is supported if (! (-e $acfsdriverstate)) { trace ("$acfsdriverstate not found"); return FALSE; } my @cmd = ($acfsdriverstate, "supported"); my @out = system_cmd_capture(@cmd); my $rc = shift @out; if ($rc == 0) { $ACFS_supported = TRUE; trace ("acfs is supported"); } else { $ACFS_supported = FALSE; trace ("acfs is not supported"); } return $ACFS_supported; } =head2 installUSMDriver Installs ACFS, ADVM, OKS - kernel and user components via acfsroot. =head3 Parameters None =head3 Returns TRUE - Configuration successful FALSE - Configuration failed =head3 Notes =cut sub installUSMDriver { my $acfsroot; my $ret = SUCCESS; # if we are running in development mode, then limit support to only when # the appropriate env variables are set if (is_dev_env()) { my $acfsInstall = uc($ENV{'USM_ENABLE_ACFS_INSTALL'}); # if this ENV is not set then we give up early if ( $acfsInstall ne "TRUE" ) { trace("ADVM/ACFS disabled because of ENV in test mode"); return $ret; } } if ($CFG->platform_family eq 'windows') { $acfsroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsroot.bat'); } else { $acfsroot = catfile ($CFG->ORA_CRS_HOME, 'bin', 'acfsroot'); } if (-e $acfsroot) { my $cmd = "$acfsroot install"; trace("Executing '$cmd'"); my @output = system_cmd_capture($cmd); my $rc = shift @output; if ($rc == 0) { trace ("$cmd ... success"); } elsif ($rc != 2) { if (scalar(grep(/09394/, @output)) > 0) { $ret = WARNING; trace("$cmd ... success, but need a system reboot"); } else { $ret = FAILED; trace ("$cmd ... failed"); } } } else { trace("$acfsroot not found"); if (isACFSSupported()) { # if acfsroot not found and usm supported, we have a problem # some required files are not here. trace("ACFS is supported on this platform, but install files are missing."); $ret = FAILED; } else { # If acfsroot not found and acfs not supported, # then assume everything is okay. trace("ACFS is not supported on this platform."); $ret = SUCCESS; } } trace("USM driver install status is $ret"); return $ret; } =head2 acfsrepl_updateResources Updates the replication resources to run at the upgraded version. Currently this upgrades from 11.2.0.2 on Linux. For this we do the following: - Stop all the replication resources. - Add the attributes PRIMARY_DEVICE and MOUNTPATH to the resources. =head3 Parameters None =head3 Returns None =head3 Notes Runs only on Linux =cut sub acfsrepl_updateResources { my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my @repltypes = ('ora.acfsrepltransport.type', 'ora.acfsreplapply.type', 'ora.acfsreplmain.type', 'ora.acfsreplinit.type'); my @replres; my %repldevhash; my $type; my $cmd; my $status; if ($^O !~ /linux/i) { # Replication is only supported starting with Linux 11.2.0.2 return; } my @oldcrs_ver = @{$CFG->oldconfig('ORA_CRS_VERSION')}; if (!($oldcrs_ver[0] eq '11' && $oldcrs_ver[1] eq '2' && $oldcrs_ver[2] eq '0' && $oldcrs_ver[3] eq '2') ) { # We aren't running on 11.2.0.2 return; } # Find all of the replication resources on this node and put them in an array. foreach $type (@repltypes) { # Add the resource to the list acfsrepl_findRes($type, \@replres, \%repldevhash); } if(@replres == 0) { # Don't do anything if we don't have any resources return; } foreach $type (@repltypes) { # Add the PRIMARY_DEVICE attribute to the resource type $cmd = "$crsctlbin modify type $type -attr \"ATTRIBUTE=PRIMARY_DEVICE\",\"TYPE=string\",\"DEFAULT_VALUE=\",\"FLAGS=CONFIG\""; trace("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); } # Stop the resources trace("Stopping replication resources"); foreach(0..$#replres) { trace("Stopping $replres[$_]"); $cmd = "$crsctlbin stop resource $replres[$_]"; trace("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); } # Update the resources foreach(0..$#replres) { my $res = $replres[$_]; my $dev = $repldevhash{$res}; trace("Updating resource $res"); if($dev ne "") { # Add the PRIMARY_DEVICE attribute to the resource $cmd = "$crsctlbin modify resource $res -attr \"PRIMARY_DEVICE=$dev\""; trace ("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); } } } =head2 acfsrepl_findRes Finds all the replication resources of a given type. Adds the resources to an array Adds the resources primary device to a hash list. =head3 Parameters type - Resource type to search for. arrayref - Reference to array that holds the resource names found. hashref - Reference to hash table that hold the primary devices found. =head3 Returns None =head3 Notes - Only runs on Linux. =cut sub acfsrepl_findRes { my $type = shift; my $arrayref = shift; my $hashref = shift; my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my $cmd = "$crsctlbin stat res -f -w \'TYPE = $type\'"; my $devcmd = "/sbin/acfsutil info fs -o primaryvolume"; my $line; my $res; open (OUT, "$cmd | ") or trace("Failed:$cmd($!)"); while () { $line = $_; if($line =~ /^NAME=/) { $res = $'; chomp($res); push(@$arrayref, $res); } if($line =~ /^MOUNTPOINT=/) { my $dev = `$devcmd $' 2>&1`; chomp($dev); ${$hashref}{ $res } = $dev; } } } =head2 acfsrepl_lastNode Does the replication upgrade processing on the last node. This is run AFTER the active version has been switched. Only runs on Linux upgrading from 11.2.0.2 =head3 Parameters Does the following: - Deletes the 'main' resource - Adds the new preapply and monitor types. - Gets all the replication resources and starts them =head3 Returns None =head3 Notes - Only runs on Linux. =cut sub acfsrepl_lastNode { my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); my $replpreapplytype = "ora.acfsreplpreapply.type"; my $replmonitortype = "ora.acfsreplmonitor.type"; my @replres; my @repltypes = ('ora.acfsrepltransport.type', 'ora.acfsreplapply.type', 'ora.acfsreplmain.type', 'ora.acfsreplinit.type'); my %repldevhash; my $res; my $cmd; my $status; my $type; my $rc; my @lsnodes; my $node; if ($^O !~ /linux/i) { # Replication is only support on Linux 11.2.0.2 return; } my @oldcrs_ver = @{$CFG->oldconfig('ORA_CRS_VERSION')}; if (!($oldcrs_ver[0] eq '11' && $oldcrs_ver[1] eq '2' && $oldcrs_ver[2] eq '0' && $oldcrs_ver[3] eq '2') ) { # We aren't running on 11.2.0.2 return; } # Get the node list in the cluster ($rc, @lsnodes) = get_olsnodes_info($CFG->OLD_CRS_HOME); # Find all of the replication resources on this node and put them in an array. foreach $type (@repltypes) { # Add the resource to the list acfsrepl_findRes($type, \@replres, \%repldevhash); } if(@replres == 0) { # Don't do anything if we don't have any resources return; } # Add the new resource types. monitor and preapply. my $addmoncmd = "$crsctlbin add type $replmonitortype -basetype cluster_resource -attr \"ATTRIBUTE=MOUNTPOINT\",\"TYPE=string\",\"DEFAULT_VALUE=\",\"ATTRIBUTE=PRIMARY_DEVICE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=AGENT_FILENAME\",\"TYPE=string\",\"DEFAULT_VALUE=%CRS_HOME%/bin/oraagent%CRS_EXE_SUFFIX%\",\"ATTRIBUTE=AUTO_START\",\"TYPE=string\",\"DEFAULT_VALUE=never\",\"ATTRIBUTE=PLACEMENT\",\"TYPE=string\",\"DEFAULT_VALUE=restricted\",\"ATTRIBUTE=SERVER_POOLS\",\"TYPE=string\", \"DEFAULT_VALUE=*\",\"ATTRIBUTE=SITE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=START_TIMEOUT\",\"TYPE=int\", \"DEFAULT_VALUE=120\""; trace ("Invoking \"$addmoncmd\""); $status = system_cmd ("$addmoncmd"); my $addpreappcmd = "$crsctlbin add type $replpreapplytype -basetype cluster_resource -attr \"ATTRIBUTE=MOUNTPOINT\",\"TYPE=string\",\"DEFAULT_VALUE=\",\"ATTRIBUTE=PRIMARY_DEVICE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=AGENT_FILENAME\",\"TYPE=string\",\"DEFAULT_VALUE=%CRS_HOME%/bin/oraagent%CRS_EXE_SUFFIX%\",\"ATTRIBUTE=AUTO_START\",\"TYPE=string\",\"DEFAULT_VALUE=never\",\"ATTRIBUTE=PLACEMENT\",\"TYPE=string\",\"DEFAULT_VALUE=restricted\",\"ATTRIBUTE=SERVER_POOLS\",\"TYPE=string\", \"DEFAULT_VALUE=*\",\"ATTRIBUTE=SITE\",\"TYPE=string\", \"DEFAULT_VALUE=\",\"ATTRIBUTE=START_TIMEOUT\",\"TYPE=int\", \"DEFAULT_VALUE=120\""; trace ("Invoking \"$addpreappcmd\""); $status = system_cmd ("$addpreappcmd"); for(0..$#replres) { my $index = $_; $res = $replres[$index]; if($res =~ /ora.repl.main./) { my $ressuffix = $'; my $isStandby = 0; my $mntpt; my $pridev; $cmd = "$crsctlbin stat res $res -f"; trace("Invoking \"$cmd\""); open (OUT, "$cmd | ") or die "Cannot run command:$cmd($!)\n"; while () { if($_ =~ /^SITE=standby/) { $isStandby = 1; } if($_ =~ /^MOUNTPOINT=/) { $mntpt = $'; chomp($mntpt); } if($_ =~ /PRIMARY_DEVICE=/) { $pridev = $'; chomp($pridev); } } # Delete the main resource from the array. delete $replres[$index]; # Add the new resources if($isStandby) { acfsrepl_addResource("ora.repl.preapply." . $ressuffix, $replpreapplytype, $mntpt, $pridev, $isStandby); push(@replres, "ora.repl.preapply." . $ressuffix); } acfsrepl_addResource("ora.repl.monitor." . $ressuffix, $replmonitortype, $mntpt, $pridev, $isStandby); push(@replres, "ora.repl.monitor." . $ressuffix); # Delete the main resource $cmd = "$crsctlbin delete resource $res"; trace("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); } } # Start all of the resources in the list foreach(0..$#replres) { my $res = $replres[$_]; if(defined($res)) { # Start the transport daemon on each node. if($res =~ /ora.repl.transport./) { foreach $node (@lsnodes) { $cmd = "$crsctlbin start resource $res -n $node"; trace("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); } } else { $cmd = "$crsctlbin start resource $res"; trace("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); } } } } sub acfsrepl_addResource { my $resname = shift; my $type = shift; my $mntpt = shift; my $pridev = shift; my $isStandby = shift; my $site; my $cmd; my $status; my $crsctlbin = catfile ($CFG->ORA_CRS_HOME, "bin", "crsctl"); if($isStandby == 1) { $site = "standby"; } else { $site = "primary"; } # Add the resource $cmd = "$crsctlbin add resource $resname -type $type -attr \"MOUNTPOINT=$mntpt\",\"PRIMARY_DEVICE=$pridev\",\"SITE=$site\""; trace("Invoking \"$cmd\""); $status = system_cmd ("$cmd"); }