#!/usr/local/bin/perl # # $Header: crs11g_upgrade.pl 08-dec-2007.05:46:57 ajdsouza Exp $ # # crs11g_upgrade.pl # # Copyright (c) 2007, 2008, Oracle. All rights reserved. # # NAME # crs11g_upgrade.pl - # Usage: crs11g_upgrade.pl [-tgt_home] # # DESCRIPTION # upgrade the targets discover metadata file targets.xml # from lower versions to crs 11g # # NOTES # # # MODIFIED (MM/DD/YY) # dchakumk 03/10/08 - XbranchMerge dchakumk_6752_xbmsrc from # st_emdbsa_11.1 # ajdsouza 01/31/07 - Creation # use strict; use warnings; use Data::Dumper; use has::Common; require "semd_common.pl"; # name : has_handle_error # desc : called to handle error messages # # arg : # error message # sub has_handle_error(@) { my ( $message ) = @_; chomp $message; $message =~ s/^\s+|\s+$// if $message; return 1 unless $message and $message =~ /^(ERROR|WARN)\s*:/i; # log the message to the log file EMD_PERL_WARN("HAS:crs11g_upgrade.pl:$message") and return 1 if $message =~/^WARN/i; EMD_PERL_ERROR("HAS:crs11g_upgrade.pl:$message") and return 1 if $message =~/^ERROR/i; die "HAS:crs11g_upgrade.pl:$message" if $message =~/^ERROR/i; return 1; } # name : has_target_fn # desc : for each element passed it filters our the enity element of interest # # arg : # ref to xml element to be filtered # ref to xml ref to be returned back # metric_name being processed # sub has_target_fn(\%\%$) { my ( $elref, $rsref, $metric_name ) = @_; # we upgrade only one host and cluster in targets.xml # the first one top down return 1 if $rsref->{cluster} and $rsref->{host}; # check if this represents a element of interest - Target return 1 unless $elref->{element} and $elref->{element} =~ /^target$/i; # interested in only cluster and host targets return 1 unless $elref->{attrs}; # we check for both type= and TYPE= my $type; map { $type = $_ if $_ =~/^type$/ic } keys %{$elref->{attrs}}; return 1 unless $elref->{attrs}{$type} and $elref->{attrs}{$type} =~ /cluster|host/i; #keep the list of hosts and clusters push $rsref->{lc $elref->{attrs}{$type}}=$elref; return 1; } #---------------------------------------------------------------- # Code Begin #---------------------------------------------------------------- die "Usage:crs11g_upgrade.pl -tgt_home \n" unless ( @ARGV >=2 and $ARGV[0] =~ /-tgt_home/ and $ARGV[1] ) or ( @ARGV >=1 and $ARGV[0] and $ARGV[0] !~ /-tgt_home/); my $tgtHome; $tgtHome = $ARGV[1] if @ARGV >=2 and $ARGV[0] =~ /-tgt_home/ and $ARGV[1]; $tgtHome = $ARGV[0] if not $tgtHome and @ARGV >=1 and $ARGV[0] and $ARGV[0] !~ /-tgt_home/ die "Usage:crs11g_upgrade.pl -tgt_home \n" unless $tgtHome; #build the path to the discovery file my $tgtFile = File::Spec->catfile($tgtHome,'sysman'); $tgtPath = File::Spec->catfile($tgtPath,,'emd'); $tgtPath = File::Spec->catfile($tgtPath,'targets.xml'); # open the target discover file and read its contents stat($tgtPath); die "crs11g_upgrade.pl:ERROR:File $tgtPath is not accessible\n" unless -e $tgtPath and -r $tgtPath; open(TGTXML, "<$tgtPath") or die "crs11g_upgrade.pl:ERROR:Failed to open file $tgtPath"; my @lns = ; close(TGTXML); my $xcontent = ''; for my $ln ( @lns ) { $xcontent = "$xcontent\n$ln" } # remove that newline or space at the begining $xcontent =~ s/^[\s\n]+|\s+$//g; die "crs11g_upgrade.pl:ERROR:Failed to get content from $tgtPath\n" unless $xcontent; # parse the xml string to a processable perl structure my %xmlvar = has::Common::parse_xml($xcontent); # traverse the perl structure to pick cluster and host of interest # picks one host and one cluster ( we assume one target.xml has one host # and one cluster) my %reslist; has::Common::traverse_xml(%xmlvar,&handle_error,&has_target_fn,\%reslist); EM_PERL_DEBUG("crs11g_upgrade.pl:ERROR:Failed to get both cluster and host\n") and exit 0 unless $reslist{cluster} and $reslist{host} and ref($reslist{cluster}) =~ /HASH/ and ref($reslist{host}) =~ /HASH/; # get the cluster name , remember practical assumption only # one cluster per box my $crsHome = has::Common::hasGetClusterName(); my $discClsName = has::Common::hasGetCRSHome(); my $isEmcrsp = has::Common::hasCheckForEmcrsp($discClsName); my $has_type; my $scanName; my $scanPort; my $eonsPort; if ( $isEmcrsp ) { $has_type = has::Common::hasGetOcrType($discClsName); if ( $has_type =~ /^cluster$/ ) { $scanName = has::Common::hasGetScanName($discClsName); $scanPort = has::Common::hasGetScanPort($discClsName); $eonsPort = has::Common::hasGetEONSPort($discClsName); } } my $type, $name; my $clsref = $reslist{cluster}; my $hostref = $reslist{host}; # if there is no cluster home then there is nothign to do # for the cluster target if ( $crsHome ) { # we check for both type= and TYPE= map { $type = $_ if $_ =~/^type$/ic; $name = $_ if $_ =~/^name$/ic } keys %{$clsref->{attrs}}; $type = 'TYPE' unless $type; $name = 'NAME' unless $name; # use the discovered cluster name if there is no cluster name $clsref->{attrs}{$name} = $discClsName unless $clsref->{attrs}{$name}; # if the cluster xml in the discovery file has properties get the property # tag my $propertytag; map { $propertytag = $_ if $_ =~ /property/i } keys %{$clsref->{child_elements}} if $clsref->{child_elements}; # build the list of existign cluster properties in the discovery file my %already_existing_properties; if ( $propertytag ) { for my $elref ( @{$clsref->{child_elements}{$propertytag}} ) { next unless $elref and ref($elref} =~ /HASH/; next unless $elref->{attrs}; # save the existing cluster properties $already_existing_properties{cluster}{uc $elref->{attrs}{NAME}} = 1 if $elref->{attrs}{NAME}; } } #if OracleHome is not a property add it my $propref = has::Common:make_element('Property','', (NAME=>'OracleHome',VALUE=>$crsHome)); has::Common::append_element($clsref,$propref) unless $already_existing_properties{cluster} and $already_existing_properties{cluster}{uc 'OracleHome'}; } # cluster target is modified now modify the host target EMD_PERL_WARN("crs11g_upgrade.pl:ERROR:Failed to find name for cluster in $tgtPath cluster target not modified") unless $clsref->{attrs} and $clsref->{attrs}{$name}; my $clsName = $clsref->{attrs}{$name}; # check if the host target has the assoc property my $assoctag; map { $assoctag = $_ if $_ =~ /AssocTargetInstance/i } keys %{$hostref->{child_elements}} if $hostref->{child_elements}; # build the list of existing host properties in the discovery file if ( $assoctag ) { for my $elref ( @{$hostref->{child_elements}{$assoctag}} ) { next unless $elref and ref($elref} =~ /HASH/; next unless $elref->{attrs}; # save the existing cluster properties $already_existing_properties{host}{uc $elref->{attrs}{ASSOCIATION_NAME}} = 1 if $elref->{attrs}{ASSOCIATION_NAME}; } } # find if there is a composite membership of cluster for the host my $comptag; map { $comptag = $_ if $_ =~ /CompositeMembership/i } keys %{$hostref->{child_elements}} if $hostref->{child_elements}; # build the list of existing host CompositeMemberships in the discovery file if ( $comptag ) { for my $elref ( @{$hostref->{child_elements}{$comptag}} ) { next unless $elref and ref($elref} =~ /HASH/; # find if there is a memberof of cluster for the host my $membertag; map { $membertag = $_ if $_ =~ /MemberOf/i } keys %{$elref->{child_elements}} if $elref->{child_elements}; next unless $membertag; # from ther memberof find if its a cluster member for my $memref ( @{$elref->{child_elements}{$membertag}} ) { next unless $memref and ref($memref} =~ /HASH/; # save the existing cluster properties $already_existing_properties{host_memberof}{uc $elref->{attrs}{ASSOCIATION}} = 1 if $elref->{attrs}{ASSOCIATION}; } } } # check and modify the host target xml for ( (1) ) { # create the assoc element if both no assoc target and no memberof exists last if $already_existing_properties{host_memberof}{uc 'cluster_member'} or $already_existing_properties{host}{uc 'AssocTargetInstance'}; my $assocref = has::Common:make_element('AssocTargetInstance','', (ASSOCIATION_NAME =>'cluster_instance', ASSOC_TARGET_TYPE => 'cluster', ASSOC_TARGET_NAME => $clsName)); has::Common:append_element($hostref,$assocref); } my $dumpstr = has::Common:dump_xml(); open (OUTFILE, ">$tgtPath") or die "crs11g_upgrade.pl:ERROR:Failed to open $tgtPath for write\n"; print OUTFILE $dumpStr; close (OUTFILE); exit 0;