# IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos720 src/bos/usr/lpp/bosinst/samples/NIM.pm 1.1 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 2008,2009 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)51 1.1 src/bos/usr/lpp/bosinst/samples/NIM.pm, bosinst, bos720 3/29/09 15:20:43 package NIM; =head1 NAME NIM =over 2 =item * NIM functions to perform higher level operations. =item * Various startup options are available. =over 2 =item * MySettings.pm =item * MyConfig.pm =item * NIM.xml content via stdin =item * NIM.xml =back =back =head1 VARIABLES =head2 %Config =over 2 =item * info NIM::Info object created to capture NIM database information. =item * images Images defined to the module. =item * lpars LPARs defined to the module. =back =head1 FUNCTIONS =cut #------------------------------------------------------------------------------- BEGIN { # print "NIM BEGIN\n"; use Hash::Util; use NIM::Util; use NIM::Info; use NIM::Deploy::Mksysb; use NIM::LPAR::AIX; use NIM::LPAR::VIOS; use Cwd; my $found = 0; if ((-e "MySettings.pm") && (-r "MySettings.pm")) { $found = 1; my $dir = getcwd(); # print "loading $dir/MySettings.pm\n"; } else { foreach my $path (@INC) { if ((-e "$path/MySettings.pm") && (-r "$path/MySettings.pm")) { $found = 1; # print "loading $path/MySettings.pm\n"; } } } require MySettings if $found; %Config = ('info' => undef, 'images' => undef, 'lpars' => undef); } #------------------------------------------------------------------------------- INIT { # print "NIM INIT\n"; if (is_nim_master()) { warn "Mismatched NIM filesets detected\n" if (check_nim_filesets() != 0); $Config{'images'} = {}; $Config{'lpars'} = {}; # do not have NIM always create all possible boot images from the SPOT resources # when netboot_kernel=64 exists, the operation complains about aix 5.3 spots and leaves them in an invalid state invoke("$Cmds{'nim'} -o change -a if_prebuild=no master"); my $config_file = NIM::Util::which_pm('MyConfig.pm'); if (defined $config_file) { # print "loading $config_file\n"; require MyConfig; } my $xml_file = NIM::Util::read_stdin(); # xml string from stdin if (! $xml_file) { $xml_file = NIM::Util::which_pm('NIM.xml'); # file name } if ($xml_file) { # print "loading $xml_file\n"; my $input = NIM::Util::parse_xml_input_file($xml_file); process_xml_input($input); } if (defined $Config{'info'}) { $Config{'info'}->refresh(); } else { $Config{'info'} = new NIM::Info(); } } if (! $NIM::Util::Settings{'xml_results'}) { # NIM::Util::reset_sigwarn_sigdie_handlers(); } } #------------------------------------------------------------------------------- =head2 is_nim_master =over 2 =item C =back =head3 DESCRIPTION =over 2 =item Queries the system to check if it is a NIM master. =back =head3 PARAMETERS =head3 RETURNS =over 2 =item * 0 - Not NIM master. =item * 1 - Is NIM master. =back =head3 EXCEPTIONS =cut #------------------------------------------------------------------------------- sub is_nim_master { my $nim_info = new NIM::Info("$Lang $Cmds{'lsnim'} -lt master 2>/dev/null"); return ($nim_info->empty() ? 0 : 1); } #------------------------------------------------------------------------------- sub object_type { my ($object_name) = @_; my @rc = (); eval { my $nim_info = new NIM::Info("$Lang $Cmds{'lsnim'} -l $object_name 2>/dev/null"); @rc = $nim_info->get_attr_values($object_name, 'type'); }; return (($@ || ($#rc != 0)) ? '' : $rc[0]); } #------------------------------------------------------------------------------- =head2 add_lpar =over 2 =item C =back =head3 DESCRIPTION =over 2 =item Define a NIM::LPAR object to the module and the equivalent standalone machine to NIM. If the standalone machine is already defined in NIM, the NIM object may be redefined with any differing attributes. =back =head3 PARAMETERS =over 2 =item * %args (REQUIRED) Hash of arguments used to specify the attributes used to define the LPAR to NIM as a standalone machine. =back =head3 RETURNS =over 2 =item * Reference to the NIM::LPAR hash object representing the LPAR. =item * undef - If invalid LPAR specification. =back =head3 EXCEPTIONS =cut #------------------------------------------------------------------------------- sub add_lpar { my %args = @_; log_print "NIM::add_lpar(@_)\n"; my $rc = undef; if (defined $args{'type'} && defined $args{'hostname'}) { my $name = $args{'hostname'}; $name =~ s/([^\.]+).*/$1/; log_print "\tAdding LPAR \'$name\'\n"; if (defined $Config{'lpars'}->{$name}) { $rc = $Config{'lpars'}->{$name}; log_print "\tAn LPAR by the same name \'$name\' was already added\n"; } else { my %handler = ( 'aix' => sub { $rc = $Config{'lpars'}->{$name} = new NIM::LPAR::AIX(@_); }, 'vios' => sub { $rc = $Config{'lpars'}->{$name} = new NIM::LPAR::VIOS(@_); } ); my $code = $handler{$args{'type'}}; if ($code) { $code->(@_); } else { warn "\tInvalid LPAR type \'$args{'type'}\' entered"; }; } } else { log_print "An incomplete LPAR specification encountered\n"; } return $rc; } #------------------------------------------------------------------------------- sub rm_lpar { my ($name) = @_; log_print "NIM::rm_lpar($name)\n"; if (defined $Config{'lpars'}->{$name}) { # uncomment the following line to delete machine definition in nim # $Config{'lpars'}->{$hostname}->delete(); delete $Config{'lpars'}->{$name}; } } #------------------------------------------------------------------------------- sub print_lpars { my ($fh) = @_; if (! $fh) { $fh = STDOUT; } if (defined $Config{'lpars'}) { my $num_lpars = scalar keys %{$Config{'lpars'}}; printf $fh "NIM config - %d lpar%s\n", $num_lpars, ($num_lpars == 1 ? '' : 's'); while (my ($name, $lpar) = each(%{$Config{'lpars'}})) { print $fh "\t$name\n"; while (my ($key, $value) = each(%$lpar)) { if ($key ne 'info') { print $fh "\t\t$key = \'$value\'\n"; } } } } } #------------------------------------------------------------------------------- =head2 add_image =over 2 =item C =back =head3 DESCRIPTION =over 2 =item Define a NIM::Deploy object to the module and the equivalent image object to NIM. If the image object is already defined in NIM, the NIM object may be redefined with any differing attributes. =back =head3 PARAMETERS =over 2 =item * %args (REQUIRED) Hash of arguments used to specify the attributes used to define the image to NIM. =back =head3 RETURNS =over 2 =item * Reference to the NIM::Deploy hash object representing the image. =item * undef - If invalid image specification. =back =head3 EXCEPTIONS =cut #------------------------------------------------------------------------------- sub add_image { my %args = @_; log_print "NIM::add_image(@_)\n"; my $rc = undef; if (defined $args{'type'} && (defined $args{'name'} || defined $args{'location'})) { my $image = undef; if ($args{'type'} eq 'mksysb') { $image = new NIM::Deploy::Mksysb(@_); if ($image) { if ($Config{'images'}->{$image->{'name'}}) { $rc = $Config{'images'}->{$image->{'name'}}; log_print "\tAn image by the same name \'$name\' or \'$location\'was already added\n"; } else { log_print "\tAdded image \'$args{'name'}:$args{'location'}\'\n"; log_print "\tname = \'$image->{'name'}\'\n"; log_print "\timage = \'$image\'\n"; $rc = $Config{'images'}->{$image->{'name'}} = $image; log_print "\timage = \'$Config{'images'}->{$image->{'name'}}\'\n"; } } else { log_print "\tInvalid image \'$args{'name'}:$args{'location'}\' entered\n"; } } else { log_print "\tInvalid image type \'$args{'type'}\' entered\n"; } } else { log_print "An incomplete image specification encountered\n"; } return $rc; } #------------------------------------------------------------------------------- sub rm_image { my ($name) = @_; log_print "NIM::rm_image($name)\n"; if (defined $Config{'image'}->{$name}) { delete $Config{'images'}->{$name}; } } #------------------------------------------------------------------------------- sub print_images { my ($fh) = @_; if (! $fh) { $fh = STDOUT; } if (defined $Config{'images'}) { my $num_images = scalar keys %{$Config{'images'}}; printf $fh "NIM config - %d image%s\n", $num_images, ($num_images == 1 ? '' : 's'); while (my ($name, $image) = each(%{$Config{'images'}})) { print $fh "\t$name\n"; while (my ($key, $value) = each(%$image)) { if ($key ne 'info') { print $fh "\t\t$key = \'$value\'\n"; } } } } } #------------------------------------------------------------------------------- sub xml_input_file_to_lpars { my ($input) = @_; my $ref_type = ref($input->{'config'}->{'lpar'}); if ($ref_type eq 'HASH') { add_lpar(%{$input->{'config'}->{'lpar'}}); } elsif ($ref_type eq 'ARRAY') { foreach my $lpar (@{$input->{'config'}->{'lpar'}}) { add_lpar(%$lpar); } } } #------------------------------------------------------------------------------- sub xml_input_file_to_lpar_defaults { my ($input) = @_; my $ref_type = ref($input->{'settings'}->{'lpar'}); if ($ref_type eq 'HASH') { while (my ($key, $value) = each(%{$input->{'settings'}->{'lpar'}})) { $NIM::LPAR::Defaults{$key} = $value; } } elsif ($ref_type eq 'ARRAY') { warn "Only a single pauto/settings/lpar element should be specified"; foreach my $lpar (@{$input->{'settings'}->{'lpar'}}) { while (my ($key, $value) = each(%$lpar)) { $NIM::LPAR::Defaults{$key} = $value; } } } } #------------------------------------------------------------------------------- sub xml_input_file_to_images { my ($input) = @_; my $ref_type = ref($input->{'config'}->{'image'}); if ($ref_type eq 'HASH') { add_image(%{$input->{'config'}->{'image'}}); } elsif ($ref_type eq 'ARRAY') { foreach my $image (@{$input->{'config'}->{'image'}}) { add_image(%$image); } } # print_images(); } #------------------------------------------------------------------------------- sub update_settings { my ($key, $value) = @_; if ($key eq 'name') { $key = 'project'; } my @hash_refs = ( \%NIM::Util::Settings, \%NIM::Info::Settings, \%NIM::LPAR::Settings, \%NIM::Deploy::Settings ); foreach my $settings (@hash_refs) { if (defined $settings->{$key}) { $settings->{$key} = $value; } } } #------------------------------------------------------------------------------- sub xml_input_file_to_project_settings { my ($input) = @_; my $ref_type = ref($input->{'settings'}->{'project'}); if ($ref_type eq 'HASH') { while (my ($key, $value) = each(%{$input->{'settings'}->{'project'}})) { update_settings($key, $value); } } elsif ($ref_type eq 'ARRAY') { warn "Only a single pauto/settings/project element should be specified"; foreach my $project (@{$input->{'settings'}->{'project'}}) { while (my ($key, $value) = each(%$project)) { update_settings($key, $value); } } } } #------------------------------------------------------------------------------- =head2 process_xml_input =over 2 =item C =back =head3 DESCRIPTION =over 2 =item Parses the XML input data structure and creates the appropriate NIM objects or module settings. Sample xml file content: =back =pod sysp /var/ibm/systemp/nim /export/nim /opt/IBM/AE aix ipv4-076 ipv4-076 austin.ibm.com mksysb was7_5300-07master_sysb /export/nim/mksysb/was7_5300-07_mksysb /tmp/nimext/AE /tmp/nimext/AE/AP/was.ap sh /opt/IBM/AE/ae -a /opt/IBM/AE/AL/wasv7.al mksysb db2-91_5300-07master_sysb /export/nim/mksysb/db2-91_5300-07_mksysb /tmp/nimext/AE /tmp/nimext/AE/AP/DB2_9.1.ap sh /opt/IBM/AE/ae -a /opt/IBM/AE/AL/DB2_9.1.al mksysb 5300-07master_sysb /tmp/nimext/AE /tmp/nimext/AE/AP/aix.ap sh /opt/IBM/AE/ae -a /opt/IBM/AE/AL/aix.al =cut =head3 PARAMETERS =over 2 =item * $xml_input (REQUIRED) XML input data structure created from the XML::Simple parser. =back =head3 RETURNS =head3 EXCEPTIONS =cut #------------------------------------------------------------------------------- sub process_xml_input { my ($input) = @_; xml_input_file_to_project_settings($input); xml_input_file_to_lpar_defaults($input); xml_input_file_to_lpars($input); xml_input_file_to_images($input); # print_lpars(); # print_images(); } #------------------------------------------------------------------------------- sub check_nim_filesets { log_print "NIM::check_nim_filesets()\n"; my @client_history = `lslpp -lqc bos.sysmgt.nim.client | grep /usr/lib/objrepos`; my @master_history = `lslpp -lqc bos.sysmgt.nim.master | grep /usr/lib/objrepos`; my $client_level; my $master_level; foreach my $line (@client_history) { my @parts = split(/:/, $line); log_print "\tbos.sysmgt.nim.client $parts[2] $parts[4]\n"; # Level and State $client_level = $parts[2]; } foreach my $line (@master_history) { my @parts = split(/:/, $line); log_print "\tbos.sysmgt.nim.master $parts[2] $parts[4]\n"; # Level and State $master_level = $parts[2]; } my $rc = ($client_level ne $master_level) ? -1 : 0; log_printf("\trc = %d\n", $rc); return $rc; } 1; # __END__ =head1 AUTHOR IBM =head1 BUGS Please report any bugs to the L. =head1 SUPPORT =head1 ACKNOWLEDGEMENTS =head1 SEE ALSO =begin html =end html =cut