mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	- zvmdiscovery plugin will not handle findme - not change request if no temp discovered bmc nodes, to avoid the confusing error message - add more logs, and ignore the `ipmitool sol info` error output
		
			
				
	
	
		
			2319 lines
		
	
	
		
			88 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			2319 lines
		
	
	
		
			88 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
#!/usr/bin/env perl
 | 
						|
## IBM(c) 2015 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#
 | 
						|
# This plugin is used to handle the z/VM discovery.
 | 
						|
# z/VM discovery will discover the z/VM virtual machines running
 | 
						|
# on a specified z/VM host and define them to xCAT DB.
 | 
						|
# In addition, it will optionally define the systems to OpenStack.
 | 
						|
#
 | 
						|
 | 
						|
package xCAT_plugin::zvmdiscovery;
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
}
 | 
						|
 | 
						|
use strict;
 | 
						|
use Data::Dumper;
 | 
						|
use Getopt::Long;
 | 
						|
use XML::Simple;
 | 
						|
$XML::Simple::PREFERRED_PARSER='XML::Parser';
 | 
						|
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
use Time::HiRes qw(gettimeofday sleep);
 | 
						|
use xCAT::Table;
 | 
						|
use xCAT::MsgUtils;
 | 
						|
use xCAT::DiscoveryUtils;
 | 
						|
use xCAT::Utils;
 | 
						|
use xCAT::zvmCPUtils;
 | 
						|
use xCAT::zvmUtils;
 | 
						|
 | 
						|
my $request_command;
 | 
						|
( $::SUDOER, $::SUDO ) = xCAT::zvmUtils->getSudoer();
 | 
						|
my $ZHCP_BIN = '/opt/zhcp/bin';
 | 
						|
 | 
						|
# Hash of host name resolution commands to be issued in a virtual OS.
 | 
						|
my @hostnameCmds = ( 'hostname --fqdn',
 | 
						|
                     'hostname --long',
 | 
						|
                     'hostname',
 | 
						|
                   );
 | 
						|
 | 
						|
# Location of the various OpenStack plugins for discovery.
 | 
						|
my $locOpenStackDiscovery = '/var/lib/sspmod/discovery.py';         # location of OpenStack discovery
 | 
						|
