#!/usr/bin/env perl # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html #------------------------------------------------------- package xCAT::ExtTab; BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; } # #NO xCAT perl library routines should be used in this begin block #(i.e. MsgUtils,Utils, etc) # #use lib "$::XCATROOT/lib/perl"; use File::Path; %ext_tabspec=(); $ext_defspec=(); # loads user defined table spec. They are stored under /opt/xcat/lib/perl/xCAT_schema directory my $path="$::XCATROOT/lib/perl/xCAT_schema"; my $filelist; # no specific files my @extSchema = &get_filelist($path, $filelist,"pm"); # print "\nextSchema=@extSchema\n"; foreach (@extSchema) { /.*\/([^\/]*).pm$/; my $file=$_; my $modname = $1; no strict 'refs'; my $warning; `logger -t xCAT processing $_`; eval {require($_)}; if ($@) { $warning ="Warning: The user defined database table schema file $file cannot be located or has compiling errors.\n"; print $warning; `logger -t xCAT $warning`; next; } if (${"xCAT_schema::" . "$modname" . "::"}{tabspec}) { my %tabspec=%{${"xCAT_schema::" . "$modname" . "::"}{tabspec}}; foreach my $tabname (keys(%tabspec)) { if (exists($ext_tabspec{$tabname})) { $warning = "Warning: File $file: the table name $tabname is used by other applications. Please rename the table.\n"; print $warning; `logger -t xCAT $warning`; } else { $ext_tabspec{$tabname}=$tabspec{$tabname}; } } } else { $warning ="\n Warning: Cannot find \%tabspec variable in the user defined database table schema file $file\n"; print $warning; `logger -t xCAT $warning`; } #get the defspec from each file and merge them into %ext_defspec if (${"xCAT_schema::" . "$modname" . "::"}{defspec}) { my %defspec=%{${"xCAT_schema::" . "$modname" . "::"}{defspec}}; foreach my $objname (keys(%defspec)) { if (exists($defspec{$objname}->{'attrs'})) { if (exists($ext_defspec{$objname})) { #print "insert\n"; my @attr_new=@{$defspec{$objname}->{'attrs'}}; my @attr=@{$ext_defspec{$objname}->{'attrs'}}; my %tmp_hash=(); foreach my $orig (@attr) { my $attrname=$orig->{attr_name}; $tmp_hash{$attrname}=1; } foreach my $h (@attr_new) { my $attrname=$h->{attr_name}; if (exists($tmp_hash{$attrname})) { $warning= " Warning: Conflict when adding user defined defspec from file $file. Attribute name $attrname is already defined in object $objname. \n"; print $warning; `logger -t xCAT $warning`; } else { #print "\ngot here objname=$objname, attrname=" . $h->{attr_name} . "\n"; push(@{$ext_defspec{$objname}->{'attrs'}}, $h); } } } else { #print "\ngot here objname=$objname, file=$file\n"; $ext_defspec{$objname}=$defspec{$objname}; } } } } } #foreach #print out the defspec #print "\nexternal defspec:\n"; #foreach(%ext_defspec) { # print " $_:\n"; # my @attr=@{$ext_defspec{$_}->{'attrs'}}; # foreach my $h (@attr) { # print " " . $h->{attr_name} . "\n"; # } #} #------------------------------------------------------- =head1 xCAT::ExtTab Handles user defined database tables. =cut #------------------------------------------------------- =head3 updateTables It is called by xcatd to generate the user-defined tables if they do not exist, it also updates the tables if there is a schema change. =cut #------------------------------------------------------- sub updateTables { #print "\nupdateTables\n"; #print "\n"; foreach (keys %ext_tabspec) { my $table= xCAT::Table->new($_,-create=>1); my $rc=$table->updateschema(); $table->close(); } } #-------------------------------------------------------------------------- =head3 Note this is a copy of the one in Table.pm but we cannot use any of the xCAT perl libraries in this routine,since the function was done in the Begin block. Description: get_filelist Arguments: directory,filelist,type Returns: The list of sql files to be processed which consists of all the files with .sql and _.sql or files with .pm and _.pm Globals: Error: Example: my @filelist =get_filelist($directory,$filelist,$type); where type = "sql" or "pm" =cut #-------------------------------------------------------------------------------- sub get_filelist { use File::Basename; my $directory = shift; my $files = shift; my $ext = shift; my $dbname = "sqlite"; my $xcatcfg = get_xcatcfg(); if ($xcatcfg =~ /^DB2:/) { $dbname = "db2"; } else { if ($xcatcfg =~ /^mysql:/) { $dbname = "mysql"; } else { if ($xcatcfg =~ /^Pg:/) { $dbname = "pgsql"; } } } $directory .= "/"; my @filelist = (); my @list = glob($directory . "*.$ext"); # all files foreach my $file (@list) { my $filename= basename($file); # strip filename my($name,$ext1) = split '\.', $filename; my($name,$ext2) = split '\_', $name; if ($ext2 eq $dbname) # matches the database { push @filelist, $file; } else { if ($ext2 eq "") # no database designated { push @filelist, $file; } else { # if not one of the databases, they just have _ in # the file name if ($ext2 ne "db2" && $ext2 ne "mysql" && $ext2 ne "pgsql" && $ext2 ne "sqlite" ) { push @filelist, $file; } } } $ext2 = ""; $ext1 = ""; } return @filelist; } #-------------------------------------------------------------------------- =head3 Note this is a copy of the one in Table.pm but we cannot use any of the xCAT perl libraries in this routine,since the function was done in the Description: get_xcatcfg Arguments: none Returns: the database name from /etc/xcat/cfgloc or sqlite Globals: Error: Example: my $xcatcfg =get_xcatcfg(); =cut #-------------------------------------------------------------------------------- sub get_xcatcfg { my $xcatcfg = (defined $ENV{'XCATCFG'} ? $ENV{'XCATCFG'} : ''); unless ($xcatcfg) { if (-r "/etc/xcat/cfgloc") { my $cfgl; open($cfgl,"<","/etc/xcat/cfgloc"); $xcatcfg = <$cfgl>; close($cfgl); chomp($xcatcfg); $ENV{'XCATCFG'}=$xcatcfg; #Store it in env to avoid many file reads } } if ($xcatcfg =~ /^$/) { if (-d "/opt/xcat/cfg") { $xcatcfg = "SQLite:/opt/xcat/cfg"; } else { if (-d "/etc/xcat") { $xcatcfg = "SQLite:/etc/xcat"; } } } unless ($xcatcfg =~ /:/) { $xcatcfg = "SQLite:" . $xcatcfg; } return $xcatcfg; } 1;