mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2693 lines
		
	
	
		
			97 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2693 lines
		
	
	
		
			97 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env perl -w
 | 
						|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
 | 
						|
#####################################################
 | 
						|
#
 | 
						|
#   Utility subroutines that can be used to manage xCAT data object
 | 
						|
#                       definitions.
 | 
						|
#
 | 
						|
#
 | 
						|
#####################################################
 | 
						|
package xCAT::DBobjUtils;
 | 
						|
 | 
						|
require xCAT::NodeRange;
 | 
						|
require xCAT::Schema;
 | 
						|
require xCAT::Table;
 | 
						|
require xCAT::Utils;
 | 
						|
require xCAT::MsgUtils;
 | 
						|
require xCAT::NetworkUtils;
 | 
						|
require xCAT::ServiceNodeUtils;
 | 
						|
use strict;
 | 
						|
 | 
						|
#  IPv6 not yet implemented - need Socket6
 | 
						|
use Socket;
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getObjectsOfType
 | 
						|
 | 
						|
        Get a list of data objects of the given type.
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                undef
 | 
						|
                @objlist - list of objects of this type
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
        Comments:
 | 
						|
 | 
						|
                @objlist = xCAT::DBobjUtils->getObjectsOfType($type);
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub getObjectsOfType
 | 
						|
{
 | 
						|
    my ($class, $type) = @_;
 | 
						|
 | 
						|
    my @objlist;
 | 
						|
 | 
						|
    # special case for site table
 | 
						|
    if ($type eq 'site') {
 | 
						|
        push(@objlist, 'clustersite');
 | 
						|
        return @objlist;
 | 
						|
    }
 | 
						|
 | 
						|
    # The database may be changed between getObjectsOfType calls
 | 
						|
    # do not use cache %::saveObjList  if --nocache is specified
 | 
						|
    if ($::saveObjList{$type} && !$::opt_nc) {
 | 
						|
        @objlist = @{ $::saveObjList{$type} };
 | 
						|
    } else {
 | 
						|
 | 
						|
        # get the key for this type object
 | 
						|
        # ex. for "network" type the key is "netname"
 | 
						|
        # get the data type spec from Schema.pm
 | 
						|
        my $datatype = $xCAT::Schema::defspec{$type};
 | 
						|
 | 
						|
        # get the key for this type object
 | 
						|
        #   ex. for "network" type the key is "netname"
 | 
						|
        my $objkey = $datatype->{'objkey'};
 | 
						|
 | 
						|
        my $table;
 | 
						|
        my $tabkey;
 | 
						|
        foreach my $this_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
            my $attr = $this_attr->{attr_name};
 | 
						|
            if ($attr eq $objkey) {
 | 
						|
 | 
						|
                # get the table & key for to lookup
 | 
						|
                # get the actual attr name to use in the table
 | 
						|
                #   - may be different then the attr name used for the object.
 | 
						|
                ($table, $tabkey) = split('\.', $this_attr->{tabentry});
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # get the whole table and add each entry in the objkey column
 | 
						|
        #   to the list of objects.
 | 
						|
        my @TableRowArray = xCAT::DBobjUtils->getDBtable($table);
 | 
						|
 | 
						|
        foreach (@TableRowArray) {
 | 
						|
            push(@objlist, $_->{$tabkey});
 | 
						|
        }
 | 
						|
 | 
						|
        # if this is type "group" we need to check the nodelist table
 | 
						|
        my @nodeGroupList = ();
 | 
						|
        if ($type eq 'group') {
 | 
						|
            my $table         = "nodelist";
 | 
						|
            my @TableRowArray = xCAT::DBobjUtils->getDBtable($table);
 | 
						|
            foreach (@TableRowArray) {
 | 
						|
                my @tmplist = split(',', $_->{'groups'});
 | 
						|
                push(@nodeGroupList, @tmplist);
 | 
						|
            }
 | 
						|
            foreach my $n (@nodeGroupList) {
 | 
						|
                if (!grep(/^$n$/, @objlist)) {
 | 
						|
                    push(@objlist, $n);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        @{ $::saveObjList{$type} } = @objlist;
 | 
						|
    }
 | 
						|
 | 
						|
    return @objlist;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getobjattrs
 | 
						|
 | 
						|
        Get data from tables
 | 
						|
 | 
						|
                $type_hash: objectname=>objtype hash
 | 
						|
                $attrs_ref: only get the specific attributes,
 | 
						|
                            this can be useful especially for performance considerations
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                undef
 | 
						|
                hash ref - (ex. $tabhash{$table}{$objname}{$attr} = $value)
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
                %tabhash = xCAT::DBobjUtils->getobjattrs(\%typehash);
 | 
						|
 | 
						|
        Comments:
 | 
						|
                For now - only support tables that have 'node' as key !!!
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub getobjattrs
 | 
						|
{
 | 
						|
    my $class    = shift;
 | 
						|
    my $ref_hash = shift;
 | 
						|
    my @attrs;
 | 
						|
 | 
						|
    # The $attrs is an optional argument
 | 
						|
    if (ref $_[0]) {
 | 
						|
        @attrs = @{ shift() };
 | 
						|
    }
 | 
						|
    my %typehash = %$ref_hash;
 | 
						|
 | 
						|
    my %tableattrs;
 | 
						|
    my %tabhash;
 | 
						|
 | 
						|
    # get a list of object names for each type
 | 
						|
    my %objtypelist;
 | 
						|
    foreach my $objname (sort (keys %typehash)) {
 | 
						|
 | 
						|
        # get list of objects for each type
 | 
						|
        # $objtypelist{$typehash{$objname}}=$objname;
 | 
						|
        push @{ $objtypelist{ $typehash{$objname} } }, $objname;
 | 
						|
    }
 | 
						|
 | 
						|
    # go through each object type and look up all the info for each object
 | 
						|
    foreach my $objtype (keys %objtypelist) {
 | 
						|
 | 
						|
        # only do node type for now
 | 
						|
        if ($objtype eq 'node') {
 | 
						|
 | 
						|
            # find the list of tables and corresponding attrs
 | 
						|
            # - for this object type
 | 
						|
            # get the object type decription from Schema.pm
 | 
						|
            my $datatype = $xCAT::Schema::defspec{$objtype};
 | 
						|
            foreach my $this_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
                my $attr = $this_attr->{attr_name};
 | 
						|
                if (scalar(@attrs) > 0) {    # Only query specific attributes
 | 
						|
                    if (!grep(/^$attr$/, @attrs)) {
 | 
						|
                        next;                # This attribute is not needed
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                # table_attr is the attr that actually appears in the
 | 
						|
                #  table which could possibly be different then the attr
 | 
						|
                #  used in the node def
 | 
						|
                # ex. 'nodetype.arch'
 | 
						|
                my ($lookup_table, $table_attr) = split('\.', $this_attr->{tabentry});
 | 
						|
                if (!grep(/^$table_attr$/, @{ $tableattrs{$lookup_table} })) {
 | 
						|
                    push @{ $tableattrs{$lookup_table} }, $table_attr;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # foreach table look up the list of attrs for this
 | 
						|
            # list of object names
 | 
						|
            foreach my $table (keys %tableattrs) {
 | 
						|
 | 
						|
                # open the table
 | 
						|
                # with autocommit => 0, it does not work on Ubuntu running mysql
 | 
						|
                my $thistable = xCAT::Table->new($table, -create => 1, -autocommit => 1);
 | 
						|
                if (!$thistable) {
 | 
						|
                    my $rsp;
 | 
						|
                    $rsp->{data}->[0] = "Could not open the \'$table\' table.";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                my @objlist = @{ $objtypelist{$objtype} };
 | 
						|
 | 
						|
                my $rec = $thistable->getNodesAttribs(\@objlist, @{ $tableattrs{$table} });
 | 
						|
 | 
						|
                # fill in %tabhash with any values that are set
 | 
						|
                foreach my $n (@objlist) {
 | 
						|
                    my $tmp1 = $rec->{$n}->[0];
 | 
						|
                    foreach $a (@{ $tableattrs{$table} }) {
 | 
						|
                        if (defined($tmp1->{$a})) {
 | 
						|
                            $tabhash{$table}{$n}{$a} = $tmp1->{$a};
 | 
						|
 | 
						|
                            #print "obj = $n, table = $table, attr =$a, val = $tabhash{$table}{$n}{$a}\n";
 | 
						|
                        } else {
 | 
						|
 | 
						|
                            # Add a has been searched flag to improve the performance
 | 
						|
                            $tabhash{$table}{$n}{ "$a" . "_hassearched" } = 1;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                #$thistable->commit;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return %tabhash;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getobjdefs
 | 
						|
 | 
						|
        Get object definitions from the DB.
 | 
						|
 | 
						|
                $type_hash: objectname=>objtype hash
 | 
						|
                $verbose: optional
 | 
						|
                $attrs_ref: only get the specific attributes,
 | 
						|
                            this can be useful especially for performance considerations
 | 
						|
                $chname_ref: used to get the table entries for changing the object name
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                undef - error
 | 
						|
                hash ref - $objecthash{objectname}{attrname} = value
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
                To use create hash for objectname and object type
 | 
						|
                ex. $objhash{$obj} = $type;
 | 
						|
 | 
						|
                - then call as follows:
 | 
						|
                %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash);
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub getobjdefs
 | 
						|
{
 | 
						|
    my ($class, $hash_ref, $verbose, $attrs_ref, $chname_ref) = @_;
 | 
						|
    my %objhash;
 | 
						|
    my %typehash = %$hash_ref;
 | 
						|
    my %tabhash;
 | 
						|
    my @attrs;
 | 
						|
    if (ref($attrs_ref)) {
 | 
						|
        @attrs = @$attrs_ref;
 | 
						|
    }
 | 
						|
 | 
						|
    @::foundTableList = ();
 | 
						|
 | 
						|
    if ($::ATTRLIST eq "none") {
 | 
						|
 | 
						|
        # just return the list of obj names
 | 
						|
        foreach my $objname (sort (keys %typehash)) {
 | 
						|
            my $type = $typehash{$objname};
 | 
						|
            $objhash{$objname}{'objtype'} = $type;
 | 
						|
        }
 | 
						|
        return %objhash;
 | 
						|
    }
 | 
						|
 | 
						|
    # see if we need to get any objects of type 'node'
 | 
						|
    my $getnodes = 0;
 | 
						|
    foreach my $objname (keys %typehash) {
 | 
						|
        if ($typehash{$objname} eq 'node') {
 | 
						|
            $getnodes = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # if so then get node info from tables now
 | 
						|
    #   still may need to look up values in some tables using
 | 
						|
    #   other keys - also need to figure out what tables to take
 | 
						|
    #   values from when using 'only_if' - see below
 | 
						|
    # - but this saves lots of time
 | 
						|
    if ($getnodes) {
 | 
						|
        if (scalar(@attrs) > 0) {    # Only get specific attributes of the node
 | 
						|
                                     # find the onlyif key for the attributes
 | 
						|
          REDO: my $datatype = $xCAT::Schema::defspec{'node'};
 | 
						|
            foreach my $this_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
                my $attr = $this_attr->{attr_name};
 | 
						|
                if (exists($this_attr->{only_if})) {
 | 
						|
                    my ($onlyif_key, $onlyif_value) = split('\=', $this_attr->{only_if});
 | 
						|
                    if (!grep (/^$onlyif_key$/, @attrs)) {
 | 
						|
                        push @attrs, $onlyif_key;
 | 
						|
                        goto REDO;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            %tabhash = xCAT::DBobjUtils->getobjattrs(\%typehash, \@attrs);
 | 
						|
        } else {
 | 
						|
            %tabhash = xCAT::DBobjUtils->getobjattrs(\%typehash);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Classify the nodes with type
 | 
						|
    my %type_obj = ();
 | 
						|
    foreach my $objname (keys %typehash) {
 | 
						|
        push @{ $type_obj{ $typehash{$objname} } }, $objname;
 | 
						|
    }
 | 
						|
 | 
						|
    foreach my $objtype (sort (keys %type_obj)) {
 | 
						|
        if ($objtype eq 'site') {
 | 
						|
            my @TableRowArray = xCAT::DBobjUtils->getDBtable('site');
 | 
						|
            foreach my $objname (sort @{ $type_obj{$objtype} }) {
 | 
						|
                if (@TableRowArray) {
 | 
						|
                    my $foundinfo = 0;
 | 
						|
                    foreach (@TableRowArray) {
 | 
						|
                        if ($_->{key}) {
 | 
						|
                            if (defined($_->{value})) {
 | 
						|
                                $foundinfo++;
 | 
						|
                                if ($verbose == 1) {
 | 
						|
                                    $objhash{$objname}{ $_->{key} } = "$_->{value}\t(Table:site - Key:$_->{key})";
 | 
						|
                                } else {
 | 
						|
                                    $objhash{$objname}{ $_->{key} } = $_->{value};
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if ($foundinfo) {
 | 
						|
                        $objhash{$objname}{'objtype'} = 'site';
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    my $rsp;
 | 
						|
                    $rsp->{data}->[0] = "Could not read the \'$objname\' object from the \'site\' table.";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } elsif ($objtype eq 'monitoring') {
 | 
						|
 | 
						|
            # need a special case for the monitoring table
 | 
						|
            # - need to check the monsetting table for entries that contain
 | 
						|
            # the same name as the monitoring table entry.
 | 
						|
            my @TableRowArray = xCAT::DBobjUtils->getDBtable('monsetting');
 | 
						|
            foreach my $objname (sort @{ $type_obj{$objtype} }) {
 | 
						|
                if (@TableRowArray) {
 | 
						|
                    my $foundinfo = 0;
 | 
						|
                    foreach (@TableRowArray) {
 | 
						|
                        if ($_->{name} eq $objname) {
 | 
						|
                            if ($_->{key}) {
 | 
						|
                                if (defined($_->{value})) {
 | 
						|
                                    $foundinfo++;
 | 
						|
                                    if ($verbose == 1) {
 | 
						|
                                        $objhash{$objname}{ $_->{key} } = "$_->{value}\t(Table:monsetting)";
 | 
						|
                                    } else {
 | 
						|
                                        $objhash{$objname}{ $_->{key} } = $_->{value};
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if ($foundinfo) {
 | 
						|
                        $objhash{$objname}{'objtype'} = 'monitoring';
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    my $rsp;
 | 
						|
                    $rsp->{data}->[0] = "Could not read the \'$objname\' object from the \'monsetting\' table.";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } elsif (($objtype eq 'auditlog') || ($objtype eq 'eventlog')) {
 | 
						|
 | 
						|
            # Special case for auditlog/eventlog
 | 
						|
            # All the auditlog/eventlog attributes are in auditlog/eventlog table,
 | 
						|
            # Do not need to read the table multiple times for each attribute.
 | 
						|
            # The auditlog/eventlog is likely be very big over time,
 | 
						|
            # performance is a big concern with the general logic
 | 
						|
            my @TableRowArray = xCAT::DBobjUtils->getDBtable($objtype);
 | 
						|
            foreach my $objname (sort @{ $type_obj{$objtype} }) {
 | 
						|
                if (@TableRowArray) {
 | 
						|
                    my $foundinfo = 0;
 | 
						|
                    foreach my $entry (@TableRowArray) {
 | 
						|
                        if ($entry->{recid} eq $objname) {
 | 
						|
                            foreach my $k (keys %{$entry}) {
 | 
						|
 | 
						|
                                # recid is the object name, do not need to be in the attributes list
 | 
						|
                                if ($k eq 'recid') { next; }
 | 
						|
                                if (defined($entry->{$k})) {
 | 
						|
                                    $foundinfo++;
 | 
						|
                                    if ($verbose == 1) {
 | 
						|
                                        $objhash{$objname}{$k} = "$entry->{$k}\t(Table:$objtype - Key:$k)";
 | 
						|
                                    } else {
 | 
						|
                                        $objhash{$objname}{$k} = $entry->{$k};
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                            if ($foundinfo) {
 | 
						|
                                $objhash{$objname}{'objtype'} = $objtype;
 | 
						|
                            }
 | 
						|
 | 
						|
                            # There should not be multiple entries with the same recid
 | 
						|
                            last;
 | 
						|
                        }    # end if($entry->
 | 
						|
                    }    # end foreach my $entry
 | 
						|
                }    # end if(@TableTowArray
 | 
						|
            }    # end foreach my $objname
 | 
						|
        } else {
 | 
						|
 | 
						|
            # get the object type decription from Schema.pm
 | 
						|
            my $datatype = $xCAT::Schema::defspec{$objtype};
 | 
						|
 | 
						|
            # get the key to look for, for this object type
 | 
						|
            my $objkey = $datatype->{'objkey'};
 | 
						|
            # go through the list of valid attrs
 | 
						|
            foreach my $this_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
                my $ent;
 | 
						|
                my $attr = $this_attr->{attr_name};
 | 
						|
 | 
						|
                # skip the key attr  ???
 | 
						|
                if ($attr eq $objkey) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                # skip the attributes that does not needed for node type
 | 
						|
                if ($getnodes) {
 | 
						|
                    if (scalar(@attrs) > 0 && !grep(/^$attr$/, @attrs)) {
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                #  OK - get the info needed to access the DB table
 | 
						|
                #   - i.e. table name, key name, attr names
 | 
						|
 | 
						|
                # need the actual table attr name corresponding
 | 
						|
                #   to the object attr name
 | 
						|
                #  ex. noderes.nfsdir
 | 
						|
                my ($tab, $tabattr) = split('\.', $this_attr->{tabentry});
 | 
						|
 | 
						|
                foreach my $objname (sort @{ $type_obj{$objtype} }) {
 | 
						|
 | 
						|
                    # get table lookup info from Schema.pm
 | 
						|
                    #  !!!! some tables depend on the value of certain attrs
 | 
						|
                    #   we need to look up attrs in the correct order or we will
 | 
						|
                    #   not be able to determine what tables to look
 | 
						|
                    #   in for some attrs.
 | 
						|
                    if (exists($this_attr->{only_if})) {
 | 
						|
                        my ($check_attr, $check_value) = split('\=', $this_attr->{only_if});
 | 
						|
 | 
						|
                        # if the object value is not the value we need
 | 
						|
                        #   to match then try the next only_if value
 | 
						|
                        next if (!($objhash{$objname}{$check_attr} =~ /\b$check_value\b/));
 | 
						|
                    }
 | 
						|
 | 
						|
 | 
						|
                    $objhash{$objname}{'objtype'} = $objtype;
 | 
						|
                    my %tabentry = ();
 | 
						|
 | 
						|
                    # def commands need to support multiple keys in one table
 | 
						|
                    # the subroutine parse_access_tabentry is used for supporting multiple keys
 | 
						|
                    my $rc = xCAT::DBobjUtils->parse_access_tabentry($objname,
 | 
						|
                        $this_attr->{access_tabentry}, \%tabentry);
 | 
						|
                    if ($rc != 0) {
 | 
						|
                        my $rsp;
 | 
						|
                        $rsp->{data}->[0] =
 | 
						|
"access_tabentry \'$this_attr->{access_tabentry}\' is not valid.";
 | 
						|
                        xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    #
 | 
						|
                    # Only allow one table in the access_tabentry
 | 
						|
                    # use multiple tables to look up tabentry does not make any sense
 | 
						|
                    my $lookup_table = $tabentry{'lookup_table'};
 | 
						|
                    my $intabhash    = 0;
 | 
						|
                    my $notsearched  = 0;
 | 
						|
                    foreach my $lookup_attr (keys %{ $tabentry{'lookup_attrs'} }) {
 | 
						|
                        # Check whether the attribute is already in %tabhash
 | 
						|
                        # The %tabhash is for performance considerations
 | 
						|
                        my $tabspec = $xCAT::Schema::tabspec{$lookup_table};
 | 
						|
                        my $nodecol = $tabspec->{'nodecol'} if defined($tabspec->{'nodecol'});
 | 
						|
                        if (($lookup_attr eq 'node' && $objtype eq 'node') || (defined($nodecol) && $objtype eq 'node' && $lookup_table ne 'ppcdirect')) {
 | 
						|
                            if (defined($tabhash{$lookup_table}{$objname}{$tabattr})) {
 | 
						|
                                if ($verbose == 1) {
 | 
						|
                                    $objhash{$objname}{$attr} = "$tabhash{$lookup_table}{$objname}{$tabattr}\t(Table:$lookup_table - Key:$lookup_attr - Column:$tabattr)";
 | 
						|
                                } else {
 | 
						|
                                    $objhash{$objname}{$attr} = $tabhash{$lookup_table}{$objname}{$tabattr};
 | 
						|
                                }
 | 
						|
                                if (defined $chname_ref) {
 | 
						|
                                    push @{ $chname_ref->{$lookup_table} }, ($tabentry{'lookup_attrs'}, $lookup_attr);
 | 
						|
                                }
 | 
						|
                                $intabhash = 1;
 | 
						|
                                last;
 | 
						|
                            } elsif (!defined($tabhash{$lookup_table}{$objname}{ "$tabattr" . "_hassearched" })) {
 | 
						|
                                $notsearched = 1;
 | 
						|
                            }
 | 
						|
                        } else {
 | 
						|
                            $notsearched = 1;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    # Not in tabhash,
 | 
						|
                    # Need to lookup the table
 | 
						|
                    if ($intabhash == 0 && $notsearched == 1) {
 | 
						|
                        # look up attr values
 | 
						|
                        my @rows = xCAT::DBobjUtils->getDBtable($lookup_table);
 | 
						|
                        if (@rows) {
 | 
						|
                            foreach my $rowent (@rows) {
 | 
						|
                                my $match = 1;
 | 
						|
                                my $matchedattr;
 | 
						|
 | 
						|
                                # Again, multiple keys support needs the "foreach"
 | 
						|
                                foreach my $lookup_attr (keys %{ $tabentry{'lookup_attrs'} }) {
 | 
						|
                                    if ($rowent->{$lookup_attr} ne $tabentry{'lookup_attrs'}{$lookup_attr}) {
 | 
						|
                                        $match = 0;
 | 
						|
                                        last;
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                                if ($match == 1) {
 | 
						|
                                    if ($verbose == 1) {
 | 
						|
                                        my @lookup_attrs = keys %{ $tabentry{'lookup_attrs'} };
 | 
						|
                                        $objhash{$objname}{$attr} = "$rowent->{$tabattr}\t(Table:$lookup_table - Key: @lookup_attrs - Column:$tabattr)";
 | 
						|
                                    } else {
 | 
						|
                                        $objhash{$objname}{$attr} = $rowent->{$tabattr};
 | 
						|
                                    }
 | 
						|
                                    if (defined $chname_ref) {
 | 
						|
                                        push @{ $chname_ref->{$lookup_table} }, ($tabentry{'lookup_attrs'}, (keys %{ $tabentry{'lookup_attrs'} })[0]);
 | 
						|
                                    }
 | 
						|
                                }    #end if ($match...
 | 
						|
                            }    #end foreach
 | 
						|
                        }    # end if (defined...
 | 
						|
                    }    #end if ($intabhash...
 | 
						|
                }
 | 
						|
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
    }    #foreach my $objtype
 | 
						|
 | 
						|
    return %objhash;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getDBtable
 | 
						|
 | 
						|
        Get a DB table, cache it , & return list of rows from the table.
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                undef - error
 | 
						|
                @rows - of table
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
        call as follows
 | 
						|
                my @TableRowArray= xCAT::DBobjUtils->getDBtable($tablename);
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub getDBtable
 | 
						|
{
 | 
						|
    my ($class, $table) = @_;
 | 
						|
    my @rows = [];
 | 
						|
 | 
						|
    # save this table info - in case this subr gets called multiple times
 | 
						|
    # --nocache flag specifies not to use cahe
 | 
						|
    if (grep(/^$table$/, @::foundTableList) && !$::opt_nc) {
 | 
						|
 | 
						|
        # already have this
 | 
						|
        @rows = @{ $::TableHash{$table} };
 | 
						|
 | 
						|
    } else {
 | 
						|
 | 
						|
        # need to get info from DB
 | 
						|
        my $thistable = xCAT::Table->new($table, -create => 1);
 | 
						|
        if (!$thistable) {
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
 | 
						|
        #@rows = $thistable->getTable;
 | 
						|
        @rows = @{ $thistable->getAllEntries() };
 | 
						|
 | 
						|
        #   !!!! this routine returns rows even if the table is empty!!!!!!
 | 
						|
 | 
						|
        #  keep track of the fact that we checked this table
 | 
						|
        #   - even if it's empty!
 | 
						|
        push(@::foundTableList, $thistable->{tabname});
 | 
						|
 | 
						|
        @{ $::TableHash{$table} } = @rows;
 | 
						|
 | 
						|
        #$thistable->commit;
 | 
						|
 | 
						|
    }    # end if not cached
 | 
						|
 | 
						|
    if (@rows) {
 | 
						|
        return @rows;
 | 
						|
    } else {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   setobjdefs
 | 
						|
 | 
						|
        Set the object definitions in the DB.
 | 
						|
            - Handles the Schema lookup and updating the DB tables.
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                1 - error
 | 
						|
                0 - OK
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
        To use:
 | 
						|
                -create hash for objectname and object type
 | 
						|
                ex. $objhash{$object}{$attribute} = value;
 | 
						|
 | 
						|
                -then call as follows:
 | 
						|
                if (xCAT::DBobjUtils->setobjdefs(\%objhash) != 0)
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub setobjdefs
 | 
						|
{
 | 
						|
    my ($class, $hash_ref) = @_;
 | 
						|
    my %objhash = %$hash_ref;
 | 
						|
    my %settableref;
 | 
						|
    my $ret = 0;
 | 
						|
    my %allupdates;
 | 
						|
    my $setattrs = 0;
 | 
						|
 | 
						|
    # get the attr=vals for these objects from the DB - if any
 | 
						|
    #   - so we can figure out where to put additional attrs
 | 
						|
    # The getobjdefs call was in the foreach loop,
 | 
						|
    # it caused mkdef/chdef performance issue,
 | 
						|
    # so it is moved out of the foreach loop
 | 
						|
 | 
						|
    my %DBhash;
 | 
						|
    my @attrs;
 | 
						|
    foreach my $objname (keys %objhash) {
 | 
						|
        my $type = $objhash{$objname}{objtype};
 | 
						|
        $DBhash{$objname} = $type;
 | 
						|
        @attrs = keys %{ $objhash{$objname} };
 | 
						|
    }
 | 
						|
 | 
						|
    my %DBattrvals;
 | 
						|
    %DBattrvals = xCAT::DBobjUtils->getobjdefs(\%DBhash, 0, \@attrs);
 | 
						|
 | 
						|
    # for each object figure out:
 | 
						|
    #   - what tables to update
 | 
						|
    #   - which table attrs correspond to which object attrs
 | 
						|
    #   - what the keys are for each table
 | 
						|
    # update the tables a row at a time
 | 
						|
    foreach my $objname (keys %objhash) {
 | 
						|
 | 
						|
        my $obj_need_update = 0;
 | 
						|
        # get attr=val that are set in the DB ??
 | 
						|
        my $type = $objhash{$objname}{objtype};
 | 
						|
 | 
						|
        # handle the monitoring table as a special case !!!!!
 | 
						|
        if ($type eq 'monitoring') {
 | 
						|
 | 
						|
            # Get the names of the attrs stored in monitoring table
 | 
						|
            # get the object type decription from Schema.pm
 | 
						|
            my $datatype = $xCAT::Schema::defspec{$type};
 | 
						|
 | 
						|
            #  get a list of valid attr names
 | 
						|
            #  for this type object
 | 
						|
            my @attrlist;
 | 
						|
            foreach my $entry (@{ $datatype->{'attrs'} }) {
 | 
						|
                push(@attrlist, $entry->{'attr_name'});
 | 
						|
            }
 | 
						|
 | 
						|
            # open the tables (monitoring and monsetting)
 | 
						|
            my $montable = xCAT::Table->new('monitoring', -create => 1, -autocommit => 0);
 | 
						|
            if (!$montable) {
 | 
						|
                my $rsp;
 | 
						|
                $rsp->{data}->[0] = "Could not set the \'$montable\' table.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                return 1;
 | 
						|
            }
 | 
						|
 | 
						|
            # open the table
 | 
						|
            my $monsettable = xCAT::Table->new('monsetting', -create => 1, -autocommit => 0);
 | 
						|
            if (!$monsettable) {
 | 
						|
                my $rsp;
 | 
						|
                $rsp->{data}->[0] = "Could not set the \'$monsettable\' table.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                return 1;
 | 
						|
            }
 | 
						|
 | 
						|
            my %keyhash;
 | 
						|
            my %updates;
 | 
						|
 | 
						|
            foreach my $attr (keys %{ $objhash{$objname} }) {
 | 
						|
                my $val;
 | 
						|
                if ($attr eq 'objtype') {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                # determine the value if we have plus or minus
 | 
						|
                if ($::plus_option) {
 | 
						|
 | 
						|
                    # add new to existing - at the end - comma separated
 | 
						|
                    if (defined($DBattrvals{$objname}{$attr})) {
 | 
						|
                        $val = "$DBattrvals{$objname}{$attr},$objhash{$objname}{$attr}";
 | 
						|
                    } else {
 | 
						|
                        $val = "$objhash{$objname}{$attr}";
 | 
						|
                    }
 | 
						|
                } elsif ($::minus_option) {
 | 
						|
 | 
						|
                    # remove the specified list of values from the current
 | 
						|
                    #   attr values.
 | 
						|
                    if ($DBattrvals{$objname}{$attr}) {
 | 
						|
 | 
						|
                        # get the list of attrs to remove
 | 
						|
                        my @currentList = split(/,/, $DBattrvals{$objname}{$attr});
 | 
						|
                        my @minusList = split(/,/, $objhash{$objname}{$attr});
 | 
						|
 | 
						|
                        # make a new list without the one specified
 | 
						|
                        my $first = 1;
 | 
						|
                        my $newlist;
 | 
						|
                        foreach my $i (@currentList) {
 | 
						|
                            chomp $i;
 | 
						|
                            if (!grep(/^$i$/, @minusList)) {
 | 
						|
 | 
						|
                                # set new groups list for node
 | 
						|
                                if (!$first) {
 | 
						|
                                    $newlist .= ",";
 | 
						|
                                }
 | 
						|
                                $newlist .= $i;
 | 
						|
                                $first = 0;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        $val = $newlist;
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
 | 
						|
                    #just set the attr to what was provided! - replace
 | 
						|
                    $val = $objhash{$objname}{$attr};
 | 
						|
                }
 | 
						|
 | 
						|
                if (grep(/^$attr$/, @attrlist)) {
 | 
						|
 | 
						|
                    # if the attr belong in the monitoring tabel
 | 
						|
                    %keyhash = (name  => $objname);
 | 
						|
                    %updates = ($attr => $val);
 | 
						|
                    $montable->setAttribs(\%keyhash, \%updates);
 | 
						|
                } else {
 | 
						|
 | 
						|
                    # else it belongs in the monsetting table
 | 
						|
                    $keyhash{name}  = $objname;
 | 
						|
                    $keyhash{key}   = $attr;
 | 
						|
                    $updates{value} = $val;
 | 
						|
                    $monsettable->setAttribs(\%keyhash, \%updates);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            $montable->commit;
 | 
						|
            $monsettable->commit;
 | 
						|
            $objhash{$objname}{updated} = 1;
 | 
						|
            next;
 | 
						|
        }    #if ($type eq 'monitoring')
 | 
						|
 | 
						|
        # handle the site table as a special case !!!!!
 | 
						|
        if ($type eq 'site') {
 | 
						|
 | 
						|
            # open the table
 | 
						|
            my $thistable =
 | 
						|
              xCAT::Table->new('site', -create => 1, -autocommit => 0);
 | 
						|
            if (!$thistable) {
 | 
						|
                my $rsp;
 | 
						|
                $rsp->{data}->[0] = "Could not set the \'$thistable\' table.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                return 1;
 | 
						|
            }
 | 
						|
 | 
						|
            foreach my $attr (keys %{ $objhash{$objname} }) {
 | 
						|
                if ($attr eq 'objtype') {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                my %keyhash;
 | 
						|
                $keyhash{key} = $attr;
 | 
						|
 | 
						|
                my $val;
 | 
						|
                if ($::plus_option) {
 | 
						|
 | 
						|
                    # add new to existing - at the end - comma separated
 | 
						|
                    if (defined($DBattrvals{$objname}{$attr})) {
 | 
						|
                        $val =
 | 
						|
"$DBattrvals{$objname}{$attr},$objhash{$objname}{$attr}";
 | 
						|
                    } else {
 | 
						|
                        $val = "$objhash{$objname}{$attr}";
 | 
						|
                    }
 | 
						|
                } elsif ($::minus_option) {
 | 
						|
 | 
						|
                    # remove the specified list of values from the current
 | 
						|
                    #   attr values.
 | 
						|
                    if ($DBattrvals{$objname}{$attr}) {
 | 
						|
 | 
						|
                        # get the list of attrs to remove
 | 
						|
                        my @currentList = split(/,/, $DBattrvals{$objname}{$attr});
 | 
						|
                        my @minusList = split(/,/, $objhash{$objname}{$attr});
 | 
						|
 | 
						|
                        # make a new list without the one specified
 | 
						|
                        my $first = 1;
 | 
						|
                        my $newlist;
 | 
						|
                        foreach my $i (@currentList) {
 | 
						|
                            chomp $i;
 | 
						|
                            if (!grep(/^$i$/, @minusList)) {
 | 
						|
 | 
						|
                                # set new groups list for node
 | 
						|
                                if (!$first) {
 | 
						|
                                    $newlist .= ",";
 | 
						|
                                }
 | 
						|
                                $newlist .= $i;
 | 
						|
                                $first = 0;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        $val = $newlist;
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
 | 
						|
                    #just set the attr to what was provided! - replace
 | 
						|
                    $val = $objhash{$objname}{$attr};
 | 
						|
 | 
						|
                }
 | 
						|
 | 
						|
                if ($val eq "") {    # delete the line
 | 
						|
                    $thistable->delEntries(\%keyhash);
 | 
						|
                } else {             # change the attr
 | 
						|
 | 
						|
                    my %updates;
 | 
						|
                    $updates{value} = $val;
 | 
						|
 | 
						|
                    my ($rc, $str) = $thistable->setAttribs(\%keyhash, \%updates);
 | 
						|
                    if (!defined($rc)) {
 | 
						|
                        if ($::verbose) {
 | 
						|
                            my $rsp;
 | 
						|
                            $rsp->{data}->[0] =
 | 
						|
"Could not set the \'$attr\' attribute of the \'$objname\' object in the xCAT database.";
 | 
						|
                            $rsp->{data}->[1] =
 | 
						|
                              "Error returned is \'$str->errstr\'.";
 | 
						|
                            xCAT::MsgUtils->message("I", $rsp, $::callback);
 | 
						|
                        }
 | 
						|
                        $ret = 1;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
            }
 | 
						|
            unless ($ret) {
 | 
						|
                $objhash{$objname}{updated} = 1;
 | 
						|
            }
 | 
						|
 | 
						|
            $thistable->commit;
 | 
						|
 | 
						|
            next;
 | 
						|
        }    #if ($type eq 'site')
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        #
 | 
						|
        #  handle the rest of the object types
 | 
						|
        #
 | 
						|
 | 
						|
        # get the object type decription from Schema.pm
 | 
						|
        my $datatype = $xCAT::Schema::defspec{$type};
 | 
						|
 | 
						|
        # get the object key to look for, for this object type
 | 
						|
        my $objkey = $datatype->{'objkey'};
 | 
						|
 | 
						|
        #  get a list of valid attr names
 | 
						|
        #     for this type object
 | 
						|
        my %attrlist;
 | 
						|
        foreach my $entry (@{ $datatype->{'attrs'} }) {
 | 
						|
 | 
						|
            #push(@{$attrlist{$type}}, $entry->{'attr_name'});
 | 
						|
            $attrlist{$type}{ $entry->{'attr_name'} } = 1;
 | 
						|
        }
 | 
						|
 | 
						|
        my @attrprovided = ();
 | 
						|
 | 
						|
        # check FINALATTRS to see if all the attrs are valid
 | 
						|
        foreach my $attr (keys %{ $objhash{$objname} }) {
 | 
						|
 | 
						|
            if ($attr eq $objkey) {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            if ($attr eq "objtype") {
 | 
						|
 | 
						|
                # objtype not stored in object definition
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            if (!defined($attrlist{$type}{$attr})) {
 | 
						|
                if ($::verbose) {
 | 
						|
                    my $rsp;
 | 
						|
                    $rsp->{data}->[0] =
 | 
						|
                      "\'$attr\' is not a valid attribute for type \'$type\'.";
 | 
						|
                    $rsp->{data}->[1] = "Skipping to the next attribute.";
 | 
						|
                    xCAT::MsgUtils->message("I", $rsp, $::callback);
 | 
						|
                }
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            push(@attrprovided, $attr);
 | 
						|
        }
 | 
						|
 | 
						|
        #   we need to figure out what table to
 | 
						|
        #      store each attr
 | 
						|
        #   And we must do this in the order given in defspec!!
 | 
						|
 | 
						|
        my @setattrlist = ();
 | 
						|
        my %checkedattrs;
 | 
						|
        my $invalidattr;
 | 
						|
 | 
						|
        foreach my $this_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
            my %keyhash;
 | 
						|
            my %updates;
 | 
						|
            my %tabentry;
 | 
						|
            my ($lookup_table, $lookup_attr, $lookup_data);
 | 
						|
            my $attr_name = $this_attr->{attr_name};
 | 
						|
 | 
						|
            if ($attr_name eq $objkey) {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            # if we have a value for this attribute then process it
 | 
						|
            #   - otherwise go to the next attr
 | 
						|
            if (defined($objhash{$objname}{$attr_name})) {
 | 
						|
 | 
						|
                # check the defspec to see where this attr goes
 | 
						|
 | 
						|
                # the table for this attr might depend on the
 | 
						|
                #       value of some other attr
 | 
						|
                # need to check the only_if entries to find one where the
 | 
						|
                #       other attr value matches what we have
 | 
						|
                #       ex. like if I want to set hdwctrlpoint I will have
 | 
						|
                #               to match the right value for mgtmethod
 | 
						|
                if (exists($this_attr->{only_if})) {
 | 
						|
                    my ($check_attr, $check_value) =
 | 
						|
                      split('\=', $this_attr->{only_if});
 | 
						|
 | 
						|
                    # if my attr value for the attr to check doesn't
 | 
						|
                    #   match this then try the next one
 | 
						|
                    # ex. say I want to set hdwctrlpoint, the table
 | 
						|
                    #   will depend on the mgtmethod attr - so I need
 | 
						|
                    #   to find the 'only_if' that matches the value
 | 
						|
                    #   specified for that attr (ex. mgtmethod=hmc)
 | 
						|
 | 
						|
                    # need to check the attrs we are setting for the object
 | 
						|
                    #   as well as the attrs for this object that may be
 | 
						|
                    #   already set in DB
 | 
						|
 | 
						|
                    if (!($objhash{$objname}{$check_attr}) && !($DBattrvals{$objname}{$check_attr})) {
 | 
						|
 | 
						|
                        # if I didn't already check for this attr
 | 
						|
                        my $rsp;
 | 
						|
                        if (!defined($checkedattrs{$attr_name})) {
 | 
						|
                            push @{ $rsp->{data} }, "Cannot set the \'$attr_name\' attribute unless a value is provided for \'$check_attr\'.";
 | 
						|
 | 
						|
                            foreach my $tmp_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
                                my $attr = $tmp_attr->{attr_name};
 | 
						|
                                if ($attr eq $check_attr) {
 | 
						|
                                    my ($tab, $at) = split(/\./, $tmp_attr->{tabentry});
 | 
						|
                                    my $schema = xCAT::Table->getTableSchema($tab);
 | 
						|
                                    my $desc = $schema->{descriptions}->{$at};
 | 
						|
                                    push @{ $rsp->{data} }, "$check_attr => $desc";
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        xCAT::MsgUtils->message("I", $rsp, $::callback);
 | 
						|
                        $checkedattrs{$attr_name} = 1;
 | 
						|
                        if ($invalidattr->{$attr_name}->{valid} != 1) {
 | 
						|
                            $invalidattr->{$attr_name}->{valid} = 0;
 | 
						|
                            $invalidattr->{$attr_name}->{condition} = "\'$check_attr=$check_value\'";
 | 
						|
                        }
 | 
						|
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (!($objhash{$objname}{$check_attr} =~ /\b$check_value\b/) && !($DBattrvals{$objname}{$check_attr} =~ /\b$check_value\b/)) {
 | 
						|
                        if ($invalidattr->{$attr_name}->{valid} != 1) {
 | 
						|
                            $invalidattr->{$attr_name}->{valid} = 0;
 | 
						|
                            $invalidattr->{$attr_name}->{condition} = "\'$check_attr=$check_value\'";
 | 
						|
 | 
						|
                        }
 | 
						|
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $invalidattr->{$attr_name}->{valid} = 1;
 | 
						|
 | 
						|
                #  get the info needed to write to the DB table
 | 
						|
                #
 | 
						|
                # get the actual attr name to use in the table
 | 
						|
                #    - may be different then the attr name used for the object.
 | 
						|
                my $ntab;
 | 
						|
                ($ntab, $::tabattr) = split('\.', $this_attr->{tabentry});
 | 
						|
 | 
						|
                my $rc = xCAT::DBobjUtils->parse_access_tabentry($objname,
 | 
						|
                    $this_attr->{access_tabentry}, \%tabentry);
 | 
						|
                if ($rc != 0) {
 | 
						|
                    my $rsp;
 | 
						|
                    $rsp->{data}->[0] =
 | 
						|
"access_tabentry \'$this_attr->{access_tabentry}\' is not valid.";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                    $objhash{$objname}{error} = 1;
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                $lookup_table = $tabentry{'lookup_table'};
 | 
						|
 | 
						|
                # Set the lookup criteria for this attribute into %allupdates
 | 
						|
                # the key is 'lookup_attrs'
 | 
						|
                foreach my $lookup_attr (keys %{ $tabentry{'lookup_attrs'} }) {
 | 
						|
                    $allupdates{$lookup_table}{$objname}{$attr_name}{'lookup_attrs'}{$lookup_attr}
 | 
						|
                      = $tabentry{'lookup_attrs'}{$lookup_attr};
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            my $val;
 | 
						|
            my $delim = ',';
 | 
						|
            if (($type eq 'group') && ($DBattrvals{$objname}{'grouptype'} eq 'dynamic')) {
 | 
						|
 | 
						|
                # dynamic node group selection string use "::" as delimiter
 | 
						|
                $delim = '::';
 | 
						|
            }
 | 
						|
 | 
						|
            if ($::plus_option) {
 | 
						|
 | 
						|
                # add new to existing - at the end - comma separated
 | 
						|
                if (defined($DBattrvals{$objname}{$attr_name})) {
 | 
						|
 | 
						|
                    # add the attr into the list if it's not already in the list!
 | 
						|
                    # and avoid the duplicate values
 | 
						|
                    my @DBattrarray = split(/$delim/, $DBattrvals{$objname}{$attr_name});
 | 
						|
                    my @objhasharray = split(/$delim/, $objhash{$objname}{$attr_name});
 | 
						|
                    foreach my $objattr (@objhasharray) {
 | 
						|
                        if (!grep(/^\Q$objattr\E$/, @DBattrarray)) {
 | 
						|
                            push @DBattrarray, $objattr;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    $val = join($delim, @DBattrarray);
 | 
						|
                } else {
 | 
						|
                    $val = "$objhash{$objname}{$attr_name}";
 | 
						|
                }
 | 
						|
 | 
						|
            } elsif ($::minus_option) {
 | 
						|
 | 
						|
                # remove the specified list of values from the current
 | 
						|
                # attr values.
 | 
						|
                if ($DBattrvals{$objname}{$attr_name}) {
 | 
						|
 | 
						|
                    # get the list of attrs to remove
 | 
						|
                    my @currentList =
 | 
						|
                      split(/$delim/, $DBattrvals{$objname}{$attr_name});
 | 
						|
                    my @minusList = split(/$delim/, $objhash{$objname}{$attr_name});
 | 
						|
 | 
						|
                    my $operation_failed = 0;
 | 
						|
                    foreach my $em (@minusList) {
 | 
						|
                        if (!(grep { $_ eq $em } @currentList)) {
 | 
						|
                            if (($::opt_t eq 'group') && ($DBattrvals{$objname}{'grouptype'} ne 'dynamic')) {
 | 
						|
                                my $rsp;
 | 
						|
                                $rsp->{data}->[0] = "$objname is not a member of \'$em\'.";
 | 
						|
                                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                                $operation_failed = 1;
 | 
						|
                            } else {
 | 
						|
                                my $rsp;
 | 
						|
                                $rsp->{data}->[0] = "$em is not in the attribute of \'$attr_name\' for the \'$objname\' definition.";
 | 
						|
                                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                                $operation_failed = 1;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if ($operation_failed) {
 | 
						|
                        $objhash{$objname}{error} = 1;
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
 | 
						|
                    # make a new list without the one specified
 | 
						|
                    my $first = 1;
 | 
						|
                    my $newlist;
 | 
						|
                    foreach my $i (@currentList) {
 | 
						|
                        chomp $i;
 | 
						|
                        if (!grep(/^\Q$i\E$/, @minusList)) {
 | 
						|
 | 
						|
                            # set new list for node
 | 
						|
                            if (!$first) {
 | 
						|
                                $newlist .= "$delim";
 | 
						|
                            }
 | 
						|
                            $newlist .= $i;
 | 
						|
                            $first = 0;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    $val = $newlist;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    my $rsp;
 | 
						|
                    $rsp->{data}->[0] = "No value got for attribute \'$attr_name\' for the \'$objname\' definition.";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
            } else {
 | 
						|
 | 
						|
                #just set the attr to what was provided! - replace
 | 
						|
                $val = $objhash{$objname}{$attr_name};
 | 
						|
 | 
						|
            }
 | 
						|
 | 
						|
            # Set the values into %allupdates
 | 
						|
            # the key is 'tabattrs'
 | 
						|
            $allupdates{$lookup_table}{$objname}{$attr_name}{'tabattrs'}{$::tabattr} = $val;
 | 
						|
            $setattrs = 1;
 | 
						|
            $obj_need_update = 1;
 | 
						|
            push(@setattrlist, $attr_name);
 | 
						|
 | 
						|
        }    # end - foreach attribute
 | 
						|
        if ($obj_need_update) {
 | 
						|
            $objhash{$objname}{updated} = 1;
 | 
						|
        }
 | 
						|
 | 
						|
        my $rsp;
 | 
						|
        foreach my $att (keys %$invalidattr) {
 | 
						|
            if ($invalidattr->{$att}->{valid} != 1) {
 | 
						|
                my $tt = $invalidattr->{$att}->{valid};
 | 
						|
                push @{ $rsp->{data} }, "Cannot set the attr=\'$att\' attribute unless $invalidattr->{$att}->{condition}.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        # TODO - need to get back to this
 | 
						|
        if (0) {
 | 
						|
            #
 | 
						|
            #  check to see if all the attrs got set
 | 
						|
            #
 | 
						|
 | 
						|
            my @errlist;
 | 
						|
            foreach $a (@attrprovided) {
 | 
						|
 | 
						|
                #  is this attr was not set then add it to the error list
 | 
						|
                if (!grep(/^$a$/, @setattrlist)) {
 | 
						|
                    push(@errlist, $a);
 | 
						|
                    $ret = 2;
 | 
						|
                }
 | 
						|
 | 
						|
            }
 | 
						|
            if ($ret == 2) {
 | 
						|
                my $rsp;
 | 
						|
                $rsp->{data}->[0] = "Could not set the following attributes for the \'$objname\' definition in the xCAT database: \'@errlist\'";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
    }    # end - foreach object
 | 
						|
 | 
						|
    #==========================================================#
 | 
						|
    #%allupdates structure:
 | 
						|
    # for command: chdef -t node -o node1 groups=all
 | 
						|
    #              usercomment=ddee passwd.HMC=HMC
 | 
						|
    #              passwd.admin=cluster passwd.general=abc123
 | 
						|
    # the %allupdates will be:
 | 
						|
    #0  'ppcdirect'
 | 
						|
    #1  HASH(0x12783d30)
 | 
						|
    #   'node1' => HASH(0x12783cc4)
 | 
						|
    #      'passwd.HMC' => HASH(0x12783ed4)
 | 
						|
    #         'lookup_attrs' => HASH(0x12783f70)
 | 
						|
    #            'hcp' => 'node1'
 | 
						|
    #            'username' => 'HMC'
 | 
						|
    #         'tabattrs' => HASH(0x12783e8c)
 | 
						|
    #            'password' => 'HMC'
 | 
						|
    #      'passwd.admin' => HASH(0x12783c64)
 | 
						|
    #         'lookup_attrs' => HASH(0x12784000)
 | 
						|
    #            'hcp' => 'node1'
 | 
						|
    #            'username' => 'admin'
 | 
						|
    #         'tabattrs' => HASH(0x12783f64)
 | 
						|
    #            'password' => 'cluster'
 | 
						|
    #      'passwd.general' => HASH(0x12783a6c)
 | 
						|
    #         'lookup_attrs' => HASH(0x12784198)
 | 
						|
    #            'hcp' => 'node1'
 | 
						|
    #            'username' => 'general'
 | 
						|
    #         'tabattrs' => HASH(0x12783aa8)
 | 
						|
    #            'password' => 'abc123'
 | 
						|
    #2  'nodelist'
 | 
						|
    #3  HASH(0x127842b8)
 | 
						|
    #   'node1' => HASH(0x12784378)
 | 
						|
    #      'groups' => HASH(0x12784090)
 | 
						|
    #         'lookup_attrs' => HASH(0x127844bc)
 | 
						|
    #            'node' => 'node1'
 | 
						|
    #         'tabattrs' => HASH(0x1277fd34)
 | 
						|
    #            'groups' => 'all'
 | 
						|
    #      'usercomment' => HASH(0x12784318)
 | 
						|
    #         'lookup_attrs' => HASH(0x12780550)
 | 
						|
    #            'node' => 'node1'
 | 
						|
    #         'tabattrs' => HASH(0x127842f4)
 | 
						|
    #            'comments' => 'ddee'
 | 
						|
    #=================================================================#
 | 
						|
    # now set the attribute values in the tables
 | 
						|
    #   - handles all except site, monitoring & monsetting for now
 | 
						|
    if ($setattrs) {
 | 
						|
        foreach my $table (keys %allupdates) {
 | 
						|
 | 
						|
            # get the keys for this table
 | 
						|
            my $schema = xCAT::Table->getTableSchema($table);
 | 
						|
            my $keys   = $schema->{keys};
 | 
						|
 | 
						|
            # open the table
 | 
						|
            my $thistable = xCAT::Table->new($table, -create => 1, -autocommit => 0);
 | 
						|
            if (!$thistable) {
 | 
						|
                my $rsp;
 | 
						|
                $rsp->{data}->[0] = "Could not set the \'$thistable\' table.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                return 1;
 | 
						|
            }
 | 
						|
 | 
						|
            # Special case for the postscripts table
 | 
						|
            # Does not set the postscripts to the postscripts table
 | 
						|
            # if the postscripts already in xcatdefaults
 | 
						|
            # for code logic, it will be clearer to put the special case into defch,
 | 
						|
            # but putting it into defch will introduce additional table access for postscripts table.
 | 
						|
            # accessing table is time consuming.
 | 
						|
            if ($table eq "postscripts") {
 | 
						|
                my $xcatdefaultsps;
 | 
						|
                my $xcatdefaultspbs;
 | 
						|
                my @TableRowArray = xCAT::DBobjUtils->getDBtable('postscripts');
 | 
						|
                if (@TableRowArray) {
 | 
						|
                    foreach my $tablerow (@TableRowArray) {
 | 
						|
                        if (($tablerow->{node} eq 'xcatdefaults') && !($tablerow->{disable})) {
 | 
						|
                            $xcatdefaultsps  = $tablerow->{postscripts};
 | 
						|
                            $xcatdefaultspbs = $tablerow->{postbootscripts};
 | 
						|
                            last;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                my @xcatdefps  = split(/,/, $xcatdefaultsps);
 | 
						|
                my @xcatdefpbs = split(/,/, $xcatdefaultspbs);
 | 
						|
                foreach my $obj (keys %{ $allupdates{$table} }) {
 | 
						|
                    if ($obj eq 'xcatdefaults') {
 | 
						|
 | 
						|
                        #xcatdefaults can be treated as a node?
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    my @newps;
 | 
						|
                    if (defined($allupdates{$table}{$obj}{'postscripts'})
 | 
						|
                        && defined($allupdates{$table}{$obj}{'postscripts'}{'tabattrs'}{'postscripts'})) {
 | 
						|
                        foreach my $tempps (split(/,/, $allupdates{$table}{$obj}{'postscripts'}{'tabattrs'}{'postscripts'})) {
 | 
						|
                            if (grep(/^$tempps$/, @xcatdefps)) {
 | 
						|
                                my $rsp;
 | 
						|
                                $rsp->{data}->[0] = "$obj: postscripts \'$tempps\' is already included in the \'xcatdefaults\'.";
 | 
						|
                                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                            } else {
 | 
						|
                                push @newps, $tempps;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        $allupdates{$table}{$obj}{'postscripts'}{'tabattrs'}{'postscripts'} = join(',', @newps);
 | 
						|
                    }
 | 
						|
                    my @newpbs;
 | 
						|
                    if (defined($allupdates{$table}{$obj}{'postbootscripts'})
 | 
						|
                        && defined($allupdates{$table}{$obj}{'postbootscripts'}{'tabattrs'}{'postbootscripts'})) {
 | 
						|
                        foreach my $temppbs (split(/,/, $allupdates{$table}{$obj}{'postbootscripts'}{'tabattrs'}{'postbootscripts'})) {
 | 
						|
                            if (grep(/^$temppbs$/, @xcatdefpbs)) {
 | 
						|
                                my $rsp;
 | 
						|
                                $rsp->{data}->[0] = "$obj: postbootscripts \'$temppbs\' is already included in the \'xcatdefaults\'.";
 | 
						|
                                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                            } else {
 | 
						|
                                push @newpbs, $temppbs;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        $allupdates{$table}{$obj}{'postbootscripts'}{'tabattrs'}{'postbootscripts'} = join(',', @newpbs);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            my $commit_manually = 0;
 | 
						|
            my %node_updates;
 | 
						|
          OBJ: foreach my $obj (keys %{ $allupdates{$table} }) {
 | 
						|
                my %keyhash;
 | 
						|
                my %updates;
 | 
						|
                my $firsttime = 1;
 | 
						|
              ROW: foreach my $row (keys %{ $allupdates{$table}{$obj} }) {
 | 
						|
 | 
						|
                    # make sure we have a value for each key
 | 
						|
                    foreach my $k (@$keys) {
 | 
						|
                        if (!$allupdates{$table}{$obj}{$row}{'lookup_attrs'}) {
 | 
						|
                            my $rsp;
 | 
						|
                            $rsp->{data}->[0] = "\nMissing required attribute values for the \'$obj\' object. The required attributes are: @$keys";
 | 
						|
                            xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                            $ret = 1;
 | 
						|
                            next ROW;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ($firsttime) {
 | 
						|
 | 
						|
                        # lookup keys in %hashkey
 | 
						|
                        # ex. $keyhash{'hcp'} = node1
 | 
						|
                        foreach my $key (keys %{ $allupdates{$table}{$obj}{$row}{'lookup_attrs'} }) {
 | 
						|
                            $keyhash{$key} = $allupdates{$table}{$obj}{$row}{'lookup_attrs'}{$key};
 | 
						|
                        }
 | 
						|
                        $firsttime = 0;
 | 
						|
                    } else {
 | 
						|
 | 
						|
                        # check if the look_attrs is the same as the %keyhash
 | 
						|
                        foreach my $key (keys %{ $allupdates{$table}{$obj}{$row}{'lookup_attrs'} }) {
 | 
						|
 | 
						|
                            # The lookup_attrs can be different for tables with more than one keys such as ppcdirect
 | 
						|
                            if ((scalar(keys %keyhash) != scalar(keys %{ $allupdates{$table}{$obj}{$row}{'lookup_attrs'} }))
 | 
						|
                                || !defined($keyhash{$key})
 | 
						|
                                || ($keyhash{$key} ne $allupdates{$table}{$obj}{$row}{'lookup_attrs'}{$key})) {
 | 
						|
 | 
						|
                                # different keys, set the existing attributes into database
 | 
						|
                                # update the %keyhash and clean up the %updates hash
 | 
						|
                                if (%updates) {
 | 
						|
                                    $commit_manually = 1;
 | 
						|
                                    my ($rc, $str) = $thistable->setAttribs(\%keyhash, \%updates);
 | 
						|
                                }
 | 
						|
                                foreach my $key (keys %{ $allupdates{$table}{$obj}{$row}{'lookup_attrs'} }) {
 | 
						|
                                    $keyhash{$key} = $allupdates{$table}{$obj}{$row}{'lookup_attrs'}{$key};
 | 
						|
                                }
 | 
						|
                                %updates = ();
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    # set values in %updates
 | 
						|
                    # ex. $updates{'groups'} = 'all,lpar'
 | 
						|
                    foreach my $attr (keys %{ $allupdates{$table}{$obj}{$row}{'tabattrs'} }) {
 | 
						|
                        if (scalar(keys %keyhash) == 0 && $keyhash{'node'} && $keyhash{'node'} eq "node") {
 | 
						|
                            $node_updates{$obj}{$attr} = $allupdates{$table}{$obj}{$row}{'tabattrs'}{$attr};
 | 
						|
                        } else {
 | 
						|
                            $updates{$attr} = $allupdates{$table}{$obj}{$row}{'tabattrs'}{$attr};
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                }    #end foreach my $row
 | 
						|
                 # only uses the setAttribs to set attribute one by one when the obj type is NOT 'node'
 | 
						|
                if (%updates) {
 | 
						|
                    $commit_manually = 1;
 | 
						|
                    my ($rc, $str) = $thistable->setAttribs(\%keyhash, \%updates);
 | 
						|
                }
 | 
						|
            }    #end foreach my $obj
 | 
						|
            if ($commit_manually) {
 | 
						|
                $thistable->commit;
 | 
						|
            }
 | 
						|
            if (%node_updates) {
 | 
						|
                $thistable->setNodesAttribs(\%node_updates);
 | 
						|
            }
 | 
						|
        }    #end forach my $table
 | 
						|
    }
 | 
						|
    return $ret;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   rmobjdefs
 | 
						|
 | 
						|
        Remove object definitions from the DB.
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                0 - OK
 | 
						|
                1 - error
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
                To use create hash for object name and object type
 | 
						|
                ex. $objhash{$obj} = $type;
 | 
						|
                - then call as follows:
 | 
						|
                xCAT::DBobjUtils->rmobjdefs(\%objhash);
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub rmobjdefs
 | 
						|
{
 | 
						|
    my ($class, $hash_ref) = @_;
 | 
						|
 | 
						|
    my %tablehash;
 | 
						|
 | 
						|
    my %typehash = %$hash_ref;
 | 
						|
 | 
						|
    # get the attr=vals for these objects so we know how to
 | 
						|
    #   find what tables have to be modified
 | 
						|
 | 
						|
    foreach my $objname (sort (keys %typehash)) {
 | 
						|
        my $type = $typehash{$objname};
 | 
						|
 | 
						|
        # special handling for site table
 | 
						|
        if ($type eq 'site') {
 | 
						|
            my %DBattrvals = xCAT::DBobjUtils->getobjdefs(\%typehash);
 | 
						|
            my $thistable =
 | 
						|
              xCAT::Table->new('site', -create => 1, -autocommit => 0);
 | 
						|
            my %keyhash;
 | 
						|
            foreach my $attr (keys %{ $DBattrvals{$objname} }) {
 | 
						|
 | 
						|
                # ex.  key = attr
 | 
						|
                $keyhash{key} = $attr;
 | 
						|
 | 
						|
                $thistable->delEntries(\%keyhash);
 | 
						|
 | 
						|
            }
 | 
						|
            $thistable->commit();
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        # get the object type decription from Schema.pm
 | 
						|
        my $datatype = $xCAT::Schema::defspec{$type};
 | 
						|
 | 
						|
        # go through the list of valid attrs
 | 
						|
        #  - need to delete the row with a $key value of $objname from $table
 | 
						|
        #  - make a hash containing $delhash{$table}{$key}= $objname
 | 
						|
        foreach my $this_attr (@{ $datatype->{'attrs'} }) {
 | 
						|
            my $attr = $this_attr->{attr_name};
 | 
						|
 | 
						|
            # get table lookup info from Schema.pm
 | 
						|
            # def commands need to support multiple keys in one table
 | 
						|
            # the subroutine parse_access_tabentry is used for supporting multiple keys
 | 
						|
            my %tabentry = ();
 | 
						|
            my $rc = xCAT::DBobjUtils->parse_access_tabentry($objname, $this_attr->{access_tabentry}, \%tabentry);
 | 
						|
            if ($rc != 0) {
 | 
						|
                my $rsp;
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
"access_tabentry \'$this_attr->{access_tabentry}\' is not valid.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            # Only allow one table in the access_tabentry
 | 
						|
            # use multiple tables to look up tabentry does not make any sense
 | 
						|
            my $lookup_table = $tabentry{'lookup_table'};
 | 
						|
 | 
						|
            # The attr_name is the *def attribute name instead of db column
 | 
						|
            my $attr_name = $this_attr->{'attr_name'};
 | 
						|
 | 
						|
            # we'll need table name, object name, attribute name and the lookup entries
 | 
						|
            # put this info in a hash - we'll process it later - below
 | 
						|
            foreach my $lookup_attr (keys %{ $tabentry{'lookup_attrs'} }) {
 | 
						|
                $tablehash{$lookup_table}{$objname}{$attr_name}{$lookup_attr}
 | 
						|
                  = $tabentry{'lookup_attrs'}{$lookup_attr};
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #=============================================#
 | 
						|
    # The tablehash looks like this
 | 
						|
    # DB<5> x %tablehash
 | 
						|
    # 'bootparams'
 | 
						|
    # HASH(0x1280828c)
 | 
						|
    #  'node1' => HASH(0x127bca50)
 | 
						|
    #     'addkcmdline' => HASH(0x127fb114)
 | 
						|
    #        'node' => 'node1'
 | 
						|
    #     'initrd' => HASH(0x127bcb40)
 | 
						|
    #        'node' => 'node1'
 | 
						|
    #     'kcmdline' => HASH(0x127fb24c)
 | 
						|
    #        'node' => 'node1'
 | 
						|
    #     'kernel' => HASH(0x127b2e80)
 | 
						|
    #        'node' => 'node1'
 | 
						|
    #  'testfsp' => HASH(0x1280e71c)
 | 
						|
    #     'addkcmdline' => HASH(0x1280e7a0)
 | 
						|
    #        'node' => 'testfsp'
 | 
						|
    #     'initrd' => HASH(0x1280e740)
 | 
						|
    #        'node' => 'testfsp'
 | 
						|
    #     'kcmdline' => HASH(0x1280e77c)
 | 
						|
    #        'node' => 'testfsp'
 | 
						|
    #     'kernel' => HASH(0x1280e758)
 | 
						|
    #        'node' => 'testfsp'
 | 
						|
    #...
 | 
						|
    # 'ppcdirect'
 | 
						|
    # HASH(0x1278fe1c)
 | 
						|
    #  'node1' => HASH(0x12808370)
 | 
						|
    #     'passwd.HMC' => HASH(0x128083e8)
 | 
						|
    #        'hcp' => 'node1'
 | 
						|
    #        'username' => 'HMC'
 | 
						|
    #     'passwd.admin' => HASH(0x128081c0)
 | 
						|
    #        'hcp' => 'node1'
 | 
						|
    #        'username' => 'admin'
 | 
						|
    #     'passwd.general' => HASH(0x128075d8)
 | 
						|
    #        'hcp' => 'node1'
 | 
						|
    #        'username' => 'general'
 | 
						|
    #  'testfsp' => HASH(0x12790620)
 | 
						|
    #     'passwd.HMC' => HASH(0x1280ee84)
 | 
						|
    #        'hcp' => 'testfsp'
 | 
						|
    #        'username' => 'HMC'
 | 
						|
    #     'passwd.admin' => HASH(0x128082f8)
 | 
						|
    #        'hcp' => 'testfsp'
 | 
						|
    #        'username' => 'admin'
 | 
						|
    #     'passwd.general' => HASH(0x1280843c)
 | 
						|
    #        'hcp' => 'testfsp'
 | 
						|
    #        'username' => 'general'
 | 
						|
    #...
 | 
						|
##=========================================================#
 | 
						|
    # now for each table - clear the entry
 | 
						|
    foreach my $table (keys %tablehash) {
 | 
						|
        my @all_keyhash;
 | 
						|
 | 
						|
        my $thistable =
 | 
						|
          xCAT::Table->new($table, -create => 1, -autocommit => 0);
 | 
						|
 | 
						|
        foreach my $obj (keys %{ $tablehash{$table} }) {
 | 
						|
            my %keyhash;
 | 
						|
            foreach my $attr (keys %{ $tablehash{$table}{$obj} }) {
 | 
						|
                foreach my $key (keys %{ $tablehash{$table}{$obj}{$attr} }) {
 | 
						|
 | 
						|
                    #multiple keys support
 | 
						|
                    if (defined($keyhash{$key}) && ($keyhash{$key} ne $tablehash{$table}{$obj}{$attr}{$key})) {
 | 
						|
                        my %tmpkeyhash;
 | 
						|
 | 
						|
                        # copy hash
 | 
						|
                        foreach my $hashkey (keys %keyhash) {
 | 
						|
                            $tmpkeyhash{$hashkey} = $keyhash{$hashkey};
 | 
						|
                        }
 | 
						|
                        push @all_keyhash, \%tmpkeyhash;
 | 
						|
 | 
						|
                        #$thistable->delEntries(\@all_keyhash);
 | 
						|
                    }
 | 
						|
 | 
						|
                    # ex. $keyhash{node}=c68m3hvp01
 | 
						|
                    $keyhash{$key} = $tablehash{$table}{$obj}{$attr}{$key};
 | 
						|
                }
 | 
						|
            }
 | 
						|
            push @all_keyhash, \%keyhash;
 | 
						|
        }
 | 
						|
 | 
						|
        # ex. delete the c68m3hvp01 entry of the node column in the
 | 
						|
        #       nodelist table
 | 
						|
        $thistable->delEntries(\@all_keyhash);
 | 
						|
 | 
						|
        $thistable->commit();
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   readFileInput
 | 
						|
 | 
						|
        Process the command line input piped in from a file.
 | 
						|
                (Support stanza or xml format.)
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                0 - OK
 | 
						|
                1 - error
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
        Comments:
 | 
						|
                Set @::fileobjtypes, @::fileobjnames, %::FILEATTRS
 | 
						|
                (i.e.- $::FILEATTRS{objname}{attr}=val)
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub readFileInput
 | 
						|
{
 | 
						|
    my ($class, $filedata) = @_;
 | 
						|
    my ($objectname, $junk1, $junk2);
 | 
						|
 | 
						|
    @::fileobjnames = ();
 | 
						|
 | 
						|
    my @lines = split /\n/, $filedata;
 | 
						|
 | 
						|
    my $header = $lines[0];
 | 
						|
 | 
						|
    # to do
 | 
						|
    #if ($header =~/<xCAT data object stanza file>/) {
 | 
						|
    # do stanza file parsing
 | 
						|
    # } elsis ($header =~/<xCAT data object XML file>/) {
 | 
						|
    # do XML parsing
 | 
						|
    #}
 | 
						|
 | 
						|
    my $look_for_colon = 1;    # start with first line that has a colon
 | 
						|
    my $objtype;
 | 
						|
 | 
						|
    foreach my $l (@lines) {
 | 
						|
 | 
						|
        # skip blank and comment lines
 | 
						|
        next if ($l =~ /^\s*$/ || $l =~ /^\s*#/);
 | 
						|
 | 
						|
        # see if it's a stanza name
 | 
						|
        if (grep(/:\s*$/, $l)) {
 | 
						|
 | 
						|
            $look_for_colon = 0;    # ok - we have a colon
 | 
						|
 | 
						|
            # Remove any trailing whitespace
 | 
						|
            $l =~ s/\s*$//;
 | 
						|
 | 
						|
            # IPv6 network names could be something like fd59::/64
 | 
						|
            # Use all the characters before the last ":" as the object name
 | 
						|
            # .* means greedy regular expression
 | 
						|
            $l =~ /^(.*):(.*?)$/;
 | 
						|
            ($objectname, $junk2) = ($1, $2);
 | 
						|
 | 
						|
            # if $junk2 is defined or there's an =
 | 
						|
            if ($junk2 || grep(/=/, $objectname)) {
 | 
						|
 | 
						|
                # error - invalid header $line in node definition file
 | 
						|
                #         skipping to next node stanza
 | 
						|
                # Skipping to the next valid header.
 | 
						|
                $look_for_colon++;
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            $objectname =~ s/^\s*//;    # Remove any leading whitespace
 | 
						|
            $objectname =~ s/\s*$//;    # Remove any trailing whitespace
 | 
						|
 | 
						|
            #  could have different default stanzas for different object types
 | 
						|
 | 
						|
            if ($objectname =~ /default/) {
 | 
						|
 | 
						|
                ($junk1, $objtype) = split(/-/, $objectname);
 | 
						|
 | 
						|
                if ($objtype) {
 | 
						|
                    $objectname = 'default';
 | 
						|
                }
 | 
						|
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            push(@::fileobjnames, $objectname);
 | 
						|
 | 
						|
        } elsif (($l =~ /^\s*(.*?)\s*=\s*(.*)\s*/) && (!$look_for_colon)) {
 | 
						|
            my $attr = $1;
 | 
						|
            my $val  = $2;
 | 
						|
            $attr =~ s/^\s*//;    # Remove any leading whitespace
 | 
						|
            $attr =~ s/\s*$//;    # Remove any trailing whitespace
 | 
						|
            $val =~ s/^\s*//;
 | 
						|
            $val =~ s/\s*$//;
 | 
						|
 | 
						|
            # remove spaces and quotes so createnode won't get upset
 | 
						|
            $val =~ s/^\s*"\s*//;
 | 
						|
            $val =~ s/\s*"\s*$//;
 | 
						|
 | 
						|
            if ($objectname eq "default") {
 | 
						|
 | 
						|
                # set the default for this attribute
 | 
						|
                $::defAttrs{$objtype}{$attr} = $val;
 | 
						|
 | 
						|
            } else {
 | 
						|
 | 
						|
                # set the value in the hash for this object
 | 
						|
                $::FILEATTRS{$objectname}{$attr} = $val;
 | 
						|
 | 
						|
                # if the attr being set is "objtype" then check
 | 
						|
                # to see if we have any defaults set for this type
 | 
						|
                # the objtype should be the first etntry in each stanza
 | 
						|
                # so after we set the defaults they will be overwritten
 | 
						|
                # by any values that appear in the rest of the stanza
 | 
						|
                if ($attr eq 'objtype') {
 | 
						|
                    push(@::fileobjtypes, $val);
 | 
						|
 | 
						|
                    #  $val will be the object type ex. site, node etc.
 | 
						|
                    foreach my $a (keys %{ $::defAttrs{$val} }) {
 | 
						|
 | 
						|
                        # set the default values for this object hash
 | 
						|
                        $::FILEATTRS{$objectname}{$a} = $::defAttrs{$val}{$a};
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
        } else {
 | 
						|
 | 
						|
            # error - invalid line in node definition file
 | 
						|
            $look_for_colon++;
 | 
						|
        }
 | 
						|
 | 
						|
    }    # end while - go to next line
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getGroupMembers
 | 
						|
 | 
						|
        Get the list of members for the specified group.
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
            undef - error
 | 
						|
            $members - comma-separated list of group members
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
        To use:
 | 
						|
            - create hash for objectname and and attr values  (need group
 | 
						|
              name (object), and grouptype  & members attr values at a
 | 
						|
              minimum.)
 | 
						|
 | 
						|
              ex. $objhash{$obj}{$attr} = value;
 | 
						|
 | 
						|
            - then call as follows:
 | 
						|
              xCAT::DBobjUtils->getGroupMembers($objectname, \%objhash);
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub getGroupMembers
 | 
						|
{
 | 
						|
    my ($class, $objectname, $hash_ref) = @_;
 | 
						|
 | 
						|
    my $members;
 | 
						|
 | 
						|
    my %objhash = %$hash_ref;
 | 
						|
 | 
						|
    # set 'static' as the dafault of nodetype
 | 
						|
    if (!defined($objhash{$objectname}{'grouptype'}) ||
 | 
						|
        $objhash{$objectname}{'grouptype'} eq "") {
 | 
						|
        $objhash{$objectname}{'grouptype'} = 'static';
 | 
						|
    }
 | 
						|
 | 
						|
    if ($objhash{$objectname}{'grouptype'} eq 'static') {
 | 
						|
 | 
						|
        my $table = "nodelist";
 | 
						|
 | 
						|
        my @TableRowArray = xCAT::DBobjUtils->getDBtable($table);
 | 
						|
 | 
						|
        my $first = 1;
 | 
						|
        foreach (@TableRowArray) {
 | 
						|
 | 
						|
            # if find the group name in the "groups" attr value then add the
 | 
						|
            # node name to the member list
 | 
						|
            #if ($_->{'groups'} =~ /$objectname/)
 | 
						|
 | 
						|
            my @nodeGroupList = split(',', $_->{'groups'});
 | 
						|
            if (grep(/^$objectname$/, @nodeGroupList)) {
 | 
						|
                chomp($_->{'node'});
 | 
						|
                if (!$first) {
 | 
						|
                    $members .= ",";
 | 
						|
                }
 | 
						|
                $members .= $_->{'node'};
 | 
						|
                $first = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
    } elsif ($objhash{$objectname}{'grouptype'} eq 'dynamic') {
 | 
						|
 | 
						|
        # find all nodes that satisfy the criteria specified in "wherevals"
 | 
						|
        # value
 | 
						|
        my %whereHash;
 | 
						|
        my %tabhash;
 | 
						|
 | 
						|
        # remove spaces and quotes so createnode won't get upset
 | 
						|
        #$val =~ s/^\s*"\s*//;
 | 
						|
        #$val =~ s/\s*"\s*$//;
 | 
						|
 | 
						|
        my @tmpWhereList = split('::', $objhash{$objectname}{'wherevals'});
 | 
						|
        my $rc = xCAT::Utils->parse_selection_string(\@tmpWhereList, \%whereHash);
 | 
						|
        if ($rc != 0) {
 | 
						|
            my $rsp;
 | 
						|
            $rsp->{data}->[0] =
 | 
						|
              "The \'-w\' option has an incorrect attr*val pair.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
        }
 | 
						|
 | 
						|
        # see what nodes have these attr=values
 | 
						|
        # get a list of all nodes
 | 
						|
        my @tmplist = xCAT::DBobjUtils->getObjectsOfType('node');
 | 
						|
 | 
						|
        # create a hash of obj names and types
 | 
						|
        my %tmphash;
 | 
						|
        foreach my $n (@tmplist) {
 | 
						|
            $tmphash{$n} = 'node';
 | 
						|
        }
 | 
						|
 | 
						|
        # Only get the specific attributes of the node
 | 
						|
        my @whereattrs = keys %whereHash;
 | 
						|
        my %nodeattrhash = xCAT::DBobjUtils->getobjdefs(\%tmphash, 0, \@whereattrs);
 | 
						|
 | 
						|
        # The attribute 'node' can be used as a key of selection string,
 | 
						|
        # however, the 'node' attribute is not included in the getobjdefs hash
 | 
						|
        foreach my $objname (keys %nodeattrhash) {
 | 
						|
            $nodeattrhash{$objname}{'node'} = $objname;
 | 
						|
        }
 | 
						|
        my $first = 1;
 | 
						|
        foreach my $objname (keys %nodeattrhash) {
 | 
						|
            if (xCAT::Utils->selection_string_match(\%nodeattrhash, $objname, \%whereHash)) {
 | 
						|
                chomp($objname);
 | 
						|
                if (!$first) {
 | 
						|
                    $members .= ",";
 | 
						|
                }
 | 
						|
                $members .= $objname;
 | 
						|
                $first = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    return $members;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getNetwkInfo
 | 
						|
 | 
						|
        Get the network info from the database for a list of nodes.
 | 
						|
 | 
						|
        Arguments:
 | 
						|
        Returns:
 | 
						|
                undef
 | 
						|
                hash ref - ex. $nethash{nodename}{networks attr name} = value
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
                %nethash = xCAT::DBobjUtils->getNetwkInfo(\@targetnodes);
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub getNetwkInfo
 | 
						|
{
 | 
						|
    my ($class, $ref_nodes) = @_;
 | 
						|
    my @nodelist = @$ref_nodes;
 | 
						|
 | 
						|
    my %nethash;
 | 
						|
    my @attrnames;
 | 
						|
 | 
						|
    # get the current list of network attrs (networks table columns)
 | 
						|
    my $datatype = $xCAT::Schema::defspec{'network'};
 | 
						|
    foreach my $a (@{ $datatype->{'attrs'} }) {
 | 
						|
        my $attr = $a->{attr_name};
 | 
						|
        push(@attrnames, $attr);
 | 
						|
    }
 | 
						|
 | 
						|
    # read the networks table
 | 
						|
    my @TableRowArray = xCAT::DBobjUtils->getDBtable('networks');
 | 
						|
    if (!@TableRowArray) {
 | 
						|
        return undef;
 | 
						|
    }
 | 
						|
 | 
						|
    # for each node - get the network info
 | 
						|
    foreach my $node (@nodelist) {
 | 
						|
 | 
						|
        # get, check, split the node IP
 | 
						|
        my $IP = xCAT::NetworkUtils->getipaddr($node);
 | 
						|
        chomp $IP;
 | 
						|
        unless (($IP =~ /\d+\.\d+\.\d+\.\d+/) || ($IP =~ /:/)) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        my ($ia, $ib, $ic, $id) = split('\.', $IP);
 | 
						|
 | 
						|
        # check the entries of the networks table
 | 
						|
        # - if the bitwise AND of the IP and the netmask gives you
 | 
						|
        # the "net" name then that is the entry you want.
 | 
						|
        foreach (@TableRowArray) {
 | 
						|
            my $NM  = $_->{'mask'};
 | 
						|
            my $net = $_->{'net'};
 | 
						|
            chomp $NM;
 | 
						|
            chomp $net;
 | 
						|
 | 
						|
            if (xCAT::NetworkUtils->ishostinsubnet($IP, $NM, $net)) {
 | 
						|
 | 
						|
                # fill in the hash -
 | 
						|
                foreach my $attr (@attrnames) {
 | 
						|
                    if (defined($_->{$attr})) {
 | 
						|
                        $nethash{$node}{$attr} = $_->{$attr};
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ($nethash{$node}{'gateway'} eq '<xcatmaster>') {
 | 
						|
                    if (xCAT::NetworkUtils->ip_forwarding_enabled()) {
 | 
						|
                        $nethash{$node}{'gateway'} = xCAT::NetworkUtils->my_ip_in_subnet($net, $NM);
 | 
						|
                    } else {
 | 
						|
                        $nethash{$node}{'gateway'} = '';
 | 
						|
                    }
 | 
						|
                    $nethash{$node}{'myselfgw'} = 1;
 | 
						|
 | 
						|
                    # For hwctrl commands, it is possible that this subroutine is called
 | 
						|
                    # on MN instead of SN, if the hcp SN is not set
 | 
						|
                    if (xCAT::Utils->isMN() && !$nethash{$node}{'gateway'}) {
 | 
						|
 | 
						|
                        # does not have ip address in this subnet,
 | 
						|
                        # use the node attribute 'xcatmaster' or site.master
 | 
						|
                        my @nodes = ("$node");
 | 
						|
                        my $sn = xCAT::ServiceNodeUtils->get_ServiceNode(\@nodes, "xcat", "Node");
 | 
						|
                        my $snkey = (keys %{$sn})[0];
 | 
						|
                        my $gw    = xCAT::NetworkUtils->getipaddr($snkey);
 | 
						|
 | 
						|
                        # two possible cases when this code is run:
 | 
						|
                        # 1. flat cluster: ip forwarding is not enabled on MN
 | 
						|
                        # 2. hw ctrl in hierarchy cluster, in which HCP SN is not set
 | 
						|
                        # in either case, MN itself should not be the gateway
 | 
						|
                        if (xCAT::NetworkUtils->thishostisnot($gw)) {
 | 
						|
                            $nethash{$node}{'gateway'} = $gw;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                }
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
    }    #end - for each node
 | 
						|
 | 
						|
    return %nethash;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   parse_access_tabentry
 | 
						|
 | 
						|
        Parse the access_tabentry field in Schema.pm.
 | 
						|
        We needs to support multiple keys in the table
 | 
						|
        Arguments:
 | 
						|
                $objname: objectname=>objtype hash
 | 
						|
                $access_tabentry: the access_tabentry defined in Schema.pm
 | 
						|
                $tabentry_ref: return the parsed result through this hash ref
 | 
						|
                                The structure of the hash is:
 | 
						|
                                {
 | 
						|
                                    'lookup_tables' => <table_name>
 | 
						|
                                    'lookup_attrs' =>
 | 
						|
                                    {
 | 
						|
                                        'attr1' => 'val1'
 | 
						|
                                        'attr2' => 'val2'
 | 
						|
                                        ...
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
        Returns:
 | 
						|
                0 - success
 | 
						|
                1 - failed
 | 
						|
        Globals:
 | 
						|
        Error:
 | 
						|
        Example:
 | 
						|
 | 
						|
                To parse the access_tabentry field
 | 
						|
 | 
						|
                my $rc = xCAT::DBobjUtils->parse_access_tabentry($objname, $this_attr->{access_tabentry}, \%tabentry);
 | 
						|
 | 
						|
        Comments:
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub parse_access_tabentry()
 | 
						|
{
 | 
						|
    my ($class, $objname, $access_tabentry, $tabentry_ref) = @_;
 | 
						|
 | 
						|
    # ex. 'nodelist.node', 'attr:node'
 | 
						|
    foreach my $ent (split('::', $access_tabentry)) {
 | 
						|
 | 
						|
        # ex. 'nodelist.node', 'attr:node'
 | 
						|
        my ($lookup_key, $lookup_value) = split('\=', $ent);
 | 
						|
 | 
						|
        # ex. 'nodelist', 'node'
 | 
						|
        my ($lookup_table, $lookup_attr) = split('\.', $lookup_key);
 | 
						|
 | 
						|
        # ex. 'attr', 'node'
 | 
						|
        my ($lookup_type, $lookup_data) = split('\:', $lookup_value);
 | 
						|
 | 
						|
        if (!defined($tabentry_ref->{'lookup_table'})) {
 | 
						|
            $tabentry_ref->{'lookup_table'} = $lookup_table;
 | 
						|
        }
 | 
						|
 | 
						|
        # Only support one lookup table in the access_tabentry
 | 
						|
        # Do we need to support multiple tables in one access_tabentry ????
 | 
						|
        # has not seen any requirement...
 | 
						|
        if ($lookup_table ne $tabentry_ref->{'lookup_table'}) {
 | 
						|
            my $rsp;
 | 
						|
            $rsp->{data}->[0] =
 | 
						|
"The access_tabentry \"$access_tabentry\" is not valid, can not specify more than one tables to look up.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
 | 
						|
        if ($lookup_type eq 'attr') {
 | 
						|
 | 
						|
            # TODO: may need to update in the future
 | 
						|
            # for now, the "val" in attr:val in
 | 
						|
            # Schema.pm can only be the object name
 | 
						|
            # In the future, even if we need to change here,
 | 
						|
            # be caution about the performance
 | 
						|
            # looking up table is time consuming
 | 
						|
            $tabentry_ref->{'lookup_attrs'}->{$lookup_attr} = $objname;
 | 
						|
        } elsif ($lookup_type eq 'str') {
 | 
						|
            $tabentry_ref->{'lookup_attrs'}->{$lookup_attr} = $lookup_data;
 | 
						|
        } else {
 | 
						|
            my $rsp;
 | 
						|
            $rsp->{data}->[0] =
 | 
						|
"The access_tabentry \"$access_tabentry\" is not valid, the lookup type can only be 'attr' or 'str'.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $::callback);
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getchildren
 | 
						|
    Arguments:
 | 
						|
        single hostname
 | 
						|
        optional port number
 | 
						|
    Returns:
 | 
						|
        array of fsp/bpa hostnames (IPs)
 | 
						|
        if specified port, it will just return nodes within the port.
 | 
						|
    Globals:
 | 
						|
        %PPCHASH - HASH of nodename -> array of ip addresses
 | 
						|
                    where the nodetype is fsp or bpa
 | 
						|
    Error:
 | 
						|
        $::RUNCMD_RC = 1;
 | 
						|
        Writes error to syslog
 | 
						|
    Example:
 | 
						|
        $c1 = getchildren($nodetocheck);
 | 
						|
        $c1 = getchildren($nodetocheck,$port);
 | 
						|
    Comments:
 | 
						|
        none
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
my %PPCHASH;
 | 
						|
 | 
						|
sub getchildren
 | 
						|
{
 | 
						|
    my $parent = shift;
 | 
						|
    if (($parent) && ($parent =~ /xCAT::/)) {
 | 
						|
        $parent = shift;
 | 
						|
    }
 | 
						|
    $::RUNCMD_RC = 0;
 | 
						|
    my $port          = shift;
 | 
						|
    my @tabletype     = qw(ppc zvm);
 | 
						|
    my @children      = ();
 | 
						|
    my @children_port = ();
 | 
						|
    if (!%PPCHASH) {
 | 
						|
        my $ppctab = xCAT::Table->new('ppc');
 | 
						|
        unless ($ppctab) {    # cannot open  the table return with error
 | 
						|
            xCAT::MsgUtils->message('S', "getchildren:Unable to open ppc table.\n");
 | 
						|
            $::RUNCMD_RC = 1;
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
        my @ps = $ppctab->getAllNodeAttribs([ 'node', 'parent', 'nodetype', 'hcp' ]);
 | 
						|
        foreach my $entry (@ps) {
 | 
						|
            my $p = $entry->{parent};
 | 
						|
            my $c = $entry->{node};
 | 
						|
            my $t = $entry->{nodetype};
 | 
						|
            if ($p and $c) {
 | 
						|
                if ($t) {     # the nodetype exists in the ppc table, use it
 | 
						|
                    if ($t eq 'fsp' or $t eq 'bpa') {
 | 
						|
 | 
						|
                        # build hash of ppc.parent -> ppc.node
 | 
						|
                        push @{ $PPCHASH{$p} }, $c;
 | 
						|
                    } elsif ($t eq 'blade') {
 | 
						|
                        push @{ $PPCHASH{$c} }, $entry->{hcp};
 | 
						|
                    }
 | 
						|
                } else {      # go look in the nodetype table to find nodetype
 | 
						|
                    my $type = getnodetype($c, "ppc");
 | 
						|
                    if ($type eq 'fsp' or $type eq 'bpa') {
 | 
						|
 | 
						|
                        # build hash of ppc.parent -> ppc.node
 | 
						|
                        push @{ $PPCHASH{$p} }, $c;
 | 
						|
                    } elsif ($type eq "blade") {
 | 
						|
                        push @{ $PPCHASH{$c} }, $entry->{hcp};
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }    # not $p and $c
 | 
						|
        }
 | 
						|
 | 
						|
        # Find parent in the hash and build return values
 | 
						|
        foreach (@{ $PPCHASH{$parent} }) {
 | 
						|
            push @children, $_;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        if (exists($PPCHASH{$parent})) {
 | 
						|
            foreach (@{ $PPCHASH{$parent} }) {
 | 
						|
                push @children, $_;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # if port not input
 | 
						|
    if (!defined($port)) {
 | 
						|
        return \@children;
 | 
						|
    } else {
 | 
						|
        if (@children) {
 | 
						|
            my $vpdtab = xCAT::Table->new('vpd');
 | 
						|
            unless ($vpdtab) {    # cannot open  the table return with error
 | 
						|
                xCAT::MsgUtils->message('S', "getchildren:Unable to open vpd table.\n");
 | 
						|
                $::RUNCMD_RC = 1;
 | 
						|
                return undef;
 | 
						|
            }
 | 
						|
            my $sides = $vpdtab->getNodesAttribs(\@children, ['side']);
 | 
						|
            if (!$sides) {
 | 
						|
                return undef;
 | 
						|
            }
 | 
						|
            foreach my $n (@children) {
 | 
						|
                my $nside = $sides->{$n}->[0];
 | 
						|
                if ($nside->{side} =~ /$port/) {
 | 
						|
                    push @children_port, $n;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return \@children_port;
 | 
						|
        } else {    # no children
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getnodetype
 | 
						|
    Query ppc table, if no type found query nodetype table
 | 
						|
    Arguments:
 | 
						|
        An array of nodenames or 1 nodename
 | 
						|
    Returns:
 | 
						|
        If the input is an array, it returns a hash,
 | 
						|
        for the nodes that can't get node type, it will be 'node' => undef;
 | 
						|
        If the input is not an array, it returns the value of type,
 | 
						|
        for the node that can't get node type, it will be undef;
 | 
						|
    Globals:
 | 
						|
        %NODETYPEHASH
 | 
						|
    Error:
 | 
						|
        $::RUNCMD_RC = 1;
 | 
						|
        Errors written to syslog
 | 
						|
    Example:
 | 
						|
        $type = xCAT::DBobjUtils->getnodetype($node, "ppc");
 | 
						|
        $type = xCAT::DBobjUtils->getnodetype($node);
 | 
						|
        $typerefer = xCAT::DBobjUtils->getnodetype(\@nodes, "PPC");
 | 
						|
        $typerefer = xCAT::DBobjUtils->getnodetype(\@nodes);
 | 
						|
    Comments:
 | 
						|
        none
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
my %NODETYPEHASH;
 | 
						|
 | 
						|
sub getnodetype
 | 
						|
{
 | 
						|
    my $nodes = shift;
 | 
						|
    if (($nodes) && ($nodes =~ /xCAT::/)) {
 | 
						|
        $nodes = shift;
 | 
						|
    }
 | 
						|
    my $table = shift;
 | 
						|
    my $rsp;
 | 
						|
    my @tabletype = qw(ppc zvm);
 | 
						|
    my %typehash;
 | 
						|
    my %tablehash;
 | 
						|
    $::RUNCMD_RC = 0;
 | 
						|
 | 
						|
    my @failnodes;
 | 
						|
    my @failnodes1;
 | 
						|
    ######################################################################
 | 
						|
    # if the table arg is set, go to the specified table first
 | 
						|
    # if can't get anything from the specified table, go to nodetype table
 | 
						|
    ######################################################################
 | 
						|
    if ($table) {
 | 
						|
        my $nodetypetab = xCAT::Table->new($table);
 | 
						|
        unless ($nodetypetab) {
 | 
						|
            xCAT::MsgUtils->message('S', "getnodetype:Unable to open $table table.\n");
 | 
						|
            $::RUNCMD_RC = 1;
 | 
						|
            if ($nodes =~ /^ARRAY/) {
 | 
						|
                foreach my $tn (@$nodes) {
 | 
						|
                    $typehash{$tn} = undef;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                $typehash{$nodes} = undef;
 | 
						|
            }
 | 
						|
            return \%typehash;
 | 
						|
        }
 | 
						|
        ############################################
 | 
						|
        # if the input node arg is an array,
 | 
						|
        # query table and don't use the global hash
 | 
						|
        ############################################
 | 
						|
        if ($nodes =~ /^ARRAY/) {
 | 
						|
            my $nodetypes = $nodetypetab->getNodesAttribs($nodes, ['nodetype']);
 | 
						|
            foreach my $tn (@$nodes) {
 | 
						|
                my $gottype = $nodetypes->{$tn}->[0]->{'nodetype'};
 | 
						|
                if ($gottype) {
 | 
						|
                    $NODETYPEHASH{$tn} = $gottype;
 | 
						|
                    $typehash{$tn}     = $gottype;
 | 
						|
                } else {
 | 
						|
                    push @failnodes, $tn;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            ################################################
 | 
						|
            # for the failed nodes, go to nodetype table
 | 
						|
            ################################################
 | 
						|
            if (@failnodes) {
 | 
						|
                my $typetable = xCAT::Table->new('nodetype');
 | 
						|
                unless ($typetable) { # cannot open  the table return with error
 | 
						|
                    xCAT::MsgUtils->message('S', "getnodetype:Unable to open nodetype table.\n");
 | 
						|
                    $::RUNCMD_RC = 1;
 | 
						|
                    foreach my $tn (@failnodes) {
 | 
						|
                        $typehash{$tn} = undef;
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    my $nodetypes = $nodetypetab->getNodesAttribs(\@failnodes, ['nodetype']);
 | 
						|
                    foreach my $tn (@failnodes) {
 | 
						|
                        if ($nodetypes->{$tn}->[0]) {
 | 
						|
                            $NODETYPEHASH{$tn} = $nodetypes->{$tn}->[0]->{'nodetype'};
 | 
						|
                            $typehash{$tn} = $nodetypes->{$tn}->[0]->{'nodetype'};
 | 
						|
                        } else {
 | 
						|
                            push @failnodes1, $tn;
 | 
						|
                            $typehash{$tn} = undef;
 | 
						|
                        }
 | 
						|
                        ##################################################
 | 
						|
                        # give error msg for the nodes can't get nodetype
 | 
						|
                        ##################################################
 | 
						|
                    }
 | 
						|
                    if (@failnodes1) {
 | 
						|
                        my $nodelist = join(",", @failnodes1);
 | 
						|
                        xCAT::MsgUtils->message('S', "getnodetype:Can't find these nodes' type: $nodelist.\n");
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            #####################
 | 
						|
            # return the result
 | 
						|
            #####################
 | 
						|
            return \%typehash;
 | 
						|
 | 
						|
        } else {
 | 
						|
            ############################################
 | 
						|
            # if the input node arg is not an array,
 | 
						|
            # query table and use the global hash first
 | 
						|
            ############################################
 | 
						|
            if ($NODETYPEHASH{$nodes}) {
 | 
						|
                return $NODETYPEHASH{$nodes};
 | 
						|
            } else {
 | 
						|
                my $typep = $nodetypetab->getNodeAttribs($nodes, ['nodetype']);
 | 
						|
                if ($typep->{nodetype}) {
 | 
						|
                    $NODETYPEHASH{$nodes} = $typep->{nodetype};
 | 
						|
                    return $typep->{nodetype};
 | 
						|
                } else { #if not find in the specified table, go to nodetype table
 | 
						|
                    my $typetable = xCAT::Table->new('nodetype');
 | 
						|
                    unless ($typetable) { # cannot open  the table return with error
 | 
						|
                        xCAT::MsgUtils->message('S', "getnodetype:Unable to open nodetype table.\n");
 | 
						|
                        $::RUNCMD_RC = 1;
 | 
						|
                        return undef;
 | 
						|
                    }
 | 
						|
                    my $typep = $typetable->getNodeAttribs($nodes, ['nodetype']);
 | 
						|
                    if ($typep->{nodetype}) {
 | 
						|
                        $NODETYPEHASH{$nodes} = $typep->{nodetype};
 | 
						|
                        return $typep->{nodetype};
 | 
						|
                    } else {
 | 
						|
                        return undef;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        ######################################################################
 | 
						|
        # if the table arg is not set, go to the nodetype table first
 | 
						|
        # if can't get anything from the specified table, go to nodetype table
 | 
						|
        ######################################################################
 | 
						|
        my $nodetypetab = xCAT::Table->new('nodetype');
 | 
						|
        unless ($nodetypetab) {
 | 
						|
            xCAT::MsgUtils->message('S', "getnodetype:Unable to open $table table.\n");
 | 
						|
            $::RUNCMD_RC = 1;
 | 
						|
            if ($nodes =~ /^ARRAY/) {
 | 
						|
                foreach my $tn (@$nodes) {
 | 
						|
                    $typehash{$tn} = undef;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                $typehash{$nodes} = undef;
 | 
						|
            }
 | 
						|
            return \%typehash;
 | 
						|
        }
 | 
						|
        ############################################
 | 
						|
        # if the input node arg is an array,
 | 
						|
        # query table and don't use the global hash
 | 
						|
        ############################################
 | 
						|
        if ($nodes =~ /^ARRAY/) {
 | 
						|
            my $nodetypes = $nodetypetab->getNodesAttribs($nodes, ['nodetype']);
 | 
						|
            foreach my $tn (@$nodes) {
 | 
						|
                my $gottype = $nodetypes->{$tn}->[0]->{'nodetype'};
 | 
						|
                if ($gottype) {
 | 
						|
                    if ($gottype =~ /,/) {    #if find ppc,osi
 | 
						|
                        my @tbty = split /,/, $gottype;
 | 
						|
                        foreach my $ttable (@tbty) {
 | 
						|
                            if (grep(/$ttable/, @tabletype)) {
 | 
						|
                                $tablehash{$tn} = $ttable;
 | 
						|
                                last;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    } elsif (grep(/$gottype/, @tabletype)) { #if find ppc or zvm
 | 
						|
                        $tablehash{$tn} = $gottype;
 | 
						|
                    } else {
 | 
						|
                        $NODETYPEHASH{$tn} = $gottype;
 | 
						|
                        $typehash{$tn}     = $gottype;
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    $typehash{$tn} = undef;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            ################################################
 | 
						|
            # for the failed nodes, go to related tables
 | 
						|
            ################################################
 | 
						|
            if (%tablehash) {
 | 
						|
                foreach my $ttable (@tabletype) {
 | 
						|
                    my @nodegroup;
 | 
						|
                    foreach my $fnode (keys %tablehash) {
 | 
						|
                        if ($tablehash{$fnode} eq $ttable) {
 | 
						|
                            push @nodegroup, $fnode;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    next unless (@nodegroup);
 | 
						|
                    my $typetable = xCAT::Table->new($ttable);
 | 
						|
                    unless ($typetable) {
 | 
						|
                        my $failnodes = join(",", @nodegroup);
 | 
						|
                        xCAT::MsgUtils->message('S', "getnodetype:Unable to open $ttable table, can't find $failnodes type.\n");
 | 
						|
                        $::RUNCMD_RC = 1;
 | 
						|
                        foreach (@nodegroup) {
 | 
						|
                            $typehash{$_} = undef;
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        my $typep = $typetable->getNodesAttribs(\@nodegroup, ['nodetype']);
 | 
						|
                        foreach my $fn (@nodegroup) {
 | 
						|
                            if ($typep->{$fn}->[0]->{'nodetype'}) {
 | 
						|
                                $typehash{$fn} = $typep->{$fn}->[0]->{'nodetype'};
 | 
						|
                                $NODETYPEHASH{$fn} = $typep->{$fn}->[0]->{'nodetype'};
 | 
						|
                            } else {
 | 
						|
                                $typehash{$fn} = undef;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return \%typehash;
 | 
						|
        } else {    # if not an array
 | 
						|
            if ($NODETYPEHASH{$nodes}) {
 | 
						|
                return $NODETYPEHASH{$nodes};
 | 
						|
            } else {
 | 
						|
                my $typep = $nodetypetab->getNodeAttribs($nodes, ["nodetype"]);
 | 
						|
                if ($typep->{nodetype} and !(grep(/$typep->{nodetype}/, @tabletype))) {
 | 
						|
                    $NODETYPEHASH{$nodes} = $typep->{nodetype};
 | 
						|
                    return $typep->{nodetype};
 | 
						|
                } elsif (grep(/$typep->{nodetype}/, @tabletype)) {
 | 
						|
                    my $typetable = xCAT::Table->new($typep->{nodetype});
 | 
						|
                    unless ($typetable) {
 | 
						|
                        xCAT::MsgUtils->message('S', "getnodetype:Unable to open nodetype table.\n");
 | 
						|
                        $::RUNCMD_RC = 1;
 | 
						|
                        return undef;
 | 
						|
                    }
 | 
						|
                    my $typep = $typetable->getNodeAttribs($nodes, ["nodetype"]);
 | 
						|
                    if ($typep->{nodetype}) {
 | 
						|
                        $NODETYPEHASH{$nodes} = $typep->{nodetype};
 | 
						|
                        return $typep->{nodetype};
 | 
						|
                    } else {
 | 
						|
                        return undef;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   getcecchildren
 | 
						|
    returns cec of the specified frame,
 | 
						|
    Arguments:
 | 
						|
        frame name
 | 
						|
    Returns:
 | 
						|
        Array of cec hostnames
 | 
						|
    Globals:
 | 
						|
        %PARENT_CHILDREN_CEC
 | 
						|
    Error:
 | 
						|
        none
 | 
						|
    Example:
 | 
						|
        @frame_members = getcecchildren($frame);
 | 
						|
    Comments:
 | 
						|
        none
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
my %PARENT_CHILDREN_CEC;
 | 
						|
 | 
						|
sub getcecchildren
 | 
						|
{
 | 
						|
    my $parent = shift;
 | 
						|
    if (($parent) && ($parent =~ /xCAT::/)) {
 | 
						|
        $parent = shift;
 | 
						|
    }
 | 
						|
    my @children = ();
 | 
						|
    if (!%PARENT_CHILDREN_CEC) {
 | 
						|
        my $ppctab = xCAT::Table->new('ppc');
 | 
						|
        unless ($ppctab) {    # cannot open  the table return with error
 | 
						|
            xCAT::MsgUtils->message('S', "getcecchildren:Unable to open ppc table.\n");
 | 
						|
            $::RUNCMD_RC = 1;
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
        if ($ppctab) {
 | 
						|
            my @ps = $ppctab->getAllNodeAttribs([ 'node', 'parent', 'nodetype' ]);
 | 
						|
            foreach my $entry (@ps) {
 | 
						|
                my $p = $entry->{parent};
 | 
						|
                my $c = $entry->{node};
 | 
						|
                my $t = $entry->{nodetype};
 | 
						|
                if ($p and $c) {
 | 
						|
                    if ($t) {    # the nodetype exists in the ppc table, use it
 | 
						|
                        if ($t eq 'cec') {
 | 
						|
 | 
						|
                            # build hash of ppc.parent -> ppc.node
 | 
						|
                            push @{ $PARENT_CHILDREN_CEC{$p} }, $c;
 | 
						|
                        }
 | 
						|
                    } else {    # go look in the nodetype table to find nodetype
 | 
						|
                        my $type = getnodetype($c);
 | 
						|
                        if ($type eq 'cec') {
 | 
						|
                            push @{ $PARENT_CHILDREN_CEC{$p} }, $c;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # find a match for the parent and build the return array
 | 
						|
            foreach (@{ $PARENT_CHILDREN_CEC{$parent} }) {
 | 
						|
                push @children, $_;
 | 
						|
            }
 | 
						|
            return \@children;
 | 
						|
        }
 | 
						|
    } else {    # already built the HASH
 | 
						|
        if (exists($PARENT_CHILDREN_CEC{$parent})) {
 | 
						|
            foreach (@{ $PARENT_CHILDREN_CEC{$parent} }) {
 | 
						|
                push @children, $_;
 | 
						|
            }
 | 
						|
            return \@children;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return undef;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   judge_node
 | 
						|
    judge the node is a real FSP/BPA,
 | 
						|
    use to distinguish if the data is defined in xCAT 2.5 or later
 | 
						|
    Arguments:
 | 
						|
        node name
 | 
						|
    Returns:
 | 
						|
        0  is a fake FSP/BPA,defined in xCAT 2.5
 | 
						|
        1  is a real FSP/BPA,defined in xCAT 2.6 or later
 | 
						|
    Error:
 | 
						|
        none
 | 
						|
    Example:
 | 
						|
        $result = judge_node($nodetocheck);
 | 
						|
    Comments:
 | 
						|
        none
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
sub judge_node
 | 
						|
{
 | 
						|
    my $node = shift;
 | 
						|
    if (($node) && ($node =~ /xCAT::/)) {
 | 
						|
        $node = shift;
 | 
						|
    }
 | 
						|
    my $type = shift;
 | 
						|
    my $flag = 0;
 | 
						|
    my $parenttype;
 | 
						|
    my $nodeparent;
 | 
						|
    my $ppctab = xCAT::Table->new('ppc');
 | 
						|
    if ($ppctab) {
 | 
						|
        $nodeparent = $ppctab->getNodeAttribs($node, ["parent"]);
 | 
						|
        if ($nodeparent and $nodeparent->{parent}) {
 | 
						|
            $parenttype = getnodetype($nodeparent->{parent});
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($type =~ /^fsp$/) {
 | 
						|
        if ($parenttype =~ /^cec$/) {
 | 
						|
            $flag = 1;
 | 
						|
        } else {
 | 
						|
            $flag = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($type =~ /^bpa$/) {
 | 
						|
        if ($parenttype =~ /^frame$/) {
 | 
						|
            $flag = 1;
 | 
						|
        } else {
 | 
						|
            $flag = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return $flag;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   expandnicsattr
 | 
						|
    Expand the nics related attributes into the readable format,
 | 
						|
    for example, the nicsips=eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
 | 
						|
    expanded format:
 | 
						|
    nicsips.eth0=1.1.1.1|2.1.1.1
 | 
						|
    nicsips.eth1=3.1.1.1|4.1.1.1
 | 
						|
 | 
						|
    Arguments:
 | 
						|
        nicsattr value, like niccsips=eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
 | 
						|
        node name, like frame10node10
 | 
						|
        nicnames: only return the value for specific nics, like "eth0,eth1"
 | 
						|
        is_group: bool value indicates whether the type of object is group
 | 
						|
    Returns:
 | 
						|
        expanded format, like:
 | 
						|
        nicsips.eth0=1.1.1.1|2.1.1.1
 | 
						|
        nicsips.eth1=3.1.1.1|4.1.1.1
 | 
						|
    Error:
 | 
						|
        none
 | 
						|
 | 
						|
    Example:
 | 
						|
        my $nicsstr = xCAT::DBobjUtils->expandnicsattr($attrval);
 | 
						|
 | 
						|
    Comments:
 | 
						|
        none
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
sub expandnicsattr()
 | 
						|
{
 | 
						|
    my $nicstr = shift;
 | 
						|
    if (($nicstr) && ($nicstr =~ /xCAT::/)) {
 | 
						|
        $nicstr = shift;
 | 
						|
    }
 | 
						|
    my ($node, $nicnames, $is_group) = @_;
 | 
						|
    my $ret;
 | 
						|
 | 
						|
    $nicstr =~ /^(.*?)=(.*?)$/;
 | 
						|
 | 
						|
    #Attribute: nicips, nichostnamesuffix, etc.
 | 
						|
    my $nicattr = $1;
 | 
						|
 | 
						|
    # Value: eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
 | 
						|
    my $nicval = $2;
 | 
						|
 | 
						|
    #if there is regrex in nicips
 | 
						|
    if (($nicval) && ($nicval =~ /^\|(.*?)\|$/)) {
 | 
						|
 | 
						|
        #$nicval Value: |node(d+)|eth0!192.1.1.($1+10)| or
 | 
						|
        #               |eth0!192.1.1.($1+10),bond0!10.28.41.($1+10)|
 | 
						|
        #In the lsdef, remove the ^| and |$ before displaying
 | 
						|
        $nicval =~ s/(^\||\|$)//g;
 | 
						|
 | 
						|
        #$nicval Value: node(d+)|eth0!192.1.1.($1+10)
 | 
						|
        if (($nicval) && ($nicval =~ /\|/)) {
 | 
						|
            my ($str1, $str2) = split('\|', $nicval);
 | 
						|
            #$nivval Value: eth0!192.1.1.($1+10)
 | 
						|
            $nicval = $str2;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # $nicarr[0]: eth0!1.1.1.1|2.1.1.1
 | 
						|
    # $nicarr[1]: eth1!3.1.1.1|4.1.1.1
 | 
						|
    my @nicarr = split(/,/, $nicval);
 | 
						|
 | 
						|
    foreach my $nicentry (@nicarr) {
 | 
						|
 | 
						|
        #nicentry: eth0!1.1.1.1|2.1.1.1
 | 
						|
        # $nicv[0]: eth0
 | 
						|
        # $nicv[1]: 1.1.1.1|2.1.1.1
 | 
						|
        my @nicv = split(/!/, $nicentry);
 | 
						|
 | 
						|
        # only return nic* attr for these specific nics
 | 
						|
        if ($nicnames) {
 | 
						|
            my @nics = split(/,/, $nicnames);
 | 
						|
            if ($nicv[0]) {
 | 
						|
 | 
						|
                # Do not need to return the nic attr for this nic
 | 
						|
                if (!grep(/^$nicv[0]$/, @nics)) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        # print group attributes in original format
 | 
						|
        if (!$is_group) {
 | 
						|
            $nicv[1]= xCAT::Table::transRegexAttrs($node, $nicv[1]);
 | 
						|
        }
 | 
						|
        # ignore the line that does not have nicname or value
 | 
						|
        if ($nicv[0] && $nicv[1]) {
 | 
						|
            $ret .= "    $nicattr.$nicv[0]=$nicv[1]\n";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    chomp($ret);
 | 
						|
    return $ret;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3   collapsenicsattr
 | 
						|
    Collapse the nics related attributes into the database format,
 | 
						|
    for example,
 | 
						|
    nicsips.eth0=1.1.1.1|2.1.1.1
 | 
						|
    nicsips.eth1=3.1.1.1|4.1.1.1
 | 
						|
 | 
						|
    the collapsed format:
 | 
						|
    nicsips=eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
 | 
						|
 | 
						|
    The collapse will be done against the hash %::FILEATTRS or %::CLIATTRS,
 | 
						|
    remove the nicips.thx attributes from %::FILEATTRS or %::CLIATTRS,
 | 
						|
    add the collapsed info nicips into %::FILEATTRS or %::CLIATTRS.
 | 
						|
 | 
						|
    Arguments:
 | 
						|
        $::FILEATTRS{$objname} or $::CLIATTRS{$objname}
 | 
						|
        $objname
 | 
						|
 | 
						|
    Returns:
 | 
						|
        None, update %::FILEATTRS or %::CLIATTRS directly
 | 
						|
 | 
						|
    Error:
 | 
						|
        none
 | 
						|
 | 
						|
    Example:
 | 
						|
        xCAT::DBobjUtils->collapsenicsattr($nodeattrhash);
 | 
						|
 | 
						|
    Comments:
 | 
						|
        none
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------------------------
 | 
						|
sub collapsenicsattr()
 | 
						|
{
 | 
						|
    my $nodeattrhash = shift;
 | 
						|
    if (($nodeattrhash) && ($nodeattrhash =~ /xCAT::/)) {
 | 
						|
        $nodeattrhash = shift;
 | 
						|
    }
 | 
						|
    my $objname = shift;
 | 
						|
    my %nicattrs = ();
 | 
						|
    foreach my $nodeattr (keys %{$nodeattrhash}) {
 | 
						|
 | 
						|
        # e.g nicips.eth0
 | 
						|
        # do not need to handle nic attributes without the postfix .ethx,
 | 
						|
        # it will be overwritten by the attributes with the postfix .ethx,
 | 
						|
        if ($nodeattr =~ /^(nic\w+)\.(.*)$/) {
 | 
						|
            if ($1 && $2) {
 | 
						|
 | 
						|
                # chdef <noderange> nicips.eth2= to remove the definition for eth2
 | 
						|
                # in this case, the $nodeattrhash->{'nicips.eth0'} is blank
 | 
						|
                # $nicattrs{nicips}{eth0} = "1.1.1.1|1.2.1.1"
 | 
						|
                $nicattrs{$1}{$2} = $nodeattrhash->{$nodeattr};
 | 
						|
 | 
						|
                # remove nicips.eth0 from the %::FILEATTRS
 | 
						|
                delete $nodeattrhash->{$nodeattr};
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # $nicattrs{'nicips'}{'eth0'} = "1.1.1.1|1.2.1.1"
 | 
						|
    # $nicattrs{'nicips'}{'eth1'} = "2.1.1.1|2.2.1.1"
 | 
						|
    foreach my $nicattr (keys %nicattrs) {
 | 
						|
        my @tmparray = ();
 | 
						|
        foreach my $nicname (keys %{ $nicattrs{$nicattr} }) {
 | 
						|
 | 
						|
            # eth0!1.1.1.1|1.2.1.1
 | 
						|
            if ($nicattrs{$nicattr}{$nicname}) {
 | 
						|
                push @tmparray, "$nicname!$nicattrs{$nicattr}{$nicname}";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # eth0!1.1.1.1|1.2.1.1,eth1!2.1.1.1|2.2.1.1
 | 
						|
        $nodeattrhash->{$nicattr} = join(',', @tmparray);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
1;
 |