my $locOpenStackNodeNameInfo = '/var/lib/sspmod/nodenameinfo.py';   # location of OpenStack node name info
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   addOpenStackSystem
 | 
						|
 | 
						|
    Description : Add a single system to OpenStack.
 | 
						|
    Arguments   : class
 | 
						|
                  callback
 | 
						|
                  z/VM host node
 | 
						|
                  verbose flag: 1 - verbose output, 0 - non-verbose
 | 
						|
                  UUID generated for this node to be used in the discoverydata table
 | 
						|
                  z/VM userid of the discovered system
 | 
						|
                  Reference to the discoverable hash variable
 | 
						|
    Returns     : Node as provisioned in OpenStack or an empty string if it failed.
 | 
						|
    Example     : my $OSnode = addOpenStackSystem( $callback,
 | 
						|
                    $zvmHost, $hcp, $verbose, $activeSystem, $discoverableRef );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub addOpenStackSystem {
 | 
						|
    my ( $callback, $zvmHost, $hcp, $verbose, $activeSystem, $discoverableRef ) = @_;
 | 
						|
    my %discoverable = %$discoverableRef;
 | 
						|
 | 
						|
    my $junk;
 | 
						|
    my $openstackNodeName = '';
 | 
						|
    my $out = '';
 | 
						|
    my $rc = 0;
 | 
						|
 | 
						|
    # Argument mapping between xCAT and the OpenStack python code.
 | 
						|
    # Argument name is as known to xCAT is the key and the value is
 | 
						|
    # the argument name as it is known to the OpenStack python code.
 | 
						|
    my %passingArgs = (
 | 
						|
            'cpuCount'            => '--cpucount',
 | 
						|
            'hostname'            => '--hostname',
 | 
						|
            'ipAddr'              => '--ipaddr',
 | 
						|
            'memory'              => '--memory',
 | 
						|
            'node'                => '--guestname',
 | 
						|
            'os'                  => '--os',
 | 
						|
            'openstackoperands'   => '',
 | 
						|
            );
 | 
						|
    my $args = "";
 | 
						|
 | 
						|
    # Build the argument string for the OpenStack call.
 | 
						|
    foreach my $key ( keys %passingArgs ) {
 | 
						|
        if ( defined( $discoverable{$activeSystem}{$key} ) ) {
 | 
						|
            if ( $key ne '' ) {
 | 
						|
                # Pass the key and the value.
 | 
						|
                $args = "$args $passingArgs{$key} $discoverable{$activeSystem}{$key}";
 | 
						|
            } else {
 | 
						|
                # When name of parm to pass is '', we just pass the value of the parm.
 | 
						|
                # The name would only complicates things for the call because it contains multiple subparms.
 | 
						|
                # We also remove any surrounding quotes or double quotes.
 | 
						|
                $args = "$args $discoverable{$activeSystem}{$key}";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    $args = "$args --verbose $verbose --zvmhost $zvmHost --uuid $discoverable{$activeSystem}{'uuid'}";
 | 
						|
 | 
						|
    # Call the python discovery command
 | 
						|
    if ( $verbose == 1 ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Passing $discoverable{$activeSystem}{'node'} to OpenStack " .
 | 
						|
                              "for userid $activeSystem on z/VM $zvmHost with arguments: $args";
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    }
 | 
						|
    xCAT::MsgUtils->message( "S", "Calling $locOpenStackDiscovery for $discoverable{$activeSystem}{'node'} on $zvmHost" );
 | 
						|
    $out = `python $locOpenStackDiscovery $args`;
 | 
						|
    xCAT::MsgUtils->message( "S", "Returned from $locOpenStackDiscovery" );
 | 
						|
 | 
						|
    if ( $out ) {
 | 
						|
        chomp( $out );
 | 
						|
 | 
						|
        if ( $verbose == 1 ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, $out;
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
        }
 | 
						|
 | 
						|
        my @lines= split( /\n/, $out );
 | 
						|
        my (@createdLine) = grep( /Node\screated:/, @lines );
 | 
						|
        if ( @createdLine ) {
 | 
						|
            # Node created. Do not need to show any output from OpenStack.
 | 
						|
            ($junk, $openstackNodeName) = split( /:\s/, $createdLine[0], 2 );
 | 
						|
        } else {
 | 
						|
            # Node was not created.
 | 
						|
            my @failedLine = grep( /Node\screation\sfailed/, @lines );
 | 
						|
            if ( @failedLine ) {
 | 
						|
                my $rsp;
 | 
						|
                push @{$rsp->{data}}, "Unable to create the node " .
 | 
						|
                                      "in OpenStack.  xCAT node creation is being undone " .
 | 
						|
                                      "for $discoverable{$activeSystem}{'node'}.";
 | 
						|
                if (( @lines > 1 ) && ( $verbose == 0 )) {
 | 
						|
                    # Had more then the "Node creation failed" line AND we have not
 | 
						|
                    # shown them (vebose == 0) so show all of the lines now.
 | 
						|
                    push @{$rsp->{data}}, "Response from the OpenStack plugin:";
 | 
						|
                    push @{$rsp->{data}}, @lines;
 | 
						|
                }
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            } else {
 | 
						|
                my @alreadyCreatedLine = grep( /already\screated/, @lines );
 | 
						|
                if ( @alreadyCreatedLine ) {
 | 
						|
                	# The node is already known to OpenStack as an instance.  We will get
 | 
						|
                	# the node name from the response in case OpenStack wants the xCAT node to
 | 
						|
                	# be a different name.
 | 
						|
                	($openstackNodeName) = $alreadyCreatedLine[0] =~ m/Node (.*) already created/;
 | 
						|
                } else {
 | 
						|
                    my $rsp;
 | 
						|
                    push @{$rsp->{data}}, "Response from the Openstack plugin " .
 | 
						|
                                          "did not contain 'Node created:' or 'Node creation failed' " .
 | 
						|
                                          "or 'already created' string.  It is assumed to have failed.";
 | 
						|
                    if (( @lines > 1 ) && ( $verbose == 0 )) {
 | 
						|
                        # Had more then the "Node creation failed" line AND we have not
 | 
						|
                        # shown them (vebose == 0) so show all of the lines now.
 | 
						|
                        push @{$rsp->{data}}, "Response from the OpenStack plugin:";
 | 
						|
                        push @{$rsp->{data}}, @lines;
 | 
						|
                    }
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "No response was received from the Openstack plugin.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
    }
 | 
						|
 | 
						|
    # If the xCAT node was renamed by OpenStack then update xCAT to use the new node name
 | 
						|
    # so that the node names match.
 | 
						|
    if (( $openstackNodeName ne '' ) and ( $discoverable{$activeSystem}{'node'} ne $openstackNodeName )) {
 | 
						|
        if ( $verbose == 1 ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "Renaming the xCAT node $discoverable{$activeSystem}{'node'} " .
 | 
						|
                                  "to $openstackNodeName as requested by the OpenStack plugin.";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
        }
 | 
						|
        my $renameRC = changeNode( $callback,
 | 
						|
                                   $discoverable{$activeSystem}{'node'},
 | 
						|
                                   'r',
 | 
						|
                                   $openstackNodeName );
 | 
						|
        if ( $renameRC == 0 ) {
 | 
						|
            $discoverable{$activeSystem}{'node'} = $openstackNodeName;
 | 
						|
        } else {
 | 
						|
            $openstackNodeName = '';  # Want to undo the created xCAT node.
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "Unable to rename the xCAT node $discoverable{$activeSystem}{'node'} " .
 | 
						|
                                  "to $openstackNodeName, as requested by the OpenStack plugin, " .
 | 
						|
                                  "rc: $renameRC";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
FINISH_addOpenStackSystem:
 | 
						|
    return $openstackNodeName;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   addPrevDisc
 | 
						|
 | 
						|
    Description : Add previously discovered xCAT nodes
 | 
						|
                  to OpenStack. (Not done. Waiting for input from Emily)
 | 
						|
    Arguments   : class
 | 
						|
                  callback
 | 
						|
                  z/VM host node
 | 
						|
                  ZHCP node
 | 
						|
                  Time when discovery was started.  Used to determine if
 | 
						|
                  a stop was requested and then we were restarted.
 | 
						|
                  nodediscoverstart argument hash
 | 
						|
    Returns     : None.
 | 
						|
    Example     : my $out = addPrevDisc( $callback, $zvmHost,
 | 
						|
                                         $hcp, $initStartTime, \%args );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub addPrevDisc {
 | 
						|
    my ( $callback, $zvmHost, $hcp, $initStartTime, $argsRef ) = @_;
 | 
						|
 | 
						|
    my %discoverable;
 | 
						|
    my @nodes;
 | 
						|
    my $rc = 0;
 | 
						|
    my $verbose = $argsRef->{'verbose'};
 | 
						|
 | 
						|
    # Get the list of discovered nodes from the 'zvm' table.
 | 
						|
    my $zvmTab = xCAT::Table->new("zvm");
 | 
						|
    if ( !$zvmTab ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Could not open table: zvm.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_addPrevDisc;
 | 
						|
    }
 | 
						|
    my @results = $zvmTab->getAttribs( { 'discovered'=>'1', 'hcp'=>$hcp }, ('userid', 'node') );
 | 
						|
    foreach my $id ( @results ) {
 | 
						|
        if ( $id->{'userid'} and $id->{'node'} ) {
 | 
						|
            $discoverable{$id->{'userid'}}{'node'} = $id->{'node'};
 | 
						|
            $discoverable{$id->{'userid'}}{'hcp'} = $hcp;
 | 
						|
        } else {
 | 
						|
            if ( $verbose == 1 ) {
 | 
						|
                my $rsp;
 | 
						|
                push @{$rsp->{data}}, "Node $id->{'node'} is missing 'userid' or 'node' property in the zvm table.";
 | 
						|
                xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            }
 | 
						|
         }
 | 
						|
    }
 | 
						|
    $zvmTab->close;
 | 
						|
 | 
						|
    if ( $verbose == 1 ) {
 | 
						|
        my @discoverableKeys = keys %discoverable;
 | 
						|
        my $discoverableCount = scalar( @discoverableKeys );
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "$discoverableCount nodes have been previously discovered for $zvmHost.";
 | 
						|
        xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the ip and hostname for each discovered node from the hosts table.
 | 
						|
    my $hostsTab = xCAT::Table->new('hosts');
 | 
						|
    if ( !$hostsTab ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Could not open table: hosts.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_addPrevDisc;
 | 
						|
    }
 | 
						|
    my %nodes;
 | 
						|
    my @attribs = ('node', 'ip', 'hostnames');
 | 
						|
    my @hosts = $hostsTab->getAllAttribs( @attribs );
 | 
						|
    foreach my $nodeRef ( @hosts ) {
 | 
						|
        my $node;
 | 
						|
        if ( $nodeRef->{'node'} ) {
 | 
						|
            $node = $nodeRef->{'node'};
 | 
						|
        } else {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ( $nodeRef->{'ip'} ) {
 | 
						|
            $nodes{$node}{'ip'} = $nodeRef->{'ip'};
 | 
						|
        } else {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        if ( $nodeRef->{'hostnames'} ) {
 | 
						|
            $nodes{$node}{'hostnames'} = $nodeRef->{'hostnames'};
 | 
						|
        } else {
 | 
						|
            # Don't have enough info, remove it from the nodes hash.
 | 
						|
            delete( @nodes{$node} );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    $hostsTab->close;
 | 
						|
 | 
						|
    foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
        my $node = $discoverable{$activeSystem}{'node'};
 | 
						|
        if ( $nodes{$node}{'ip'} ) {
 | 
						|
            $discoverable{$activeSystem}{'ipAddr'} = $nodes{$node}{'ip'};
 | 
						|
            $discoverable{$activeSystem}{'hostname'} = $nodes{$node}{'hostnames'};
 | 
						|
        } else {
 | 
						|
            # Don't have enough info, remove it from the discoverable hash.
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the OS info, memory, CPU count and UUID.
 | 
						|
    foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
        # Verify that the virtual machine is currently running.
 | 
						|
        my $out = `ssh -q $::SUDOER\@$hcp $::SUDO $ZHCP_BIN/smcli "Image_Status_Query -T '$activeSystem'"`;
 | 
						|
        $rc = $? >> 8;
 | 
						|
        if ( $rc == 255 ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "z/VM discovery is unable to communicate with the zhcp server: $hcp";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        } elsif ( $rc == 1 ) {
 | 
						|
            if ( $verbose == 1 ) {
 | 
						|
                my $rsp;
 | 
						|
                push @{$rsp->{data}}, "ignoring: $activeSystem - virtual machine is not logged on";
 | 
						|
                xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
            }
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        } elsif ( $rc != 0 ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "An unexpected return code $rc was received from " .
 | 
						|
                                  "the zhcp server $hcp for an smcli Image_Status_Query " .
 | 
						|
                                  "request.  SMAPI servers may be unavailable.  " .
 | 
						|
                                  "Received response: $out";
 | 
						|
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        # Get the OS version from the OS.
 | 
						|
        my $os = xCAT::zvmUtils->getOsVersion( $::SUDOER, $discoverable{$activeSystem}{'node'}, $callback );
 | 
						|
        if ( $os ) {
 | 
						|
            $discoverable{$activeSystem}{'os'} = $os;
 | 
						|
        } else {
 | 
						|
            if ( $verbose == 1 ) {
 | 
						|
                my $rsp;
 | 
						|
                push @{$rsp->{data}}, "ignoring: $activeSystem - Unable to obtain OS version information from node $discoverable{$activeSystem}{'node'}";
 | 
						|
                xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
            }
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        # Install vmcp in the target system just in case no one has done that yet.
 | 
						|
        xCAT::zvmCPUtils->loadVmcp( $::SUDOER, $discoverable{$activeSystem}{'node'} );
 | 
						|
 | 
						|
        # Get the current memory from CP.
 | 
						|
        my $memory = xCAT::zvmCPUtils->getMemory( $::SUDOER, $discoverable{$activeSystem}{'node'} );
 | 
						|
        if ( $memory ) {
 | 
						|
            $discoverable{$activeSystem}{'memory'} = $memory;
 | 
						|
        } else {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "Could not obtain the current virtual machine memory size from node: $discoverable{$activeSystem}{'node'}";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        # Get the current CPU count from CP.
 | 
						|
        my $cpuString = xCAT::zvmCPUtils->getCpu( $::SUDOER, $discoverable{$activeSystem}{'node'} );
 | 
						|
        if ( $cpuString ) {
 | 
						|
            my @cpuLines = split( /\n/, $cpuString );
 | 
						|
            $discoverable{$activeSystem}{'cpuCount'} = scalar( @cpuLines );
 | 
						|
        } else {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "Could not obtain the current virtual machine CPU count from node: $discoverable{$activeSystem}{'node'}";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        $discoverable{$activeSystem}{'uuid'} = xCAT::Utils::genUUID();
 | 
						|
    }
 | 
						|
 | 
						|
    my $rsp;
 | 
						|
    if ( %discoverable ) {
 | 
						|
        if ( $verbose == 1 ) {
 | 
						|
            push @{$rsp->{data}}, "The following xCAT nodes are eligible for OpenStack only discovery:";
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        push @{$rsp->{data}}, "No xCAT nodes are eligible for OpenStack only discovery.";
 | 
						|
    }
 | 
						|
    foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
        $discoverable{$activeSystem}{'openstackoperands'} = $argsRef->{'openstackoperands'};
 | 
						|
        if ( $verbose == 1 ) {
 | 
						|
            push @{$rsp->{data}}, "  $discoverable{$activeSystem}{'node'}";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ( $rsp ) {
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    }
 | 
						|
 | 
						|
    foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
        # Exit if we have been asked to stop discovery for this host.
 | 
						|
        my $startTime = getRunningDiscTimestamp( $callback, $zvmHost );
 | 
						|
        if ( $startTime != $initStartTime ) {
 | 
						|
            # Start time for this run is different from start time in the site table.
 | 
						|
            # User must have stopped and restarted discovery for this host.
 | 
						|
            # End now to let other discovery handle the work.
 | 
						|
            push @{$rsp->{data}}, "Stopping due to a detected stop request.";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
            goto FINISH_addPrevDisc;
 | 
						|
        }
 | 
						|
 | 
						|
        # Define the system to OpenStack
 | 
						|
        my $openstackNodeName = addOpenStackSystem( $callback, $zvmHost, $hcp, $verbose, $activeSystem, \%discoverable );
 | 
						|
        if ( $openstackNodeName ) {
 | 
						|
            updateDiscoverydata( $callback, 'add', $verbose, $zvmHost, $activeSystem, \%discoverable );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
FINISH_addPrevDisc:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   changeNode
 | 
						|
 | 
						|
    Description : Change an xCAT node.  The change can
 | 
						|
                  be a rename or a deletion of the node from
 | 
						|
                  the xCAT tables.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  node name
 | 
						|
                  Type of change:
 | 
						|
                    'r'  - rename the node name and redo makehosts
 | 
						|
                    'd'  - delete the node from xCAT tables and /etc/hosts
 | 
						|
                    'do' - delete the node from xCAT tables only, don't
 | 
						|
                           undo makehosts
 | 
						|
    Returns     : Return code
 | 
						|
                    0 - It worked
 | 
						|
                    1 - It failed
 | 
						|
    Example     : rc = changeNode( $callback, $nodeName, 'r', $newName );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub changeNode {
 | 
						|
    my $callback = shift;
 | 
						|
    my $nodeName = shift;
 | 
						|
    my $changeType = shift;
 | 
						|
    my $newNode = shift;
 | 
						|
 | 
						|
    my $rc = 0;           # Assume everything works
 | 
						|
    my $retStrRef;
 | 
						|
 | 
						|
    # Remove the node from the /etc/hosts file
 | 
						|
    if (( $changeType eq 'r' ) or ( $changeType eq 'd' )) {
 | 
						|
        my $out = `/opt/xcat/sbin/makehosts -d $nodeName 2>&1`;
 | 
						|
        if ( $out ne '' ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "'makehosts -d' failed for $nodeName.  Node is still defined in xCAT MN's /etc/hosts file.  'makehosts' response: $out";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            $rc = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Remove the node.
 | 
						|
    if (( $changeType eq 'd' ) or ( $changeType eq 'do' )) {
 | 
						|
        my $retRef = xCAT::Utils->runxcmd({command => ['rmdef'], stdin=>['NO_NODE_RANGE'], arg => [ "-t", "node", "-o", $nodeName ]}, $request_command, 0, 2);
 | 
						|
        if ( $::RUNCMD_RC != 0 ) {
 | 
						|
            my $rsp;
 | 
						|
            $retStrRef = parse_runxcmd_ret($retRef);
 | 
						|
            push @{$rsp->{data}}, "Unable to remove node $nodeName from the xCAT tables.  rmdef response: $retStrRef->[1]";
 | 
						|
            push @{$rsp->{data}}, "-t". "node". "-o". $nodeName;
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            $rc = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Rename the node.
 | 
						|
    if ( $changeType eq 'r' ) {
 | 
						|
        my $retRef = xCAT::Utils->runxcmd({command=>['chdef'], stdin=>['NO_NODE_RANGE'], arg=>[ '-t', 'node', '-o', $nodeName, '-n', $newNode, '--nocache' ]}, $request_command, 0, 2);
 | 
						|
        if ( $::RUNCMD_RC != 0 ) {
 | 
						|
            my $rsp;
 | 
						|
            $retStrRef = parse_runxcmd_ret($retRef);
 | 
						|
            push @{$rsp->{data}}, '-t'. 'node'. '-o'. $nodeName. '-n'. $newNode;
 | 
						|
            push @{$rsp->{data}}, "Unable to rename node $nodeName " .
 | 
						|
                "to $newNode in the xCAT tables.  " .
 | 
						|
                "The node definition for $nodeName will be removed.  " .
 | 
						|
                "chdef response: $retStrRef->[1]";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            $rc = 1;
 | 
						|
            changeNode( $callback, $nodeName, 'do' );
 | 
						|
        } else {
 | 
						|
            my $out = `/opt/xcat/sbin/makehosts $newNode 2>&1`;
 | 
						|
            if ( $out ne '' ) {
 | 
						|
                my $rsp;
 | 
						|
                push @{$rsp->{data}}, "'makehosts' failed for $newNode.  " .
 | 
						|
                    "The node definition for $newNode will be removed.  " .
 | 
						|
                    "'makehosts' response: $out";
 | 
						|
                xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
                $rc = 1;
 | 
						|
                changeNode( $callback, $newNode, 'do' );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return $rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   createNode
 | 
						|
 | 
						|
    Description : Find an available xCAT nodename and create a node
 | 
						|
                  for the virtual machine and indicate it is a
 | 
						|
                  discovered node.  Also, do a MAKEHOSTS so xCAT MN
 | 
						|
                  can access it by the node name.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  DNS name associated with the OS in the machine
 | 
						|
                  Desired name format template, if specified
 | 
						|
                  Current numeric adjustment value, used to get
 | 
						|
                      to the next available nodename.
 | 
						|
                  xCAT STANZA information in a string that will
 | 
						|
                       be used to create the node.
 | 
						|
                  Reference for the xCAT NODEs hash so that we
 | 
						|
                      can check for already known node names.
 | 
						|
    Returns     : Node name if created or empty string if an error occurred.
 | 
						|
                  Current numeric value
 | 
						|
    Example     : ( $node, $numeric ) = createNode($callback, $discoverable{$activeSystem}{'hostname'},
 | 
						|
                                        $args{'nodenameformat'}, $numeric, $retstr_gen, \%xcatNodes);
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub createNode {
 | 
						|
    my $callback = shift;
 | 
						|
    my $dnsName = shift;
 | 
						|
    my $nameFormat = shift;
 | 
						|
    my $numeric = shift;
 | 
						|
    my $stanzaInfo = shift;
 | 
						|
    my $xcatNodesRef = shift;
 | 
						|
 | 
						|
    my $attempts = 0;     # Number of attempts to find a usable node name
 | 
						|
    my $nodeName;         # Node name found or being checked
 | 
						|
    my $prefix = '';      # Node name prefix, used with templates
 | 
						|
    my $rsp;              # Message work variable
 | 
						|
    my $shortName;        # Short form of the DNS name
 | 
						|
    my $suffix = '';      # Node name suffix, initially none
 | 
						|
    my $templateType = 0; # Type of template; 0: none, 1: old style xCAT, 2: OpenStack (sprintf)
 | 
						|
 | 
						|
    # Determine the component parts of the new node name based on whether
 | 
						|
    # a template is specified.
 | 
						|
    if ( $nameFormat ) {
 | 
						|
        if ( $nameFormat =~ /#NNN/ ) {
 | 
						|
            # Old Style xCAT template e.g. node#NNN -> node001
 | 
						|
            $templateType = 1;
 | 
						|
 | 
						|
            # Deconstruct the name format template into its component parts.
 | 
						|
            my @fmtParts = split ( '#NNN', $nameFormat );
 | 
						|
            $prefix = $fmtParts[0];
 | 
						|
            $suffix = $fmtParts[1];
 | 
						|
        } elsif ( $nameFormat =~ /%/ ) {
 | 
						|
            # OpenStack style template, uses sprintf for formatting
 | 
						|
            $templateType = 2;
 | 
						|
        } else {
 | 
						|
            $nodeName = '';
 | 
						|
            push @{$rsp->{data}}, "Unrecognized node name template.  Nodes will not be discovered.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            goto FINISH_createNode;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $numeric eq '' ) {
 | 
						|
            $numeric = 0;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        # Set up to use the DNS short name as the root of the node name.
 | 
						|
        my @nameParts = split( /\./, $dnsName );
 | 
						|
        $shortName = lc( $nameParts[0] );
 | 
						|
        $numeric = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Loop to find an available node name and reserve it by creating the
 | 
						|
    # node with minimal information.
 | 
						|
    while ( 1 ) {
 | 
						|
        # Create the next nodename
 | 
						|
        if ( $templateType == 1 ) {
 | 
						|
            $numeric = $numeric + 1;
 | 
						|
            my $numSize = length($numeric);
 | 
						|
            if ( $numSize < 3 ) {
 | 
						|
                $numSize = 3;
 | 
						|
            }
 | 
						|
            my $format = "%0".$numSize."d";
 | 
						|
            $numeric = sprintf($format, $numeric);
 | 
						|
            $nodeName = $prefix.$numeric.$suffix;
 | 
						|
        } elsif ( $templateType == 2 ) {
 | 
						|
            $numeric = $numeric + 1;
 | 
						|
            $nodeName = sprintf($nameFormat, $numeric);
 | 
						|
        } else {
 | 
						|
            if ( $numeric ne '' ){
 | 
						|
                $numeric += 1;
 | 
						|
            }
 | 
						|
            $nodeName = $shortName.$numeric;
 | 
						|
        }
 | 
						|
 | 
						|
        # Verify that the nodename is available.
 | 
						|
        if ( !$xcatNodesRef->{$nodeName} ) {
 | 
						|
            # Found an available node name
 | 
						|
            # Attempt to create the node with that name.
 | 
						|
            $attempts += 1;
 | 
						|
            my $retstr_gen = "$nodeName:\n$stanzaInfo";
 | 
						|
            my $retRef = xCAT::Utils->runxcmd({command=>["mkdef"], stdin=>[$retstr_gen], arg=>['-z']}, $request_command, 0, 2);
 | 
						|
 | 
						|
            if ( $::RUNCMD_RC == 0 ) {
 | 
						|
                # Node created.  All done.
 | 
						|
                $xcatNodesRef->{$nodeName} = 1;
 | 
						|
 | 
						|
                # Update the zvm table for the node to indicate that it is a discovered system.
 | 
						|
                my %zvmProps = ( "discovered" => "1" );
 | 
						|
                my $zvmTab = xCAT::Table->new('zvm');
 | 
						|
                if ( !$zvmTab ) {
 | 
						|
                    # Node was created but there is not much we can do about it since
 | 
						|
                    # not being able to update the zvm table indicates a severe error.
 | 
						|
                    push @{$rsp->{data}}, "Could not open table: zvm.  $nodeName was created but discovered=1 could not be set in the zvm table.";
 | 
						|
                    xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
                } else {
 | 
						|
                    $zvmTab->setAttribs( {node => $nodeName}, \%zvmProps );
 | 
						|
                    $zvmTab->commit();
 | 
						|
                }
 | 
						|
                last;
 | 
						|
            } else {
 | 
						|
                if ( $attempts > 10 ) {
 | 
						|
                    # Quit trying to create a node after 10 attempts
 | 
						|
                    my $retStrRef = parse_runxcmd_ret($retRef);
 | 
						|
                    my $rsp;
 | 
						|
                    push @{$rsp->{data}}, "Unable to create a node, $nodeName.  Last attempt response: $retStrRef->[1]";
 | 
						|
                    xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
                    $nodeName = '';
 | 
						|
                    last;
 | 
						|
                } else {
 | 
						|
                    # Assume xCAT daemon is unavailable.  Give it 15 seconds to come back
 | 
						|
                    # before next attempt.
 | 
						|
                    sleep(15);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Did not find an available node name on this pass.
 | 
						|
        # Wipe out the nodename in case we exit the loop.  Also, ensure a numeric
 | 
						|
        # is used next time around.
 | 
						|
        $nodeName = '';
 | 
						|
        if ( $numeric eq '' ){
 | 
						|
            $numeric = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ( $nodeName ne '' ) {
 | 
						|
        # Issue MAKEHOSTS so that xCAT MN can drive commands to the host using the node name.
 | 
						|
        # Note: If OpenStack changes the node name then we will have to redo this later.
 | 
						|
        my $out = `/opt/xcat/sbin/makehosts $nodeName 2>&1`;
 | 
						|
        if ( $out ne '' ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "'makehosts' failed for $nodeName.  Node creation is being undone.  'makehosts' response: $out";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
            changeNode( $callback, $nodeName, 'do' );
 | 
						|
            $nodeName = '';
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
FINISH_createNode:
 | 
						|
    return ( $nodeName, $numeric );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   findme
 | 
						|
 | 
						|
    Description : Handle the request form node to map and
 | 
						|
                  define the request to a node.
 | 
						|
    Arguments   : request handle
 | 
						|
                  callback
 | 
						|
                  sub request
 | 
						|
    Returns     : 0 - No error
 | 
						|
                  non-zero - Error detected.
 | 
						|
    Example     : findme( $request, $callback, $request_command );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub findme {
 | 
						|
    my $request = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    my $subreq = shift;
 | 
						|
 | 
						|
    my $SEQdiscover = getSiteVal("__SEQDiscover");
 | 
						|
    my $PCMdiscover = getSiteVal("__PCMDiscover");
 | 
						|
    my $ZVMdiscover = getSiteVal("__ZVMDiscover");
 | 
						|
    unless ( $ZVMdiscover ) {
 | 
						|
        if ( $SEQdiscover or $PCMdiscover ) {
 | 
						|
            # profile or sequential discovery is running, then just return
 | 
						|
            # to make the other discovery handle it
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # update the discoverydata table to have an undefined node
 | 
						|
        $request->{discoverymethod}->[0] = 'undef';
 | 
						|
        xCAT::DiscoveryUtils->update_discovery_data($request);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getOpenStackTemplate
 | 
						|
 | 
						|
    Description : Get the current template used by OpenStack
 | 
						|
                  for this host and the largest numeric
 | 
						|
                  value currently in use.
 | 
						|
    Arguments   : callback
 | 
						|
                  z/VM host node
 | 
						|
    Returns     : Template to be used for node naming
 | 
						|
                  Highest numeric value in use
 | 
						|
    Example     : my $out = getOpenStackTemplate( $callback, $zvmHost );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getOpenStackTemplate {
 | 
						|
    my ( $callback, $zvmHost ) = @_;
 | 
						|
 | 
						|
    my $out = '';
 | 
						|
    my %response = (
 | 
						|
        'template' => '',
 | 
						|
        'number' => '' );
 | 
						|
 | 
						|
    xCAT::MsgUtils->message( "S", "Calling $locOpenStackNodeNameInfo for $zvmHost" );
 | 
						|
    $out = `python $locOpenStackNodeNameInfo`;
 | 
						|
    xCAT::MsgUtils->message( "S", "Returned from $locOpenStackNodeNameInfo with $out" );
 | 
						|
 | 
						|
    if (( $out ne '' ) && ( $out !~ /^Error detected/ )) {
 | 
						|
        my @parts = split( /\s/, $out );
 | 
						|
        my $key;
 | 
						|
        foreach my $part ( @parts ) {
 | 
						|
            if ( $part eq 'Template:' ) {
 | 
						|
                $key = 'template';
 | 
						|
            } elsif ( $part eq 'Number:' ) {
 | 
						|
                $key = 'number';
 | 
						|
            } else {
 | 
						|
                $part =~ s/^\s+|\s+$//g;    # Trim leading & ending blanks
 | 
						|
                $response{$key} = $part;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        my $rsp;
 | 
						|
        my @lines = split( /\n/, $out );
 | 
						|
        shift( @lines );
 | 
						|
        if ( @lines ) {
 | 
						|
            push @{$rsp->{data}}, @lines;
 | 
						|
        } else {
 | 
						|
            push @{$rsp->{data}}, "An error was detected in the nova instance name template."
 | 
						|
        }
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        $response{'template'} = '';
 | 
						|
    }
 | 
						|
 | 
						|
FINISH_getOpenStackTemplate:
 | 
						|
    return ( $response{'template'}, $response{'number'} );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getRunningDiscTimestamp
 | 
						|
 | 
						|
    Description : Get the timestamp on a specific running
 | 
						|
                  discovery from the site table variable.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  z/VM host node
 | 
						|
    Returns     : Timestamp for the run that was specified or
 | 
						|
                    empty string if a run was not found.
 | 
						|
    Example     : $ts = getRunningDiscTimestamp( 'zvm1' );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getRunningDiscTimestamp {
 | 
						|
    my $callback = shift;
 | 
						|
    my $zvmHost = shift;
 | 
						|
 | 
						|
    my $rsp;            # Response buffer for output messages
 | 
						|
    my $ts = '';        # Timestamp value
 | 
						|
 | 
						|
    my $val = getSiteVal("__ZVMDiscover");
 | 
						|
    if ( $val ) {
 | 
						|
        if ( $val =~ /zvmhost=$zvmHost,/ ) {
 | 
						|
            my @discoveries = split( /zvmhost=/, $val );
 | 
						|
            foreach my $discovery ( @discoveries ) {
 | 
						|
                if ( $discovery =~ "^$zvmHost" ) {
 | 
						|
                    my @parts = split( ',', $discovery );
 | 
						|
                    if ( $parts[1] ) {
 | 
						|
                        $ts = $parts[1];
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return $ts;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getSiteVal
 | 
						|
 | 
						|
    Description : Bypasses a problem with get_site_attribute
 | 
						|
                  returning an old cashe value instead of
 | 
						|
                  the current value.
 | 
						|
    Arguments   : Name of attribute
 | 
						|
    Returns     : Value from the site table
 | 
						|
    Example     : ( $val ) = getSiteVal( '__ZVMDiscover' );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getSiteVal {
 | 
						|
    my $attribute = shift;
 | 
						|
 | 
						|
    my $response = '';        # Response buffer for return
 | 
						|
 | 
						|
    my $siteTab = xCAT::Table->new( "site", -autocommit=>1 );
 | 
						|
    my @results = $siteTab->getAttribs( { 'key'=>$attribute }, ('value') );
 | 
						|
    foreach my $id ( @results ) {
 | 
						|
        $response .= $id->{'value'};
 | 
						|
    }
 | 
						|
    $siteTab->close;
 | 
						|
 | 
						|
    return $response;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   handled_commands
 | 
						|
 | 
						|
    Description : Returns the supported commands and their handler.
 | 
						|
    Arguments   : None.
 | 
						|
    Returns     : Command handler hash for this module.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub handled_commands {
 | 
						|
    return {
 | 
						|
        #findme             => 'zvmdiscovery',   # Not handle findme in this plugin, #4860
 | 
						|
        #nodediscoverdef   => 'zvmdiscovery',    # Handled by sequential discovery
 | 
						|
        nodediscoverls     => 'zvmdiscovery',
 | 
						|
        nodediscoverstart  => 'zvmdiscovery',
 | 
						|
        nodediscoverstatus => 'zvmdiscovery',
 | 
						|
        nodediscoverstop   => 'zvmdiscovery',
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   nodediscoverls
 | 
						|
 | 
						|
    Description : List discovered z/VM systems.
 | 
						|
    Arguments   : callback
 | 
						|
                  arguments for nodediscoverls
 | 
						|
    Returns     : None.
 | 
						|
    Example     : nodediscoverls( $callback, $args );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub nodediscoverls {
 | 
						|
    my $callback = shift;
 | 
						|
    my $args = shift;
 | 
						|
 | 
						|
    my %origArgs;                # Original arguments from the command invocation
 | 
						|
    my $maxNodeSize = 4;         # Maximum size of a nodename in the current list
 | 
						|
    my $maxHostSize = 6;         # Maximum size of a host nodename in the current list
 | 
						|
    my $maxUseridSize = 6;       # Maximum size of a userid in the current list
 | 
						|
 | 
						|
    # Determine which options were specified and their values.
 | 
						|
    if ( $args ) {
 | 
						|
        @ARGV = @$args;
 | 
						|
    }
 | 
						|
 | 
						|
    GetOptions(
 | 
						|
        't=s'         => \$origArgs{'type'},
 | 
						|
        'u=s'         => \$origArgs{'uuid'},
 | 
						|
        'l'           => \$origArgs{'long'},
 | 
						|
        'h|help'      => \$origArgs{'help'},
 | 
						|
        'v|version'   => \$origArgs{'ver'},
 | 
						|
        'z|zvmhost=s' => \$origArgs{'zvmHost'} );
 | 
						|
 | 
						|
    # If '-u' was specified then let seqdiscovery handle it as common output.
 | 
						|
    if ( $origArgs{'uuid'} ) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # If z/VM discovery is running and the type was not already specified then
 | 
						|
    # we treat this as a z/VM type of listing.
 | 
						|
    my @ZVMDiscover = xCAT::TableUtils->get_site_attribute( "__ZVMDiscover" );
 | 
						|
    if ( $ZVMDiscover[0] ) {
 | 
						|
        $origArgs{'type'} = 'zvm';
 | 
						|
    }
 | 
						|
 | 
						|
    # Weed out invocations that this routine does not handle but instead
 | 
						|
    # leaves to sequential discovery to handle.
 | 
						|
    if ( $origArgs{'help'} ||
 | 
						|
         $origArgs{'ver'}  ||
 | 
						|
         ( $origArgs{'type'} && $origArgs{'type'} ne 'zvm' ))
 | 
						|
    {
 | 
						|
        # Sequential discovery will have handled these options.
 | 
						|
        return;
 | 
						|
    } elsif ( $origArgs{'zvmHost'} || ( $origArgs{'type'} && $origArgs{'type'} eq 'zvm' )) {
 | 
						|
        # z/VM related operands are handled here.
 | 
						|
    } else {
 | 
						|
        # Sequential discovery will have handled other combinations of options.
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # If a zvmHost was specified then process it into an array
 | 
						|
    my %zvmHosts;
 | 
						|
    my @inputZvmHosts;
 | 
						|
    if ( $origArgs{'zvmHost'} ) {
 | 
						|
        if ( index( $origArgs{'zvmHost'}, ',' ) != -1 ) {
 | 
						|
            # Must have specified multiple host node names
 | 
						|
            my @hosts = split( /,/, $origArgs{'zvmHost'} );
 | 
						|
            foreach my $host ( @hosts ) {
 | 
						|
                if ( !$host ) {
 | 
						|
                    # Tolerate zvmhost value beginning with a comma.
 | 
						|
                    # It is wrong but not worth an error message.
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                push( @inputZvmHosts, $host );
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            push( @inputZvmHosts, $origArgs{'zvmHost'} );
 | 
						|
        }
 | 
						|
        %zvmHosts = map { $_ => 1 } @inputZvmHosts;
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the list xCAT nodes and their userids.
 | 
						|
    my $zvmTab = xCAT::Table->new("zvm");
 | 
						|
    if ( !$zvmTab ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Could not open table: zvm.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_nodediscoverls;
 | 
						|
    }
 | 
						|
    my %xcatNodes;
 | 
						|
    my @attribs = ('node', 'userid');
 | 
						|
    my @nodes = $zvmTab->getAllAttribs( @attribs );
 | 
						|
    foreach my $nodeRef ( @nodes ) {
 | 
						|
        if ( !$nodeRef->{'node'} || !$nodeRef->{'userid'} ) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        $xcatNodes{$nodeRef->{'node'}} = $nodeRef->{'userid'};
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the list of discovered systems for the specified z/VMs.
 | 
						|
    my %discoveredNodes;
 | 
						|
    my $disTab = xCAT::Table->new('discoverydata');
 | 
						|
    if ( !$disTab ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Could not open table: discoverydata.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_nodediscoverls;
 | 
						|
    }
 | 
						|
 | 
						|
    my @disData = $disTab->getAllAttribsWhere( "method='zvm'", 'node', 'uuid', 'otherdata',
 | 
						|
                                               'method', 'discoverytime', 'arch', 'cpucount',
 | 
						|
                                               'memory');
 | 
						|
    foreach my $disRef ( @disData ) {
 | 
						|
        if ( !$disRef->{'uuid'} || !$disRef->{'node'} || !$disRef->{'otherdata'} ) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        my $host = $disRef->{'otherdata'};
 | 
						|
        $host =~ s/^zvmhost.//g;
 | 
						|
 | 
						|
        if ( !%zvmHosts | $zvmHosts{$host} ) {
 | 
						|
            my $node = $disRef->{'node'};
 | 
						|
            $discoveredNodes{$node}{'uuid'} = $disRef->{'uuid'};
 | 
						|
            $discoveredNodes{$node}{'host'} = $host;
 | 
						|
            if ( $xcatNodes{$node} ) {
 | 
						|
                $discoveredNodes{$node}{'userid'} = $xcatNodes{$node};
 | 
						|
            }
 | 
						|
            $discoveredNodes{$node}{'method'} = $disRef->{'method'};
 | 
						|
            $discoveredNodes{$node}{'discoverytime'} = $disRef->{'discoverytime'};
 | 
						|
            $discoveredNodes{$node}{'arch'} = $disRef->{'arch'};
 | 
						|
            $discoveredNodes{$node}{'cpucount'} = $disRef->{'cpucount'};
 | 
						|
            $discoveredNodes{$node}{'memory'} = $disRef->{'memory'};
 | 
						|
 | 
						|
            # Update size of node and host node names if size has increased.
 | 
						|
            # This is used later when producing the output.
 | 
						|
            my $length = length( $host );
 | 
						|
            if ( $length > $maxHostSize ) {
 | 
						|
                $maxHostSize = $length;
 | 
						|
            }
 | 
						|
            $length = length( $node );
 | 
						|
            if ( $length > $maxNodeSize ) {
 | 
						|
                $maxNodeSize = $length;
 | 
						|
            }
 | 
						|
            $length = length( $discoveredNodes{$node}{'userid'} );
 | 
						|
            if ( $length > $maxUseridSize ) {
 | 
						|
                $maxUseridSize = $length;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Produce the output
 | 
						|
    my $rsp;
 | 
						|
    my $discoverednum = keys %discoveredNodes;
 | 
						|
    push @{$rsp->{data}}, "Discovered $discoverednum nodes.";
 | 
						|
    if ( %discoveredNodes ) {
 | 
						|
        # Create the format string for the column output
 | 
						|
        if ( $maxHostSize > 20 ) {
 | 
						|
            $maxHostSize = 20;     # Set a maximum, individual lines may throw it off but we need to be reasonable.
 | 
						|
        }
 | 
						|
        $maxHostSize += 2;
 | 
						|
        if ( $maxNodeSize > 20 ) {
 | 
						|
            $maxNodeSize = 20;     # Set a maximum, individual lines may throw it off but we need to be reasonable.
 | 
						|
        }
 | 
						|
        $maxNodeSize += 2;
 | 
						|
        if ( $maxUseridSize > 20 ) {
 | 
						|
            $maxUseridSize = 20;     # Set a maximum, individual lines may throw it off but we need to be reasonable.
 | 
						|
        }
 | 
						|
        $maxUseridSize += 2;
 | 
						|
 | 
						|
        my $fmtString;
 | 
						|
        if ( !$origArgs{'long'} ) {
 | 
						|
            $fmtString = ' %-' . $maxNodeSize . 's%-' . $maxUseridSize . 's%-' . $maxHostSize . 's';
 | 
						|
            push @{$rsp->{data}}, sprintf( $fmtString, 'NODE', 'USERID', 'ZVM HOST' );
 | 
						|
        }
 | 
						|
 | 
						|
        # Create the output
 | 
						|
        foreach my $node (keys %discoveredNodes) {
 | 
						|
            if ( $origArgs{'long'} ) {
 | 
						|
                push @{$rsp->{data}}, "Object uuid: $discoveredNodes{$node}{'uuid'}";
 | 
						|
                push @{$rsp->{data}}, "    node=$node";
 | 
						|
                push @{$rsp->{data}}, "    userid=$discoveredNodes{$node}{'userid'}";
 | 
						|
                push @{$rsp->{data}}, "    host=$discoveredNodes{$node}{'host'}";
 | 
						|
                push @{$rsp->{data}}, "    method=$discoveredNodes{$node}{'method'}";
 | 
						|
                push @{$rsp->{data}}, "    discoverytime=$discoveredNodes{$node}{'discoverytime'}";
 | 
						|
                push @{$rsp->{data}}, "    arch=$discoveredNodes{$node}{'arch'}";
 | 
						|
                push @{$rsp->{data}}, "    cpucount=$discoveredNodes{$node}{'cpucount'}";
 | 
						|
                push @{$rsp->{data}}, "    memory=$discoveredNodes{$node}{'memory'}";
 | 
						|
            } else {
 | 
						|
                push @{$rsp->{data}}, sprintf( $fmtString,
 | 
						|
                                               $node,
 | 
						|
                                               $discoveredNodes{$node}{'userid'},
 | 
						|
                                               $discoveredNodes{$node}{'host'} );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
 | 
						|
FINISH_nodediscoverls:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   nodediscoverstart
 | 
						|
 | 
						|
    Description : Initiate the z/VM discovery process.
 | 
						|
    Arguments   : callback
 | 
						|
                  arguments for nodediscoverstart
 | 
						|
    Returns     : None.
 | 
						|
    Example     : nodediscoverstart( $callback, $args );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub nodediscoverstart {
 | 
						|
    my $callback = shift;
 | 
						|
    my $args = shift;
 | 
						|
 | 
						|
    my $lock = 0;            # Lock word, 0: not obtained, 1: lock failed, other: lock handle
 | 
						|
    my @newZvmHosts;         # Array of z/VM host nodes on this command invocation
 | 
						|
    my %origArgs;            # Original arguments from the command invocation
 | 
						|
    my %parms;               # Parameters to pass along to start routine
 | 
						|
    my $rsp;                 # Response buffer for output messages
 | 
						|
    my %runningZvmHosts;     # List of z/VM host nodes from the __ZVMDiscover property in the site table
 | 
						|
    my $zvmHost;             # Short scope work parameter used to contain a z/VM host node name
 | 
						|
 | 
						|
    # Valid attributes for nodediscoverstart
 | 
						|
    my %validArgs = (
 | 
						|
        'defineto'          => 1,
 | 
						|
        'groups'            => 1,
 | 
						|
        'ipfilter'          => 1,
 | 
						|
        'nodenameformat'    => 1,
 | 
						|
        'useridfilter'      => 1,
 | 
						|
        'zvmhost'           => 1,
 | 
						|
        'openstackoperands' => 1,
 | 
						|
    );
 | 
						|
 | 
						|
    if ( $args ) {
 | 
						|
        @ARGV = @$args;
 | 
						|
    }
 | 
						|
 | 
						|
    $origArgs{'verbose'} = 0;     # Assume we are not doing verbose
 | 
						|
    my ($help, $ver);
 | 
						|
    if (!GetOptions(
 | 
						|
        'h|help' => \$help,
 | 
						|
        'V|verbose' => \$origArgs{'verbose'},
 | 
						|
        'v|version' => \$ver)) {
 | 
						|
        # Sequential discovery will have produced an error message.
 | 
						|
        # We don't need another
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( $help | $ver ) {
 | 
						|
        # Sequential discovery will have handled these options.
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    foreach ( @ARGV ) {
 | 
						|
        my ($name, $value) = split ('=', $_);
 | 
						|
        $origArgs{$name} = $value;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( !defined( $origArgs{'zvmhost'} ) ) {
 | 
						|
        # If zvmhost parm is not present then this is not a z/VM discovery.
 | 
						|
        goto FINISH_NODEDISCOVERSTART;
 | 
						|
    }
 | 
						|
 | 
						|
    push @{$rsp->{data}}, "Processing: nodediscoverstart @$args";
 | 
						|
    xCAT::MsgUtils->message("I", $rsp, $callback, 1);
 | 
						|
 | 
						|
    # Check the running of sequential or profile-based discovery
 | 
						|
    my $SEQdiscover = getSiteVal("__SEQDiscover");
 | 
						|
    my $PCMdiscover = getSiteVal("__PCMDiscover");
 | 
						|
    if ( $PCMdiscover or $SEQdiscover ) {
 | 
						|
        push @{$rsp->{data}}, "z/VM Discovery cannot be run together with Sequential or Profile-based discovery";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        goto FINISH_NODEDISCOVERSTART;
 | 
						|
    }
 | 
						|
 | 
						|
    # Verify that specified filters are valid.
 | 
						|
    if ( defined( $origArgs{'ipfilter'} )) {
 | 
						|
        eval {''=~/$origArgs{'ipfilter'}/};
 | 
						|
        if ( $@ ) {
 | 
						|
            push @{$rsp->{data}}, "The ipfilter is not a valid regular expression: $@";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ( defined( $origArgs{'useridfilter'} )) {
 | 
						|
        eval {''=~/$origArgs{'useridfilter'}/};
 | 
						|
        if ( $@ ) {
 | 
						|
            push @{$rsp->{data}}, "The useridfilter is not a valid regular expression: $@";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Set the default defineto option if none was specified and verify the value.
 | 
						|
    if ( ! defined( $origArgs{'defineto'} ) ) {
 | 
						|
        $origArgs{'defineto'} = 'both';
 | 
						|
    } else {
 | 
						|
        if (( $origArgs{'defineto'} ne 'both' ) and ( $origArgs{'defineto'} ne 'xcatonly' ) and
 | 
						|
            ( $origArgs{'defineto'} ne 'openstackonly' )) {
 | 
						|
            push @{$rsp->{data}}, "Specified 'defineto' value is not 'both', 'xcatonly' or " .
 | 
						|
                                  "'openstackonly': $origArgs{'defineto'}";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Verify that the OpenStack plugin is available.
 | 
						|
    if ( $origArgs{'defineto'} ne 'xcatonly' ) {
 | 
						|
        if ( !-e $locOpenStackDiscovery ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "$locOpenStackDiscovery does not exist.  " .
 | 
						|
                                  "Discovery cannot occur.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
        if ( $origArgs{'defineto'} ne 'both' ) {
 | 
						|
            if ( !-e $locOpenStackNodeNameInfo ) {
 | 
						|
                my $rsp;
 | 
						|
                push @{$rsp->{data}}, "$locOpenStackNodeNameInfo does not exist.  " .
 | 
						|
                                      "Discovery cannot occur.";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
                goto FINISH_NODEDISCOVERSTART;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Use sudo or not
 | 
						|
    # This looks in the passwd table for a key = sudoer
 | 
						|
    ($::SUDOER, $::SUDO) = xCAT::zvmUtils->getSudoer();
 | 
						|
 | 
						|
    # Obtain any ongoing z/VM discovery parms and get the list of z/VM hosts.
 | 
						|
    $lock = xCAT::Utils->acquire_lock( "nodemgmt", 0 );
 | 
						|
    if ( $lock == 1 ) {
 | 
						|
        push @{$rsp->{data}}, "Unable to acquire the 'nodemgmt' lock to protect __ZVMDiscover property in the xCAT site table from changes.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
        goto FINISH_NODEDISCOVERSTART;
 | 
						|
    }
 | 
						|
 | 
						|
    my $ZVMdiscover = getSiteVal( "__ZVMDiscover" );
 | 
						|
    if ( $ZVMdiscover ) {
 | 
						|
        if ( $ZVMdiscover =~ '^zvmhost=' ) {
 | 
						|
            my @discoveries = split(/zvmhost=/, $ZVMdiscover);
 | 
						|
            foreach my $activeParms ( @discoveries ) {
 | 
						|
                if ( !$activeParms ) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                if ( index( $activeParms, ',' ) != -1 ) {
 | 
						|
                    $zvmHost = substr( $activeParms, 0, index( $activeParms, ',' ));
 | 
						|
                } else {
 | 
						|
                    $zvmHost = $activeParms;
 | 
						|
                }
 | 
						|
                $runningZvmHosts{$zvmHost} = 1;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            # Not an expected format, Drop it when we push out the new saved parameters.
 | 
						|
            push @{$rsp->{data}}, "Wrong format";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            $ZVMdiscover = '';
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my %param;               # The valid parameters in a hash
 | 
						|
    my $textParam;           # The valid parameters in 'name=value,name=value...' format
 | 
						|
    my @newZvmhosts;         # Array of z/VM hosts to be added
 | 
						|
    my %zhcpServers;         # Hash of ZHCP servers for each new host to be discovered.
 | 
						|
 | 
						|
    # Validate the parameters
 | 
						|
    foreach my $name ( keys %origArgs ) {
 | 
						|
        if ( $name eq 'verbose' ) {
 | 
						|
            # Verbose is a hyphenated option and is not listed in the
 | 
						|
            # validArgs hash.  So we won't do a validation check on it.
 | 
						|
        } elsif ( !defined( $validArgs{$name} ) ) {
 | 
						|
            push @{$rsp->{data}}, "Argument \"$name\" is not valid.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
        if ( !defined( $origArgs{$name} ) ) {
 | 
						|
            push @{$rsp->{data}}, "The parameter \"$name\" needs a value.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
 | 
						|
        if (( $name eq 'nodenameformat' ) and ( index( $origArgs{$name}, '#NNN' ) == -1)) {
 | 
						|
            push @{$rsp->{data}}, "The parameter \"$name\" is missing the '#NNN' string.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
            goto FINISH_NODEDISCOVERSTART;
 | 
						|
        }
 | 
						|
 | 
						|
        # Invoke the OpenStack plugin to validate OpenStack related variables.
 | 
						|
        if (( $name eq 'openstackoperands' ) and
 | 
						|
            (( $origArgs{'defineto'} eq 'both' ) || ( $origArgs{'defineto'} eq 'openstackonly' )) &&
 | 
						|
             defined( $origArgs{$name} )) {
 | 
						|
            $origArgs{$name} =~ s/^\'+|\'+$//g;
 | 
						|
            $origArgs{$name} =~ s/^\"+|\"+$//g;
 | 
						|
            xCAT::MsgUtils->message( "S", "Calling $locOpenStackDiscovery to validate parms: $origArgs{$name}" );
 | 
						|
            my $out = `python $locOpenStackDiscovery --validate $origArgs{$name}`;
 | 
						|
            chomp( $out );
 | 
						|
            xCAT::MsgUtils->message( "S", "Returned from $locOpenStackDiscovery with $out" );
 | 
						|
            if ( $out ne '0' ) {
 | 
						|
                if ( $out eq '' ) {
 | 
						|
                    $out = "No response was received from $locOpenStackDiscovery for OpenStack operand validation.  z/VM discovery will not be started.";
 | 
						|
                }
 | 
						|
                push @{$rsp->{data}}, "$out";
 | 
						|
                xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
                goto FINISH_NODEDISCOVERSTART;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Keep the valid parameters
 | 
						|
        if ( $name eq 'zvmhost' ) {
 | 
						|
            if ( index( $origArgs{$name}, ',' ) != -1 ) {
 | 
						|
                # Must have specified multiple host node names
 | 
						|
                my @hosts = split( /,/, $origArgs{$name} );
 | 
						|
                foreach $zvmHost ( @hosts ) {
 | 
						|
                    if ( !$zvmHost ) {
 | 
						|
                        # Tolerate zvmhost value beginning with a comma.
 | 
						|
                        # It is wrong but not worth an error message.
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    push( @newZvmhosts, $zvmHost );
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                push( @newZvmhosts, $origArgs{$name} );
 | 
						|
            }
 | 
						|
            foreach $zvmHost ( @newZvmhosts ) {
 | 
						|
                if ( exists( $runningZvmHosts{$zvmHost} )) {
 | 
						|
                    push @{$rsp->{data}}, "The node \"$zvmHost\" specified with the zvmhost parameter is already running z/VM discovery.";
 | 
						|
                    xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
                    goto FINISH_NODEDISCOVERSTART;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            # Non-zvmhost parms get added to textParam string
 | 
						|
            $param{$name} = $origArgs{$name};
 | 
						|
            $param{$name} =~ s/^\s+|\s+$//g;
 | 
						|
            $textParam .= $name . '=' . $param{$name} . ' ';
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    $textParam =~ s/,\z//;
 | 
						|
    if ( $textParam ) {
 | 
						|
        $textParam =  $textParam;
 | 
						|
    }
 | 
						|
 | 
						|
    my ($sec,  $min,  $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
 | 
						|
    my $currTime = sprintf("%02d-%02d-%04d %02d:%02d:%02d",
 | 
						|
                           $mon + 1, $mday, $year + 1900, $hour, $min, $sec);
 | 
						|
 | 
						|
    # Save the discovery parameters to the site.  __ZVMDiscover which will be used by nodediscoverls/status/stop and findme.
 | 
						|
    foreach $zvmHost ( @newZvmhosts ) {
 | 
						|
        # Verify that the zvmHost node exists
 | 
						|
        my @reqProps = ( 'node' );
 | 
						|
        my $propVals = xCAT::zvmUtils->getNodeProps( 'nodetype', $zvmHost, @reqProps );
 | 
						|
        if ( !$propVals->{'node'} ) {
 | 
						|
            push @{$rsp->{data}}, "The z/VM host node is not a defined node.  " .
 | 
						|
                                  "The node $zvmHost is missing from the nodetype table.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # Verify that the node is a z/VM host and locate the ZHCP server for this host.
 | 
						|
        my @propNames = ( 'hcp', 'nodetype' );
 | 
						|
        $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $zvmHost, @propNames );
 | 
						|
 | 
						|
        if ( $propVals->{'nodetype'} ne 'zvm') {
 | 
						|
            push @{$rsp->{data}}, "The specified z/VM host $zvmHost does not appear to be a z/VM host.  " .
 | 
						|
                                  "The 'nodetype' property in the zvm table should be set to 'zvm'.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        my $hcp = $propVals->{'hcp'};
 | 
						|
        if ( $hcp ) {
 | 
						|
            # Remember the ZHCP info so we can pass it along
 | 
						|
            $zhcpServers{$zvmHost} = $hcp;
 | 
						|
        } else {
 | 
						|
            push @{$rsp->{data}}, "The 'hcp' property is not defined in the zvm table for $zvmHost node.";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # Add the parms for the new z/VM host to the list of running servers and their parms
 | 
						|
        if ( $ZVMdiscover eq '' ) {
 | 
						|
            $ZVMdiscover = "zvmhost=$zvmHost,$currTime,$textParam";
 | 
						|
        } else {
 | 
						|
            $ZVMdiscover .= ",zvmhost=$zvmHost,$currTime,$textParam";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $siteTab = xCAT::Table->new( "site", -autocommit=>1 );
 | 
						|
    $siteTab->setAttribs( {"key" => "__ZVMDiscover"}, {"value" => "$ZVMdiscover"} );
 | 
						|
    $siteTab->commit();
 | 
						|
    $siteTab->close();
 | 
						|
 | 
						|
    xCAT::Utils->release_lock( $lock, 1 );
 | 
						|
    $lock = 0;
 | 
						|
 | 
						|
    # Start each new discovery.
 | 
						|
    foreach $zvmHost ( @newZvmhosts ) {
 | 
						|
        startDiscovery( $callback, $zvmHost, $zhcpServers{$zvmHost}, $currTime, \%param );
 | 
						|
    }
 | 
						|
 | 
						|
    # Common exit point to ensure that any lock has been freed.
 | 
						|
FINISH_NODEDISCOVERSTART:
 | 
						|
    # Release the lock if we obtained it.
 | 
						|
    if (( $lock != 1 ) and ( $lock != 0 )) {
 | 
						|
        xCAT::Utils->release_lock( $lock, 1 );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   nodediscoverstatus
 | 
						|
 | 
						|
    Description : Display the z/VM discovery status.
 | 
						|
    Arguments   : callback
 | 
						|
                  arguments for nodediscoverstatus
 | 
						|
    Returns     : None.
 | 
						|
    Example     : nodediscoverstatus( $callback, $args );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub nodediscoverstatus {
 | 
						|
    my $callback = shift;
 | 
						|
    my $args = shift;
 | 
						|
 | 
						|
    my @inputZvmHosts;       # Input list of z/VM host nodes
 | 
						|
    my $rsp;                 # Response buffer for output messages
 | 
						|
    my @runningZvmHosts;     # z/VM host nodes being queried
 | 
						|
    my $zvmHost;             # Small scope variable to temporarily hold a host node value
 | 
						|
 | 
						|
    # Valid attributes for z/VM discovery
 | 
						|
    my ( $help, $ver );
 | 
						|
    if ( !GetOptions(
 | 
						|
        'h|help' => \$help,
 | 
						|
        'v|version' => \$ver,
 | 
						|
        'z|zvmhost=s' => \$zvmHost )) {
 | 
						|
        # Return if unrecognized parms found so other discoveries can respond.
 | 
						|
        goto FINISH_NODEDISCOVERSTATUS;
 | 
						|
    }
 | 
						|
 | 
						|
    # Return if the user asked for help or version because sequential discovery will handle that.
 | 
						|
    if ( $help or $ver ) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Return if sequential or profile discovery is running or all are stopped.
 | 
						|
    # Sequential discovery will handle the response in that case.
 | 
						|
    my $SEQdiscover = getSiteVal("__SEQDiscover");
 | 
						|
    my $PCMdiscover = getSiteVal("__PCMDiscover");
 | 
						|
    my $ZVMdiscover = getSiteVal("__ZVMDiscover");
 | 
						|
    if (( $PCMdiscover or $SEQdiscover ) or ( !$SEQdiscover and !$PCMdiscover and !$ZVMdiscover )) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Put any specified zvmhosts into a hash that we can query.
 | 
						|
    if ( $zvmHost ) {
 | 
						|
        if ( index( $zvmHost, ',' ) != -1 ) {
 | 
						|
            # Must have specified multiple host node names
 | 
						|
            my @hosts = split( /,/, $zvmHost );
 | 
						|
            foreach $zvmHost ( @hosts ) {
 | 
						|
                if ( !$zvmHost ) {
 | 
						|
                    # Tolerate zvmhost value beginning with a comma.
 | 
						|
                    # It is wrong but not worth an error message.
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                push( @inputZvmHosts, $zvmHost );
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            push( @inputZvmHosts, $zvmHost );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my %inputZvmHostsHash = map { $_ => 1 } @inputZvmHosts;
 | 
						|
 | 
						|
    # Get the list of z/VM hosts.
 | 
						|
    my $newZVMdiscover;
 | 
						|
    if ( $ZVMdiscover ) {
 | 
						|
        if ( $ZVMdiscover =~ '^zvmhost=' ) {
 | 
						|
            my @discoveries = split( /zvmhost=/, $ZVMdiscover );
 | 
						|
            foreach my $activeParms ( @discoveries ) {
 | 
						|
                if ( !$activeParms ) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                if ( index( $activeParms, ',' ) != -1 ) {
 | 
						|
                    $zvmHost = substr( $activeParms, 0, index( $activeParms, ',' ));
 | 
						|
                } else {
 | 
						|
                    $zvmHost = $activeParms;
 | 
						|
                }
 | 
						|
                push( @runningZvmHosts, $zvmHost );
 | 
						|
                if ( exists( $inputZvmHostsHash{$zvmHost} )) {
 | 
						|
                    $inputZvmHostsHash{$zvmHost} = 2;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            # Not an expected format, Drop it when we push out the new saved parameters.
 | 
						|
            push @{$rsp->{data}}, "__ZVMDiscover property in the xCAT site table is corrupted.  It has been cleared so that all z/VM discovery stops.  You may restart z/VM discovery.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
 | 
						|
            # Remove the site.__ZVMDiscover property
 | 
						|
            # We don't need a lock because we are whipping out the value and not trying to keep it around.
 | 
						|
            my $siteTab = xCAT::Table->new( "site", -autocommit=>1 );
 | 
						|
            $siteTab->delEntries({key => '__ZVMDiscover'});
 | 
						|
            $siteTab->commit();
 | 
						|
            $siteTab->close();
 | 
						|
            undef $siteTab;
 | 
						|
            goto FINISH_NODEDISCOVERSTATUS;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ( !@inputZvmHosts ) {
 | 
						|
        # Not a specific status request so let's remind them that sequential
 | 
						|
        # and Profile discovery are stopped.
 | 
						|
        push @{$rsp->{data}}, "Sequential discovery is stopped.";
 | 
						|
        push @{$rsp->{data}}, "Profile discovery is stopped.";
 | 
						|
        xCAT::MsgUtils->message( "I", $rsp, $callback, 1 );
 | 
						|
    }
 | 
						|
 | 
						|
    # Inform the user about any node that is specified as input but is not running discovery.
 | 
						|
    if ( %inputZvmHostsHash ) {
 | 
						|
        # --zvmhost was specified so indicate a response for each host.
 | 
						|
        foreach $zvmHost ( keys %inputZvmHostsHash ) {
 | 
						|
            if ( $inputZvmHostsHash{$zvmHost} == 1 ) {
 | 
						|
                push @{$rsp->{data}}, "z/VM Discovery is stopped for: $zvmHost.";
 | 
						|
                xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
            } else {
 | 
						|
                push @{$rsp->{data}}, "z/VM Discovery is started for: $zvmHost.";
 | 
						|
                xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        # --zvmhost was not specified so give a single line response.
 | 
						|
        if ( @runningZvmHosts ) {
 | 
						|
            my $runningList;
 | 
						|
            foreach $zvmHost ( @runningZvmHosts ) {
 | 
						|
                if ( $runningList ) {
 | 
						|
                    $runningList .= ', ' . $zvmHost;
 | 
						|
                } else {
 | 
						|
                    $runningList = $zvmHost;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, "z/VM Discovery is started for: $runningList";
 | 
						|
            xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
        } else {
 | 
						|
            # No on-going z/VM discovery.
 | 
						|
            push @{$rsp->{data}}, "z/VM Discovery is stopped.";
 | 
						|
            xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Common exit point to ensure that any lock has been freed.
 | 
						|
    # Currently, we do not use locks in this routine.
 | 
						|
FINISH_NODEDISCOVERSTATUS:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   nodediscoverstop
 | 
						|
 | 
						|
    Description : Stop the z/VM discovery process.
 | 
						|
    Arguments   : callback
 | 
						|
                  arguments for nodediscoverstop
 | 
						|
                  $auto option (not used by z/VM)
 | 
						|
    Returns     : None.
 | 
						|
    Example     : nodediscoverstop( $callback, $args, $auto );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub nodediscoverstop {
 | 
						|
    my $callback = shift;
 | 
						|
    my $args = shift;
 | 
						|
    my $auto = shift;
 | 
						|
 | 
						|
    my @inputZvmHosts;       # Input list of z/VM host nodes to stop
 | 
						|
    my $rsp;                 # Response buffer for output messages
 | 
						|
    my @stoppingZvmHosts;    # z/VM host nodes that can be stopped because they are running
 | 
						|
    my $zvmHost;             # Small scope variable to temporarily hold a host node value
 | 
						|
 | 
						|
    # Check for a running of z/VM discovery
 | 
						|
    my $ZVMdiscover = getSiteVal("__ZVMDiscover");
 | 
						|
    if ( !$ZVMdiscover ) {
 | 
						|
        # Return so one of the other discoveries can handle the response.
 | 
						|
        goto FINISH_NODEDISCOVERSTOP;
 | 
						|
    }
 | 
						|
 | 
						|
    # Handle parameters
 | 
						|
    if ( $args ) {
 | 
						|
        @ARGV = @$args;
 | 
						|
    }
 | 
						|
 | 
						|
    my ( $help, $ver );
 | 
						|
    if ( !GetOptions(
 | 
						|
        'h|help' => \$help,
 | 
						|
        'v|version' => \$ver,
 | 
						|
        'z|zvmhost=s' => \$zvmHost )) {}
 | 
						|
 | 
						|
    # Return if the user asked for help or version because sequential will handle that.
 | 
						|
    if ( $help or $ver ) {
 | 
						|
        goto FINISH_NODEDISCOVERSTOP;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( $zvmHost ) {
 | 
						|
        if ( index( $zvmHost, ',' ) != -1 ) {
 | 
						|
            # Must have specified multiple host node names
 | 
						|
            my @hosts = split( /,/, $zvmHost );
 | 
						|
            foreach $zvmHost ( @hosts ) {
 | 
						|
                if ( !$zvmHost ) {
 | 
						|
                    # Tolerate zvmhost value beginning with a comma.
 | 
						|
                    # It is wrong but not worth an error message.
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                push( @inputZvmHosts, $zvmHost );
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            push( @inputZvmHosts, $zvmHost );
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        # If zvmhost parm is not present then this is not a z/VM discovery.
 | 
						|
        push @{$rsp->{data}}, "nodediscoverstop did not specify a --zvmhost property.";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        goto FINISH_NODEDISCOVERSTOP;
 | 
						|
    }
 | 
						|
    my %inputZvmHostsHash = map { $_ => 1 } @inputZvmHosts;
 | 
						|
 | 
						|
    # Obtain any on-going z/VM discovery parms and get the list of z/VM hosts.
 | 
						|
    my $ZVMdiscover = getSiteVal("__ZVMDiscover");
 | 
						|
    my $newZVMdiscover;
 | 
						|
    if ( $ZVMdiscover ) {
 | 
						|
        if ( $ZVMdiscover =~ '^zvmhost=' ) {
 | 
						|
            my @discoveries = split( /zvmhost=/, $ZVMdiscover );
 | 
						|
            foreach my $activeParms ( @discoveries ) {
 | 
						|
                if ( !$activeParms ) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                if ( index( $activeParms, ',' ) != -1 ) {
 | 
						|
                    $zvmHost = substr( $activeParms, 0, index( $activeParms, ',' ));
 | 
						|
                } else {
 | 
						|
                    $zvmHost = $activeParms;
 | 
						|
                }
 | 
						|
 | 
						|
                if ( exists( $inputZvmHostsHash{$zvmHost} )) {
 | 
						|
                    $inputZvmHostsHash{$zvmHost} = 2;
 | 
						|
                    push( @stoppingZvmHosts, $zvmHost );
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            # Not an expected format, Drop it when we push out the new saved parameters.
 | 
						|
            push @{$rsp->{data}}, "__ZVMDiscover property in the xCAT site table is corrupted.  It has been cleared so that all z/VM discovery stops.  You may restart z/VM discovery.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
 | 
						|
            # Remove the site.__ZVMDiscover property
 | 
						|
            my $siteTab = xCAT::Table->new( "site", -autocommit=>1 );
 | 
						|
            $siteTab->delEntries({key => '__ZVMDiscover'});
 | 
						|
            $siteTab->commit();
 | 
						|
            $siteTab->close();
 | 
						|
            undef $siteTab;
 | 
						|
            goto FINISH_NODEDISCOVERSTOP;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Inform the user about any node that is specified as input but is not running discovery.
 | 
						|
    foreach $zvmHost ( keys %inputZvmHostsHash ) {
 | 
						|
        if ( $inputZvmHostsHash{$zvmHost} == 1 ) {
 | 
						|
            push @{$rsp->{data}}, "z/VM discovery is not running for node: $zvmHost.";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Stop the host discovery immediately, if possible.
 | 
						|
    foreach $zvmHost ( @stoppingZvmHosts ) {
 | 
						|
        stopDiscovery( $callback, $zvmHost, \@ARGV );
 | 
						|
    }
 | 
						|
 | 
						|
    # Common exit point.
 | 
						|
FINISH_NODEDISCOVERSTOP:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-----------------------------------------------------
 | 
						|
=head3  parse_runxcmd_ret
 | 
						|
 | 
						|
    Description : Get return of runxcmd and convert it into strings.
 | 
						|
    Arguments   : The return reference of runxcmd
 | 
						|
    Returns     : [$outstr, $errstr], A reference of list, placing
 | 
						|
                  standard output and standard error message.
 | 
						|
    Example     : my $retStrRef = parse_runxcmd_ret($retRef);
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------
 | 
						|
sub parse_runxcmd_ret {
 | 
						|
    my $retRef = shift;
 | 
						|
 | 
						|
    my $msglistref;
 | 
						|
    my $outstr = "";
 | 
						|
    my $errstr = "";
 | 
						|
    if ($retRef){
 | 
						|
        if($retRef->{data}){
 | 
						|
            $msglistref = $retRef->{data};
 | 
						|
            $outstr = Dumper(@$msglistref);
 | 
						|
            xCAT::MsgUtils->message( 'S', "Command standard output: $outstr" );
 | 
						|
        }
 | 
						|
        if($retRef->{error}){
 | 
						|
            $msglistref = $retRef->{error};
 | 
						|
            $errstr =  Dumper(@$msglistref);
 | 
						|
            xCAT::MsgUtils->message( 'S', "Command error output: $errstr" );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return [$outstr, $errstr];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   process_request
 | 
						|
 | 
						|
    Description : Process a request and drive the function handler.
 | 
						|
    Arguments   : Request handle
 | 
						|
                  Callback handle
 | 
						|
                  Command that is requested
 | 
						|
    Returns     : None
 | 
						|
    Example     : process_request( $request, $callback, $request_command );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub process_request {
 | 
						|
    my $request = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    $request_command = shift;
 | 
						|
 | 
						|
    my $command = $request->{command}->[0];
 | 
						|
    my $args = $request->{arg};
 | 
						|
 | 
						|
    if ($command eq "findme"){
 | 
						|
        if (defined($request->{discoverymethod}) and defined($request->{discoverymethod}->[0]) and ($request->{discoverymethod}->[0] ne 'undef')) {
 | 
						|
 | 
						|
            # The findme request had been processed by other module, just return
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        findme( $request, $callback, $request_command );
 | 
						|
    } elsif ($command eq "nodediscoverls") {
 | 
						|
        nodediscoverls( $callback, $args );
 | 
						|
    } elsif ($command eq "nodediscoverstart") {
 | 
						|
        nodediscoverstart( $callback, $args );
 | 
						|
    } elsif ($command eq "nodediscoverstop") {
 | 
						|
        nodediscoverstop( $callback, $args );
 | 
						|
    } elsif ($command eq "nodediscoverstatus") {
 | 
						|
        nodediscoverstatus( $callback, $args );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   removeHostInfo
 | 
						|
 | 
						|
    Description : Remove z/VM host info from the __ZVMDiscover
 | 
						|
                  property in the site table.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  z/VM host node name
 | 
						|
    Returns     : None.
 | 
						|
    Example     : $rc = removeHostInfo( $callback, $zvmHost );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub removeHostInfo {
 | 
						|
    my $callback = shift;
 | 
						|
    my $zvmHost = shift;
 | 
						|
 | 
						|
    my $lock = 0;            # Lock word, 0: not obtained, 1: lock failed, other: lock handle
 | 
						|
    my $rsp;                 # Response buffer for output messages
 | 
						|
 | 
						|
    # Obtain any on-going z/VM discovery parms and get the list of z/VM hosts.
 | 
						|
    $lock = xCAT::Utils->acquire_lock( "nodemgmt", 0 );
 | 
						|
    if ( $lock == 1 ) {
 | 
						|
        push @{$rsp->{data}}, "Unable to acquire the 'nodemgmt' lock to protect __ZVMDiscover property in the xCAT site table.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
        goto FINISH_removeHostInfo;
 | 
						|
    }
 | 
						|
 | 
						|
    my $origZVMdiscover = getSiteVal("__ZVMDiscover");
 | 
						|
    my $newZVMdiscover;
 | 
						|
    if ( $origZVMdiscover ) {
 | 
						|
        if ( $origZVMdiscover =~ '^zvmhost=' ) {
 | 
						|
            my $currHost;
 | 
						|
            my @discoveries = split( /zvmhost=/, $origZVMdiscover );
 | 
						|
            foreach my $activeParms ( @discoveries ) {
 | 
						|
                if ( !$activeParms ) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
                if ( index( $activeParms, ',' ) != -1 ) {
 | 
						|
                    $currHost = substr( $activeParms, 0, index( $activeParms, ',' ));
 | 
						|
                } else {
 | 
						|
                    $currHost = $activeParms;
 | 
						|
                }
 | 
						|
 | 
						|
                if ( $zvmHost ne $currHost ) {
 | 
						|
                    # Not stopping this host so keep it in the new __ZVMdiscover property.
 | 
						|
                    $activeParms =~ s/\,+$//;
 | 
						|
                    my $hostDiscParms = "zvmhost=$activeParms";
 | 
						|
                    if ( $newZVMdiscover ) {
 | 
						|
                        $newZVMdiscover = "$newZVMdiscover,$hostDiscParms";
 | 
						|
                    } else {
 | 
						|
                        $newZVMdiscover = $hostDiscParms;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            # Not an expected format, Drop it when we push out the new saved parameters.
 | 
						|
            push @{$rsp->{data}}, "__ZVMDiscover property in the xCAT site table is corrupted.  It has been cleared so that all z/VM discovery stops.  You may restart z/VM discovery.";
 | 
						|
            xCAT::MsgUtils->message( "E", $rsp, $callback, 1 );
 | 
						|
 | 
						|
            # Remove the site table's '__ZVMDiscover property.
 | 
						|
            my $siteTab = xCAT::Table->new( "site", -autocommit=>1 );
 | 
						|
            $siteTab->delEntries({key => '__ZVMDiscover'});
 | 
						|
            $siteTab->commit();
 | 
						|
            $siteTab->close();
 | 
						|
            undef $siteTab;
 | 
						|
            goto FINISH_removeHostInfo;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Update the site table to have the remaining discovery host information.
 | 
						|
    my $siteTab = xCAT::Table->new( "site", -autocommit=>1 );
 | 
						|
    if ( !$newZVMdiscover ) {
 | 
						|
        $siteTab->delEntries({key => '__ZVMDiscover'});
 | 
						|
    } else {
 | 
						|
        $siteTab->setAttribs({"key" => "__ZVMDiscover"}, {"value" => "$newZVMdiscover"});
 | 
						|
    }
 | 
						|
    $siteTab->commit();
 | 
						|
    $siteTab->close();
 | 
						|
    undef $siteTab;
 | 
						|
 | 
						|
    # Common exit point so we can make certain to release any lock that is held.
 | 
						|
FINISH_removeHostInfo:
 | 
						|
    # Release the lock if we obtained it.
 | 
						|
    if (( $lock != 1 ) and ( $lock != 0 )) {
 | 
						|
        xCAT::Utils->release_lock( $lock, 1 );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   startDiscovery
 | 
						|
 | 
						|
    Description : Start z/VM discovery for a particular z/VM host.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  z/VM host node name
 | 
						|
                  ZHCP
 | 
						|
                  Start time of the discovery
 | 
						|
                  Hash of arguments specified on the nodediscoverstart
 | 
						|
                    command and their values
 | 
						|
    Returns     : None
 | 
						|
    Example     : startDiscovery( $callback, $zvmHost, $hcp, $startTime, \%args );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub startDiscovery{
 | 
						|
    my $callback = shift;
 | 
						|
    my $zvmHost = shift;
 | 
						|
    my $hcp = shift;
 | 
						|
    my $initStartTime = shift;
 | 
						|
    my $argsRef = shift;
 | 
						|
    my %args = %$argsRef;
 | 
						|
 | 
						|
    my $numeric = "";             # Numeric portion of last generated node name
 | 
						|
    my $out;                      # Output work buffer
 | 
						|
    my $rc;                       # Return code
 | 
						|
    my $rsp;                      # Response buffer for output messages
 | 
						|
    my $startOpenStack = 0;       # Tell OpenStack provisioner to begin, 0: no, 1: yes
 | 
						|
 | 
						|
    push @{$rsp->{data}}, "z/VM discovery started for $zvmHost";
 | 
						|
    xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
 | 
						|
    # Clean the entries in the discoverydata table for discovery method 'zvm'
 | 
						|
    # and the specific zvmHost that we are going to begin to discover.
 | 
						|
    my $disTab = xCAT::Table->new("discoverydata");
 | 
						|
    if ( !$disTab ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Could not open table: discoverydata.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_startDiscovery;
 | 
						|
    }
 | 
						|
 | 
						|
    my %keyhash;
 | 
						|
    $keyhash{'method'} = 'zvm';
 | 
						|
    $keyhash{'otherdata'} = "zvmhost." . $zvmHost;
 | 
						|
    $disTab->delEntries( \%keyhash );
 | 
						|
    $disTab->commit();
 | 
						|
 | 
						|
    # Handle 'openstackonly' discovery or get the template for 'both' discovery.
 | 
						|
    if ( $args{'defineto'} eq 'openstackonly' ) {
 | 
						|
        # Verify that OpenStack has a valid template to use when it is called
 | 
						|
        # to handle the node.
 | 
						|
        my ( $osTemplate, $osNumeric ) = getOpenStackTemplate( $callback, $zvmHost );
 | 
						|
        if ( $osTemplate eq '' ) {
 | 
						|
            # An error was detected in the template and message produced leave now.
 | 
						|
            goto FINISH_startDiscovery;
 | 
						|
        }
 | 
						|
        # Discover the xCAT nodes available to OpenStack
 | 
						|
        $out = addPrevDisc( $callback, $zvmHost, $hcp, $initStartTime, \%args );
 | 
						|
        goto FINISH_startDiscovery;
 | 
						|
    } elsif ( $args{'defineto'} eq 'both') {
 | 
						|
        # Obtain the template and highest numeric value from OpenStack
 | 
						|
        my ( $osTemplate, $osNumeric ) = getOpenStackTemplate( $callback, $zvmHost );
 | 
						|
        if ( $osTemplate ne '' ) {
 | 
						|
            $args{'nodenameformat'} = $osTemplate;
 | 
						|
            $numeric = $osNumeric;
 | 
						|
        } else {
 | 
						|
            # An error was detected in the template and message produced leave now.
 | 
						|
            goto FINISH_startDiscovery;
 | 
						|
        }
 | 
						|
 | 
						|
        $startOpenStack = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the current list of node names.
 | 
						|
    my @nodeNames;
 | 
						|
    my $nodelistTab = xCAT::Table->new('nodelist');
 | 
						|
    if ( !$nodelistTab ) {
 | 
						|
        push @{$rsp->{data}}, "Could not open table: nodelist.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_startDiscovery;
 | 
						|
    }
 | 
						|
 | 
						|
    my @attribs = ('node');
 | 
						|
    my @nodes = $nodelistTab->getAllAttribs( @attribs );
 | 
						|
    foreach my $node ( @nodes ) {
 | 
						|
        push @nodeNames,$node->{'node'};
 | 
						|
    }
 | 
						|
    @nodes = sort @nodeNames;
 | 
						|
    my %xcatNodes = map { $_ => 1 } @nodes;
 | 
						|
 | 
						|
    # Obtain the list of logged on users.
 | 
						|
    $out = `ssh -q $::SUDOER\@$hcp $::SUDO $ZHCP_BIN/smcli "Image_Status_Query '-T *'"`;
 | 
						|
    $rc = $? >> 8;
 | 
						|
    if ( $rc == 255 ) {
 | 
						|
        push @{$rsp->{data}}, "z/VM discovery is unable to communicate with the zhcp system: $hcp";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_startDiscovery;
 | 
						|
    } elsif ( $rc != 0 ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "An unexpected return code $rc was received from " .
 | 
						|
                              "the zhcp server $hcp for an smcli Image_Status_Query " .
 | 
						|
                              "request.  SMAPI servers may be unavailable.  " .
 | 
						|
                              "Received response: $out";
 | 
						|
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
        goto FINISH_startDiscovery;
 | 
						|
    }
 | 
						|
 | 
						|
    # Build the hash of running systems.
 | 
						|
    my @runningSystems = split( "\n", lc( $out ) );
 | 
						|
 | 
						|
    # Create a hash of discoverable systems by starting with the
 | 
						|
    # list of running systems and removing any systems in the
 | 
						|
    # list of non-discoverable (known to be z/VM servers or
 | 
						|
    # non-Linux systems).
 | 
						|
    my @nonDiscoverable = (
 | 
						|
        'auditor',  'autolog1', 'autolog2', 'avsvm',
 | 
						|
        'bldcms',   'bldnuc',   'bldracf',  'bldseg',
 | 
						|
        'cbdiodsp', 'cmsbatch',
 | 
						|
        'datamove', 'datamov2', 'datamov3', 'datamov4', 'diskacnt',
 | 
						|
        'dirmaint', 'dirmsat',  'dirmsat2', 'dirmsat3', 'dirmsat4',
 | 
						|
        'dtcens1',  'dtcens2',  'dtcsmapi', 'dtcvsw1',  'dtcvsw2',
 | 
						|
        'erep',
 | 
						|
        'ftpserve', 'gcs',      'gskadmin',
 | 
						|
        'ibmuser',  'imap',     'imapauth',
 | 
						|
        'ldapsrv',  'lohcost',
 | 
						|
        'maint',    'maint630', 'maint640',
 | 
						|
        'migmaint', 'monwrite', 'mproute',
 | 
						|
        'operator', 'operatns', 'opersymp', 'opncloud',
 | 
						|
        'osadmin1', 'osadmin2', 'osadmin3',
 | 
						|
        'osamaint', 'osasf',    'ovfdev62',
 | 
						|
        'perfsvm',  'persmapi', 'pmaint',   'portmap',
 | 
						|
        'racfsmf',  'racfvm',   'racmaint', 'rexecd',
 | 
						|
        'rscs',     'rscsauth', 'rscsdns',  'rxagent1',
 | 
						|
        'smtp',     'snmpd',    'snmpsuba', 'ssl',      'ssldcssm',
 | 
						|
        'sysadmin', 'sysmon',
 | 
						|
        'tcpip',    'tcpmaint', 'tsafvm',
 | 
						|
        'uftd',
 | 
						|
        'vmnfs',    'vmrmadmn', 'vmrmsvm',
 | 
						|
        'vmservp',  'vmservr',  'vmservu',  'vmservs',  'vsmevsrv',
 | 
						|
        'vsmguard', 'vsmproxy', 'vsmreqim', 'vsmreqin', 'vsmreqiu',
 | 
						|
        'vsmreqi6', 'vsmwork1', 'vsmwork2', 'vsmwork3', 'vsmwork4',
 | 
						|
        'vsmwork5', 'vsmwork6', 'vsmwork7', 'vsmwork8', 'vsmwork9',
 | 
						|
        'xcat',     'xcatserv', 'xchange',
 | 
						|
        'zhcp',     'zvmlxapp', 'zvmmaplx',
 | 
						|
        '4osasf40', '5684042j', '6vmdir30', '6vmhcd20', '6vmlen20',
 | 
						|
        '6vmptk30', '6vmrac30', '6vmrsc30', '6vmtcp30',
 | 
						|
    );
 | 
						|
    my %discoverable;
 | 
						|
    @discoverable {@runningSystems} = ( );
 | 
						|
    delete @discoverable{@nonDiscoverable};
 | 
						|
 | 
						|
    # Apply any user specified userid filter to the list to weed it further.
 | 
						|
    if ( $args{'useridfilter'} ) {
 | 
						|
        if ( $args{'verbose'} ) {
 | 
						|
            push @{$rsp->{data}}, "Applying useridfilter: '" . $args{'useridfilter'} . "'";
 | 
						|
            xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
        }
 | 
						|
        foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
            if ( $activeSystem !~ m/$args{'useridfilter'}/i ) {
 | 
						|
                delete( $discoverable{$activeSystem} );
 | 
						|
                if ( $args{'verbose'} ) {
 | 
						|
                    push @{$rsp->{data}}, "ignoring: $activeSystem - filtered by user";
 | 
						|
                    xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                if ( $args{'verbose'} ) {
 | 
						|
                    push @{$rsp->{data}}, "keeping: $activeSystem";
 | 
						|
                    xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Determine the long and short zhcp DNS name.
 | 
						|
    my ( $longName, $shortName );
 | 
						|
    if ( $hcp =~ /\./ ) {
 | 
						|
        $longName = lc( $hcp );
 | 
						|
        my @parts = split( /\./, $longName );
 | 
						|
        if ( $parts[0] ne '' ) {
 | 
						|
            $shortName = $parts[0];
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        $shortName = lc( $hcp );
 | 
						|
    }
 | 
						|
    if (( !defined $longName ) && ( -e '/etc/hosts' )) {
 | 
						|
        # Search /etc/hosts for the short name in a non-commented out portion of the lines and
 | 
						|
        # look for the long name (contains periods).  The short and long form can be in any order
 | 
						|
        # after the IP address.
 | 
						|
        $out = `cat /etc/hosts | sed 's/#\.*\$//g' | sed 's/\$/ /g' | grep -i " $shortName "`;
 | 
						|
        my @lines = split( /\n/, $out );
 | 
						|
        my @parts = split( / /, $lines[0] );
 | 
						|
        my $numParts = @parts;
 | 
						|
        for( my $i = 1; $i < $numParts; $i++ ) {
 | 
						|
            if ( $parts[$i] =~ /\./ ) {
 | 
						|
                $longName = lc( $parts[$i] );
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Get the list of systems that are known to xCAT already for this host.
 | 
						|
    my %knownToXCAT;
 | 
						|
    my @knownUserids;
 | 
						|
    my $zvmTab = xCAT::Table->new("zvm");
 | 
						|
    my @attribs = ('hcp', 'userid');
 | 
						|
    @nodes = $zvmTab->getAllAttribs( @attribs );
 | 
						|
    foreach my $nodeRef ( @nodes ) {
 | 
						|
        my $nodeHCP;
 | 
						|
        if ( $nodeRef->{'hcp'} && $nodeRef->{'userid'} ) {
 | 
						|
            $nodeHCP = lc( $nodeRef->{'hcp'} );
 | 
						|
            if ((( defined $longName) && ( $longName eq $nodeHCP )) ||
 | 
						|
                (( defined $shortName) && ( $shortName eq $nodeHCP ))) {
 | 
						|
                push @knownUserids, lc( $nodeRef->{'userid'} );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my %knownToXCAT = map { $_ => 1 } @knownUserids;
 | 
						|
 | 
						|
    # Weed out any systems that are already defined as xCAT nodes.
 | 
						|
    foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
        if ( $knownToXCAT{$activeSystem} ) {
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            if ( $args{'verbose'} ) {
 | 
						|
                push @{$rsp->{data}}, "ignoring: $activeSystem - already defined to xCAT";
 | 
						|
                xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $numSystems = scalar( keys %discoverable );
 | 
						|
    xCAT::MsgUtils->message( "S", "Discovery for $zvmHost found $numSystems virtual machines." );
 | 
						|
 | 
						|
    # Perform a set of potentially long running functions.  We do this one
 | 
						|
    # server at a time so that we can stop if we are told to do so.
 | 
						|
    # Loop through the list performing the following:
 | 
						|
    #   - See if discovery has been stopped early.
 | 
						|
    #   - Attempt to access the system to identify which server can be discovered.
 | 
						|
    #   - Contact the system to obtain system information.
 | 
						|
    #   - Create a xCAT node and update xCAT tables.
 | 
						|
    #   - Drive the OpenStack definition of the node, if requested.
 | 
						|
    my ($ipAddr,$ipVersion, $hostname);
 | 
						|
    foreach my $activeSystem ( keys %discoverable ) {
 | 
						|
 | 
						|
        # Exit if we have been asked to stop discovery for this host.
 | 
						|
        my $startTime = getRunningDiscTimestamp( $callback, $zvmHost );
 | 
						|
        if ( $startTime != $initStartTime ) {
 | 
						|
            # Start time for this run is different from start time in the site table.
 | 
						|
            # User must have stopped and restarted discovery for this host.
 | 
						|
            # End now to let other discovery handle the work.
 | 
						|
            push @{$rsp->{data}}, "Stopping due to a detected stop request.";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
            goto FINISH_startDiscovery;
 | 
						|
        }
 | 
						|
 | 
						|
        # Further refine the list by finding only systems which have a NICs with known IP addresses
 | 
						|
        # that will allow us to SSH into them.
 | 
						|
        $rc = xCAT::zvmUtils->findAccessIP( $callback, $activeSystem, $hcp, \%discoverable, \%args, $::SUDOER );
 | 
						|
        if ( $rc != 0 ) {
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            if ( $args{'verbose'} ) {
 | 
						|
                push @{$rsp->{data}}, "ignoring: $activeSystem - could not access the virtual server.";
 | 
						|
                xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
            }
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        # Obtain the memory and CPU count from the active system information.
 | 
						|
        $out = `ssh -q $::SUDOER\@$hcp $::SUDO $ZHCP_BIN/smcli "Image_Active_Configuration_Query -T '$activeSystem'"`;
 | 
						|
        $rc = $? >> 8;
 | 
						|
        if ($rc == 255) {
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            push @{$rsp->{data}}, "z/VM discovery is unable to communicate with the zhcp system: $hcp";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            next;
 | 
						|
        } elsif ( $rc != 0 ) {
 | 
						|
            my $rsp;
 | 
						|
            push @{$rsp->{data}}, "An unexpected return code $rc was received from " .
 | 
						|
                                  "the zhcp server $hcp for an smcli Image_Active_Configuration_Query " .
 | 
						|
                                  "request.  SMAPI servers may be unavailable.  " .
 | 
						|
                                  "Received response: $out";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback);
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        my $memOut = `echo "$out" | egrep -i 'Memory:'`;
 | 
						|
        chomp $memOut;
 | 
						|
        my @parts = split( /Memory: /, $memOut );
 | 
						|
        @parts = split( / /, $parts[1] );
 | 
						|
        $discoverable{$activeSystem}{'memory'} = $parts[0].$parts[1];
 | 
						|
        my $cpuOut = `echo "$out" | egrep -i 'CPU count:'`;
 | 
						|
        chomp $cpuOut;
 | 
						|
        @parts = split( 'CPU count: ', $cpuOut );
 | 
						|
        $discoverable{$activeSystem}{'cpuCount'} = $parts[1];
 | 
						|
 | 
						|
        my $os = xCAT::zvmUtils->getOSFromIP( $callback, $activeSystem, $discoverable{$activeSystem}{'ipAddr'}, $discoverable{$activeSystem}{'ipVersion'} );
 | 
						|
        if ( $os ne '' ) {
 | 
						|
            $discoverable{$activeSystem}{'os'} = $os;
 | 
						|
        } else {
 | 
						|
            if ( $args{'verbose'} ) {
 | 
						|
                push @{$rsp->{data}}, "ignoring: $activeSystem - unable to obtain OS version information from the operating system";
 | 
						|
                xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
            }
 | 
						|
            delete( $discoverable{$activeSystem} );
 | 
						|
            next;
 | 
						|
        }
 | 
						|
 | 
						|
        xCAT::MsgUtils->message( "S", "Discovery for $zvmHost is preparing to create a node for $activeSystem." );
 | 
						|
 | 
						|
        # Set up to define the node.
 | 
						|
        $discoverable{$activeSystem}{'uuid'} = xCAT::Utils::genUUID();
 | 
						|
        $discoverable{$activeSystem}{'openstackoperands'} = $args{'openstackoperands'};
 | 
						|
 | 
						|
        # Generate an xCAT node name for the newly discovered system.
 | 
						|
        my $node;
 | 
						|
 | 
						|
        # Create an xCAT node.
 | 
						|
        my $retstr_gen = '';
 | 
						|
 | 
						|
        $retstr_gen .= "    arch=s390x\n";
 | 
						|
        if ( $args{'groups'} ) {
 | 
						|
            $retstr_gen .= "    groups=$args{'groups'}\n";
 | 
						|
        } else {
 | 
						|
            $retstr_gen .= "    groups=all\n";
 | 
						|
        }
 | 
						|
        $retstr_gen .= "    hcp=$hcp\n";
 | 
						|
        if ( $discoverable{$activeSystem}{'hostname'} ) {
 | 
						|
            $retstr_gen .= "    hostnames=$discoverable{$activeSystem}{'hostname'}\n";
 | 
						|
        }
 | 
						|
        $retstr_gen .= "    ip=$discoverable{$activeSystem}{'ipAddr'}\n";
 | 
						|
        $retstr_gen .= "    mgt=zvm\n";
 | 
						|
        $retstr_gen .= "    objtype=node\n";
 | 
						|
        $retstr_gen .= "    os=$discoverable{$activeSystem}{'os'}\n";
 | 
						|
        $retstr_gen .= "    userid=$activeSystem\n";
 | 
						|
 | 
						|
        ( $node, $numeric ) = createNode( $callback, $discoverable{$activeSystem}{'hostname'}, $args{'nodenameformat'}, $numeric, $retstr_gen, \%xcatNodes );
 | 
						|
        if ( $node eq '' ) {
 | 
						|
            # If we cannot create a node then skip this one and go on to the next.
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        $discoverable{$activeSystem}{'node'} = $node;
 | 
						|
 | 
						|
        # Start OpenStack Provisioning for this node, if desired.
 | 
						|
        if ( $startOpenStack ) {
 | 
						|
            my $openstackNodeName = addOpenStackSystem( $callback, $zvmHost, $hcp, $args{'verbose'}, $activeSystem, \%discoverable );
 | 
						|
 | 
						|
            if ( !$openstackNodeName ) {
 | 
						|
                # Node was not created in OpenStack.  Remove it from xCAT.
 | 
						|
                changeNode( $callback, $node, 'd' );
 | 
						|
                next;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        updateDiscoverydata( $callback, 'add', $args{'verbose'}, $zvmHost, $activeSystem, \%discoverable );
 | 
						|
    }
 | 
						|
 | 
						|
    # Common exit point.
 | 
						|
FINISH_startDiscovery:
 | 
						|
    my $startTime = getRunningDiscTimestamp( $callback, $zvmHost );
 | 
						|
    if ( $startTime == $initStartTime ) {
 | 
						|
        my @stopArgs = ();
 | 
						|
        stopDiscovery( $callback, $zvmHost, \@stopArgs );
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   stopDiscovery
 | 
						|
 | 
						|
    Description : Stop z/VM discovery for a particular z/VM host.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  z/VM host node name
 | 
						|
                  Array of arguments specified on nodediscoverstop or
 | 
						|
                    an empty array if this is an internal call.
 | 
						|
    Returns     : None.
 | 
						|
    Example     : stopDiscovery( $callback, $zvmHost, \@args );
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub stopDiscovery{
 | 
						|
    my $callback = shift;
 | 
						|
    my $zvmHost = shift;
 | 
						|
    my $argsRef = shift;
 | 
						|
    my @args = @$argsRef;
 | 
						|
 | 
						|
    my $rsp;
 | 
						|
    push @{$rsp->{data}}, "z/VM discovery is being stopped for $zvmHost.";
 | 
						|
    xCAT::MsgUtils->message( "I", $rsp, $callback, 1 );
 | 
						|
 | 
						|
    # Get the hcp from the zvm table.
 | 
						|
    my @propNames = ( 'hcp', 'nodetype' );
 | 
						|
    my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $zvmHost, @propNames );
 | 
						|
    my $hcp = $propVals->{'hcp'};
 | 
						|
 | 
						|
    # Get the list of discovered systems from the zvm table.
 | 
						|
    my $zvmTab = xCAT::Table->new('zvm');
 | 
						|
    if ( !$zvmTab ) {
 | 
						|
        push @{$rsp->{data}}, "Could not open table: zvm.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    my %discoveredNodes;
 | 
						|
    my @zvmData = $zvmTab->getAllAttribsWhere( "hcp='$hcp'", 'node', 'userid' );
 | 
						|
    foreach ( @zvmData ) {
 | 
						|
        $discoveredNodes{$_->{'node'}} = $_->{'userid'};
 | 
						|
    }
 | 
						|
 | 
						|
    # Go though the discoverydata table and display the z/VM discovery entries
 | 
						|
    my $disTab = xCAT::Table->new('discoverydata');
 | 
						|
    if ( !$disTab ) {
 | 
						|
        push @{$rsp->{data}}, "Could not open table: discoverydata.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    my @disData = $disTab->getAllAttribsWhere( "method='zvm' and otherdata='zvmhost.$zvmHost'", 'node' );
 | 
						|
    push @{$rsp->{data}}, "Discovered ".($#disData+1)." nodes running on $zvmHost.";
 | 
						|
 | 
						|
    if ( @disData ) {
 | 
						|
        push @{$rsp->{data}}, sprintf("    %-20s%-8s", 'NODE', 'z/VM USERID');
 | 
						|
        foreach ( @disData ) {
 | 
						|
             push @{$rsp->{data}}, sprintf("    %-20s%-8s", $_->{'node'}, $discoveredNodes{$_->{'node'}} );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    removeHostInfo( $callback, $zvmHost );
 | 
						|
 | 
						|
    xCAT::MsgUtils->message( "I", $rsp, $callback );
 | 
						|
    xCAT::MsgUtils->message( "I", "z/VM discovery stopped for z/VM host: $zvmHost" );
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  updateDiscoverydata
 | 
						|
 | 
						|
    Description : Update the discoverydata table.
 | 
						|
    Arguments   : Callback handle
 | 
						|
                  function: 'add' is the only function
 | 
						|
                    currently supported.
 | 
						|
                  verbose flag
 | 
						|
                  z/VM host node name
 | 
						|
                  Virtual machine userid
 | 
						|
                  discoverable hash which contains lots of properties
 | 
						|
    Returns     : None.
 | 
						|
    Example     : updateDiscoverydata( $callback, 'add', $verbose, $zvmHost,
 | 
						|
                                       $activeSystem, \%discoverable ):
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub updateDiscoverydata{
 | 
						|
    my ( $callback, $function, $verbose, $zvmHost, $activeSystem, $discoverableRef ) = @_;
 | 
						|
    my %discoverable = %$discoverableRef;
 | 
						|
 | 
						|
    my %discoverInfo;
 | 
						|
    my $disTab = xCAT::Table->new("discoverydata");
 | 
						|
    if ( !$disTab ) {
 | 
						|
        my $rsp;
 | 
						|
        push @{$rsp->{data}}, "Could not open table: discoverydata.";
 | 
						|
        xCAT::MsgUtils->message( "E", $rsp, $callback );
 | 
						|
        goto FINISH_updateDiscoverydata;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( $function = 'add' ) {
 | 
						|
        # Create a row in the discoverydata table to represent this discovered system.
 | 
						|
        $discoverInfo{'arch'} = "s390x";
 | 
						|
        $discoverInfo{'cpucount'} = $discoverable{$activeSystem}{'cpuCount'};
 | 
						|
        $discoverInfo{'memory'} = $discoverable{$activeSystem}{'memory'};
 | 
						|
        $discoverInfo{'method'} = "zvm";
 | 
						|
        $discoverInfo{'node'} = $discoverable{$activeSystem}{'node'};
 | 
						|
        $discoverInfo{'otherdata'} = 'zvmhost.' . $zvmHost;
 | 
						|
 | 
						|
        # Set the discovery time.
 | 
						|
        my ($sec,  $min,  $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
 | 
						|
        my $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d",
 | 
						|
                               $mon + 1, $mday, $year + 1900, $hour, $min, $sec);
 | 
						|
        $discoverInfo{'discoverytime'} = $currtime;
 | 
						|
 | 
						|
        # Update the discoverydata table.
 | 
						|
        $disTab->setAttribs({uuid => $discoverable{$activeSystem}{'uuid'}}, \%discoverInfo);
 | 
						|
        $disTab->commit();
 | 
						|
    }
 | 
						|
 | 
						|
FINISH_updateDiscoverydata:
 | 
						|
    return;
 | 
						|
}
 | 
						|
1;
 |