PCM discover initial draft ready
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@13904 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		@@ -6,6 +6,7 @@ use warnings;
 | 
			
		||||
use Socket;
 | 
			
		||||
use File::Path qw/mkpath/;
 | 
			
		||||
use File::Temp qw/tempfile/;
 | 
			
		||||
use Fcntl qw(:flock);
 | 
			
		||||
require xCAT::Table;
 | 
			
		||||
require xCAT::TableUtils;
 | 
			
		||||
require xCAT::NodeRange;
 | 
			
		||||
@@ -67,6 +68,7 @@ sub get_allocable_staticips_innet
 | 
			
		||||
=head3 genhosts_with_numric_tmpl
 | 
			
		||||
      Description : Generate numric hostnames using numric template name.
 | 
			
		||||
      Arguments   : $format - The hostname format string..
 | 
			
		||||
                    $rank - The start number.
 | 
			
		||||
      Returns     : numric hostname list
 | 
			
		||||
      Example     : 
 | 
			
		||||
              calling  genhosts_with_numric_tmpl("compute#NNnode") will return a list like:
 | 
			
		||||
@@ -76,10 +78,10 @@ sub get_allocable_staticips_innet
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub genhosts_with_numric_tmpl
 | 
			
		||||
{
 | 
			
		||||
    my ($class, $format) = @_;
 | 
			
		||||
    my ($class, $format, $rank) = @_;
 | 
			
		||||
 | 
			
		||||
    my ($prefix, $appendix, $len) = xCAT::PCMNodeMgmtUtils->split_hostname($format, 'N');
 | 
			
		||||
    return xCAT::PCMNodeMgmtUtils->gen_numric_hostnames($prefix, $appendix, $len);
 | 
			
		||||
    return xCAT::PCMNodeMgmtUtils->gen_numric_hostnames($prefix, $appendix, $len, $rank);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
@@ -139,10 +141,13 @@ sub split_hostname
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub gen_numric_hostnames
 | 
			
		||||
{
 | 
			
		||||
    my ($class, $prefix, $appendix, $len) = @_;
 | 
			
		||||
    my ($class, $prefix, $appendix, $len, $rank) = @_;
 | 
			
		||||
    my @hostnames;
 | 
			
		||||
    my $cnt = 0;
 | 
			
		||||
 | 
			
		||||
    my $cnt=0;
 | 
			
		||||
    if ($rank){
 | 
			
		||||
        $cnt = $rank;
 | 
			
		||||
    } 
 | 
			
		||||
    my $maxnum = 10 ** $len;
 | 
			
		||||
    while($cnt < $maxnum)
 | 
			
		||||
    {
 | 
			
		||||
@@ -392,39 +397,56 @@ sub get_allnode_singleattrib_hash
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3 acquire_lock
 | 
			
		||||
      Description : Create lock file for node management plugin so that there is 
 | 
			
		||||
                    no multi node mamangement plugins running.
 | 
			
		||||
                    The file content will be the pid of the plugin running process.
 | 
			
		||||
                    Once the plugin process terminated abnormally and lock file not removed,
 | 
			
		||||
                    next time node management plugin runs, it will read the lock file 
 | 
			
		||||
                    and check whether this process is running or not. If not, 
 | 
			
		||||
                    just remove this lock file and create a new one.
 | 
			
		||||
      Arguments   : N/A
 | 
			
		||||
      Returns     : 1 - create lock success.
 | 
			
		||||
                    0 - failed, there may be a node management process running.
 | 
			
		||||
      Description : Create lock file for PCM plugins so that there is 
 | 
			
		||||
                    no multi instance of plugins running at same time.
 | 
			
		||||
                    The lock file content will be the pid of the plugin running process.
 | 
			
		||||
                    Using perl's flock to achive this.
 | 
			
		||||
                    Note: we can not judge whether PCM discovering is running or only 
 | 
			
		||||
                          through acquire_lock("nodemgmt")
 | 
			
		||||
                          We must also call is_discover_started() 
 | 
			
		||||
      Arguments   : action name: for example: nodemgmt, imageprofile...etc We'll generate
 | 
			
		||||
                    a lock file named as /var/lock/pcm/$action.
 | 
			
		||||
      Returns     : -1 - Acquire lock failed.
 | 
			
		||||
                    fh of lock file - the filehandler of lock file.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub acquire_lock
 | 
			
		||||
{
 | 
			
		||||
    my $lockfile = "/var/lock/pcm/nodemgmt";
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    my $action = shift;
 | 
			
		||||
    my $lockdir = "/var/lock/pcm";
 | 
			
		||||
    mkdir "$lockdir", 0755 unless -d "$lockdir";
 | 
			
		||||
    my $lockfile = "$lockdir/$action";
 | 
			
		||||
 | 
			
		||||
    if (-e $lockfile) {
 | 
			
		||||
        open LOCKFILE, "<$lockfile";
 | 
			
		||||
        my @lines = <LOCKFILE>;
 | 
			
		||||
        my $pid = $lines[0];
 | 
			
		||||
        if (-d "/proc/$pid") {
 | 
			
		||||
            return 0;
 | 
			
		||||
        } else{
 | 
			
		||||
            # the process already not exists, remove lock file.
 | 
			
		||||
            File::Path->rmtree($lockfile);
 | 
			
		||||
        }
 | 
			
		||||
    mkdir "$lockdir", 0755 unless -d "$lockdir";
 | 
			
		||||
    open my $fh, ">$lockfile";
 | 
			
		||||
    # use flock, non-blocking mode while acquiring a lock.
 | 
			
		||||
    my $lockret = flock($fh, LOCK_EX|LOCK_NB);
 | 
			
		||||
    if(! $lockret){
 | 
			
		||||
        close $fh;
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    print $fh $$;
 | 
			
		||||
    return $fh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3 is_discover_started
 | 
			
		||||
      Description : Judge whether PCM discovering is running or not.
 | 
			
		||||
      Arguments   : NA
 | 
			
		||||
      Returns     : 1 - Discover is running
 | 
			
		||||
                    0 - Discover is not started.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub is_discover_started
 | 
			
		||||
{
 | 
			
		||||
    my @sitevalues = xCAT::TableUtils->get_site_attribute("__PCMDiscover");
 | 
			
		||||
    if (! $sitevalues[0]){
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    open LOCKFILE, ">$lockfile";
 | 
			
		||||
    print LOCKFILE $$;
 | 
			
		||||
    close LOCKFILE;
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -432,23 +454,18 @@ sub acquire_lock
 | 
			
		||||
 | 
			
		||||
=head3 release_lock
 | 
			
		||||
      Description : Release lock for node management process.
 | 
			
		||||
      Arguments   : N/A
 | 
			
		||||
      Returns     : N/A
 | 
			
		||||
      Arguments   : fh - the lock file handler.
 | 
			
		||||
      Returns     : return value of flock.
 | 
			
		||||
                    True - release lock succeed.
 | 
			
		||||
                    False - release lock failed.
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
sub release_lock
 | 
			
		||||
{
 | 
			
		||||
    my $lockfile = "/var/lock/pcm/nodemgmt";
 | 
			
		||||
    if (-e $lockfile){
 | 
			
		||||
        open LOCKFILE, "<$lockfile";
 | 
			
		||||
        my @lines = <LOCKFILE>;
 | 
			
		||||
        my $pid = $lines[0];
 | 
			
		||||
        close LOCKFILE;
 | 
			
		||||
        if ($pid ne $$){
 | 
			
		||||
            File::Path->rmtree($lockfile);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    my $lockfh = shift;
 | 
			
		||||
    return flock($lockfh, LOCK_UN|LOCK_NB);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -70,56 +70,95 @@ sub process_request {
 | 
			
		||||
    
 | 
			
		||||
    my $nodelist = $request->{node};
 | 
			
		||||
    my $retref;
 | 
			
		||||
    my $rsp;
 | 
			
		||||
 | 
			
		||||
    if($command eq 'kitcmd_nodemgmt_add')
 | 
			
		||||
    {
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating hosts entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makehosts"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist, arg=>['-n']}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating DNS entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        # Work around for makedns bug, it will set umask to 0007.
 | 
			
		||||
        #umask(0022);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update DHCP entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makekdhcp"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update known hosts";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makeknownhosts"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        my $firstnode = (@$nodelist)[0];
 | 
			
		||||
        my $profileref = xCAT::PCMNodeMgmtUtils->get_nodes_profiles([$firstnode]);
 | 
			
		||||
        my %profilehash = %$profileref;
 | 
			
		||||
        if (exists $profilehash{$firstnode}{"ImageProfile"}){
 | 
			
		||||
            $rsp->{info}->[0] = "[PCM nodes mgmt]Update nodes' boot settings";
 | 
			
		||||
            $::CALLBACK->($rsp);
 | 
			
		||||
            $retref = xCAT::Utils->runxcmd({command=>["nodeset"], node=>$nodelist, arg=>['osimage='.$profilehash{$firstnode}{"ImageProfile"}]}, $request_command, 0, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($command eq 'kitcmd_nodemgmt_remove'){
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["nodeset"], node=>$nodelist, arg=>['offline']}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update known hosts";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makeknownhosts"], node=>$nodelist, arg=>['-r']}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update DHCP entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makekdhcp"], node=>$nodelist, arg=>['-d']}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating DNS entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist, arg=>['-d']}, $request_command, 0, 1);
 | 
			
		||||
        # Work around for makedns bug, it will set umask to 0007.
 | 
			
		||||
        #umask(0022);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating hosts entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makehosts"], node=>$nodelist, arg=>['-d']}, $request_command, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($command eq 'kitcmd_nodemgmt_update'){
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating hosts entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makehosts"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist, arg=>['-n']}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating DNS entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        # Work around for makedns bug, it will set umask to 0007.
 | 
			
		||||
        #umask(0022);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update DHCP entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makekdhcp"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update known hosts";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makeknownhosts"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        my $firstnode = (@$nodelist)[0];
 | 
			
		||||
        my $profileref = xCAT::PCMNodeMgmtUtils->get_nodes_profiles([$firstnode]);
 | 
			
		||||
        my %profilehash = %$profileref;
 | 
			
		||||
        if (exists $profilehash{$firstnode}{"ImageProfile"}){
 | 
			
		||||
            $rsp->{info}->[0] = "[PCM nodes mgmt]Update nodes' boot settings";
 | 
			
		||||
            $::CALLBACK->($rsp);
 | 
			
		||||
            $retref = xCAT::Utils->runxcmd({command=>["nodeset"], node=>$nodelist, arg=>['osimage='.$profilehash{$firstnode}{"ImageProfile"}]}, $request_command, 0, 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($command eq 'kitcmd_nodemgmt_refresh'){
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating hosts entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makehosts"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist, arg=>['-n']}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating DNS entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makedns"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        # Work around for makedns bug, it will set umask to 0007.
 | 
			
		||||
        #umask(0022);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update DHCP entries";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makekdhcp"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Update known hosts";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makeknownhosts"], node=>$nodelist}, $request_command, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($command eq 'kitcmd_nodemgmt_finished')
 | 
			
		||||
    {
 | 
			
		||||
        $rsp->{info}->[0] = "[PCM nodes mgmt]Updating conserver configuration files";
 | 
			
		||||
        $::CALLBACK->($rsp);
 | 
			
		||||
        $retref = xCAT::Utils->runxcmd({command=>["makeconservercf"]}, $request_command, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,10 @@ sub handled_commands {
 | 
			
		||||
        addhost_discover     => 'pcmnodes',
 | 
			
		||||
        removehost     => 'pcmnodes',
 | 
			
		||||
        updatehost     => 'pcmnodes',
 | 
			
		||||
        pcmdiscover_start => 'pcmnodes',
 | 
			
		||||
        pcmdiscover_stop => 'pcmnodes',
 | 
			
		||||
        pcmdiscover_nodels => 'pcmnodes',
 | 
			
		||||
        findme => 'pcmnodes',
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -76,16 +80,29 @@ sub handled_commands {
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub process_request {
 | 
			
		||||
 | 
			
		||||
    my $lock = xCAT::PCMNodeMgmtUtils->acquire_lock();
 | 
			
		||||
    unless ($lock){
 | 
			
		||||
        setrsp_errormsg("Can not acquire lock, some process is operating node related actions.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    $request = shift;
 | 
			
		||||
    $callback = shift;
 | 
			
		||||
    $::CALLBACK = $callback;
 | 
			
		||||
    $request_command = shift;
 | 
			
		||||
    $command = $request->{command}->[0];
 | 
			
		||||
    $args = $request->{arg};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    my $lockfh = xCAT::PCMNodeMgmtUtils->acquire_lock("nodemgmt");
 | 
			
		||||
    if ($lockfh == -1){
 | 
			
		||||
        setrsp_errormsg("Can not acquire lock, some process is operating node related actions.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # These commands should make sure no discover is running.
 | 
			
		||||
    if (grep{ $_ eq $command} ("addhost_hostfile", "removehost", "updatehost")){
 | 
			
		||||
        my $discover_running = xCAT::PCMNodeMgmtUtils->is_discover_started();
 | 
			
		||||
        if ($discover_running){
 | 
			
		||||
            setrsp_errormsg("Can not run command $command as PCM discover is running.");
 | 
			
		||||
            xCAT::PCMNodeMgmtUtils->release_lock($lockfh);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
	
 | 
			
		||||
    if ($command eq "addhost_hostfile"){
 | 
			
		||||
        addhost_hostfile()
 | 
			
		||||
@@ -93,8 +110,17 @@ sub process_request {
 | 
			
		||||
    	removehost();
 | 
			
		||||
    } elsif ($command eq "updatehost"){
 | 
			
		||||
    	updatehost();
 | 
			
		||||
    } elsif ($command eq "pcmdiscover_start"){
 | 
			
		||||
        pcmdiscover_start();
 | 
			
		||||
    } elsif ($command eq "pcmdiscover_nodels"){
 | 
			
		||||
        pcmdiscover_nodels();
 | 
			
		||||
    } elsif ($command eq "findme"){
 | 
			
		||||
        findme();
 | 
			
		||||
    } elsif ($command eq "pcmdiscover_stop"){
 | 
			
		||||
        pcmdiscover_stop();
 | 
			
		||||
    }
 | 
			
		||||
    xCAT::PCMNodeMgmtUtils->release_lock($lock);
 | 
			
		||||
 | 
			
		||||
    xCAT::PCMNodeMgmtUtils->release_lock($lockfh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
@@ -157,39 +183,49 @@ sub parse_args{
 | 
			
		||||
sub addhost_hostfile {
 | 
			
		||||
 | 
			
		||||
    # Parse arges.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Import PCM nodes through hostinfo file.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Import PCM nodes through hostinfo file.");
 | 
			
		||||
    my $retstr = parse_args();
 | 
			
		||||
    if ($retstr){
 | 
			
		||||
        setrsp_errormsg($retstr);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    # Make sure the specified parameters are valid ones.
 | 
			
		||||
    # TODO: support privisioning template.
 | 
			
		||||
    my @enabledparams = ('file', 'groups', 'networkprofile', 'hardwareprofile', 'imageprofile');
 | 
			
		||||
    my @enabledparams = ('file', 'groups', 'networkprofile', 'hardwareprofile', 'imageprofile', 'hostnameformat');
 | 
			
		||||
    foreach my $argname (keys %args_dict){
 | 
			
		||||
        if (! grep{ $_ eq $argname} @enabledparams){
 | 
			
		||||
            setrsp_errormsg("Illegal attribute $argname specified.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    # validate hostinfo file.
 | 
			
		||||
    if (! exists $args_dict{'file'}){
 | 
			
		||||
        setrsp_errormsg("No hostinfo file specified.");
 | 
			
		||||
        return;
 | 
			
		||||
    # Mandatory arguments.
 | 
			
		||||
    foreach (('file','networkprofile', 'imageprofile', 'hostnameformat')){
 | 
			
		||||
        if(! exists($args_dict{$_})){
 | 
			
		||||
            setrsp_errormsg("Mandatory parameter $_ not specified.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    elsif(! (-e $args_dict{'file'})){
 | 
			
		||||
 | 
			
		||||
    if(! (-e $args_dict{'file'})){
 | 
			
		||||
        setrsp_errormsg("The hostinfo file not exists.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Get database records: all hostnames, all ips, all racks...
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Getting database records.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Getting database records.");
 | 
			
		||||
    my $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('nodelist', 'node');
 | 
			
		||||
    %allhostnames = %$recordsref;
 | 
			
		||||
    $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('ipmi', 'bmc');
 | 
			
		||||
    %allbmcips = %$recordsref;
 | 
			
		||||
    $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('mac', 'mac');
 | 
			
		||||
    %allmacs = %$recordsref;
 | 
			
		||||
    # MAC records looks like: "01:02:03:04:05:0E!node5│01:02:03:05:0F!node6-eth1". We want to get the real mac addres.
 | 
			
		||||
    foreach (keys %allmacs){
 | 
			
		||||
        my @hostentries = split(/\|/, $_);
 | 
			
		||||
        foreach my $hostandmac ( @hostentries){
 | 
			
		||||
            my ($macstr, $machostname) = split("!", $hostandmac);
 | 
			
		||||
            $allmacs{$macstr} = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('hosts', 'ip');
 | 
			
		||||
    %allinstallips = %$recordsref;
 | 
			
		||||
    $recordsref = xCAT::NetworkUtils->get_all_nicips(1);
 | 
			
		||||
@@ -198,13 +234,14 @@ sub addhost_hostfile {
 | 
			
		||||
    # Merge all BMC IPs and install IPs into allips.
 | 
			
		||||
    %allips = (%allips, %allbmcips, %allinstallips);
 | 
			
		||||
 | 
			
		||||
    #my $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('rack', 'rackname');
 | 
			
		||||
    #%allracks = %$recordsref;
 | 
			
		||||
    #my $recordsref =  xCAT::PCMNodeMgmtUtils->get_allchassis(1);
 | 
			
		||||
    #%allchassis = %$recordsref;
 | 
			
		||||
    #TODO: can not use getallnode to get rack infos.
 | 
			
		||||
    #$recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('rack', 'rackname');
 | 
			
		||||
    %allracks = ();
 | 
			
		||||
    $recordsref =  xCAT::PCMNodeMgmtUtils->get_all_chassis(1);
 | 
			
		||||
    %allchassis = %$recordsref;
 | 
			
		||||
 | 
			
		||||
    # Generate temporary hostnames for hosts entries in hostfile. 
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Generate temporary hostnames.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Generate temporary hostnames.");
 | 
			
		||||
    my ($retcode_read, $retstr_read) = read_and_generate_hostnames($args_dict{'file'});
 | 
			
		||||
    if ($retcode_read != 0){
 | 
			
		||||
        setrsp_errormsg($retstr_read);
 | 
			
		||||
@@ -212,7 +249,7 @@ sub addhost_hostfile {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Parse and validate the hostinfo string. The real hostnames will be generated here.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Parsing hostinfo string and validate it.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Parsing hostinfo string and validate it.");
 | 
			
		||||
    my ($hostinfo_dict_ref, $invalid_records_ref) = parse_hosts_string($retstr_read);
 | 
			
		||||
    my %hostinfo_dict = %$hostinfo_dict_ref;
 | 
			
		||||
    my @invalid_records = @$invalid_records_ref;
 | 
			
		||||
@@ -226,18 +263,18 @@ sub addhost_hostfile {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Create the real hostinfo string in stanza file format.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Generating new hostinfo string.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Generating new hostinfo string.");
 | 
			
		||||
    my ($retcode_gen, $retstr_gen) = gen_new_hostinfo_string(\%hostinfo_dict);
 | 
			
		||||
    unless ($retcode_gen){
 | 
			
		||||
        setrsp_errormsg($retstr_gen);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    # call mkdef to create hosts and then call nodemgmt for node management plugins.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call mkdef to create pcm nodes.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]call mkdef to create pcm nodes.");
 | 
			
		||||
    my $retref = xCAT::Utils->runxcmd({command=>["mkdef"], stdin=>[$retstr_gen], arg=>['-z']}, $request_command, 0, 1);
 | 
			
		||||
 | 
			
		||||
    my @nodelist = keys %hostinfo_dict;
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call nodemgmt plugins.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]call nodemgmt plugins.");
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_add"], node=>\@nodelist}, $request_command, 0, 1);
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_finished"], node=>\@nodelist}, $request_command, 0, 1);
 | 
			
		||||
    setrsp_success(\@nodelist);
 | 
			
		||||
@@ -255,12 +292,12 @@ sub addhost_hostfile {
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub removehost{
 | 
			
		||||
    my $nodes   = $request->{node};
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Remove PCM nodes.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Remove PCM nodes.");
 | 
			
		||||
    # For remove nodes, we should call 'nodemgmt' in front of 'noderm'
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call nodemgmt plugins.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]call nodemgmt plugins.");
 | 
			
		||||
    my $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_remove"], node=>$nodes}, $request_command, 0, 1);
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_finished"], node=>$nodes}, $request_command, 0, 1);
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call noderm to remove nodes.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]call noderm to remove nodes.");
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["noderm"], node=>$nodes}, $request_command, 0, 1);
 | 
			
		||||
    setrsp_success($nodes);
 | 
			
		||||
}
 | 
			
		||||
@@ -279,7 +316,7 @@ sub updatehost{
 | 
			
		||||
    my $nodes   = $request->{node};
 | 
			
		||||
    my %updated_groups;
 | 
			
		||||
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Update PCM nodes settings.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Update PCM nodes settings.");
 | 
			
		||||
    # Parse arges.
 | 
			
		||||
    my $retstr = parse_args();
 | 
			
		||||
    if ($retstr){
 | 
			
		||||
@@ -287,7 +324,6 @@ sub updatehost{
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    # Make sure the specified parameters are valid ones.
 | 
			
		||||
    # TODO: support privisioning template.
 | 
			
		||||
    my @enabledparams = ('networkprofile', 'hardwareprofile', 'imageprofile');
 | 
			
		||||
    foreach my $argname (keys %args_dict){
 | 
			
		||||
        if (! grep{ $_ eq $argname} @enabledparams){
 | 
			
		||||
@@ -297,7 +333,7 @@ sub updatehost{
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Get current templates for all nodes.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Read database to get groups for all nodes.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Read database to get groups for all nodes.");
 | 
			
		||||
    my %groupdict;
 | 
			
		||||
    my $nodelstab = xCAT::Table->new('nodelist');
 | 
			
		||||
    my $nodeshashref = $nodelstab->getNodesAttribs($nodes, ['groups']);
 | 
			
		||||
@@ -326,13 +362,13 @@ sub updatehost{
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #update DataBase.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]Update database records.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]Update database records.");
 | 
			
		||||
    my $nodetab = xCAT::Table->new('nodelist',-create=>1);
 | 
			
		||||
    $nodetab->setNodesAttribs(\%updatenodeshash);
 | 
			
		||||
    $nodetab->close();
 | 
			
		||||
    
 | 
			
		||||
    # call plugins
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call nodemgmt plugins.\n");
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]call nodemgmt plugins.");
 | 
			
		||||
    my $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_update"], node=>$nodes}, $request_command, 0, 1);
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_finished"], node=>$nodes}, $request_command, 0, 1);
 | 
			
		||||
    setrsp_success($nodes);
 | 
			
		||||
@@ -340,6 +376,314 @@ sub updatehost{
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  pcmdiscover_start
 | 
			
		||||
 | 
			
		||||
    Description : Start PCM discovery. If already started, return a failure.
 | 
			
		||||
                  User should specify networkprofile, hardwareprofile, 
 | 
			
		||||
                  imageprofile, hostnameformat, rack, chassis, height and u so
 | 
			
		||||
                  that node's IP address will be generated automatcially 
 | 
			
		||||
                  according to networkprofile, node's hardware settings will
 | 
			
		||||
                  be set according to hardware profile, node's os settings will
 | 
			
		||||
                  be set according to image profile, node's hostname will be 
 | 
			
		||||
                  set according to hostnameformat and rank. And other node's 
 | 
			
		||||
                  attribs will also be set according to rack, chassis, height and u.
 | 
			
		||||
    Arguments   : N/A
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub pcmdiscover_start{
 | 
			
		||||
    # Parse arges.
 | 
			
		||||
    setrsp_infostr("[PCM nodes mgmt]PCM discovery started.");
 | 
			
		||||
    my $retstr = parse_args();
 | 
			
		||||
    if ($retstr){
 | 
			
		||||
        setrsp_errormsg($retstr);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my @enabledparams = ('networkprofile', 'hardwareprofile', 'imageprofile', 'hostnameformat', 'rank', 'rack', 'chassis', 'height', 'u');
 | 
			
		||||
    foreach my $argname (keys %args_dict){
 | 
			
		||||
        if (! grep{ $_ eq $argname} @enabledparams){
 | 
			
		||||
            setrsp_errormsg("Illegal attribute $argname specified.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    # mandatory arguments.
 | 
			
		||||
    foreach my $key ('networkprofile', 'imageprofile', 'hostnameformat'){
 | 
			
		||||
        if (! exists $args_dict{$key}){
 | 
			
		||||
            setrsp_errormsg("argument $key must be specified");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Read DB to confirm the discover is not started yet. 
 | 
			
		||||
    my @sitevalues = xCAT::TableUtils->get_site_attribute("__PCMDiscover");
 | 
			
		||||
    if ($sitevalues[0]){
 | 
			
		||||
        setrsp_errormsg("PCM node discovery already started.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # save discover args into table site.
 | 
			
		||||
    my $valuestr = "";
 | 
			
		||||
    foreach (keys %args_dict){
 | 
			
		||||
        if($args_dict{$_}){
 | 
			
		||||
            $valuestr .= "$_:$args_dict{$_},";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $sitetab = xCAT::Table->new('site',-create=>1);
 | 
			
		||||
    $sitetab->setAttribs({"key" => "__PCMDiscover"}, {"value" => "$valuestr"});
 | 
			
		||||
    $sitetab->close();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  pcmdiscover_stop
 | 
			
		||||
 | 
			
		||||
    Description : Stop PCM auto discover. This action will remove the 
 | 
			
		||||
                  dababase flags.
 | 
			
		||||
    Arguments   : N/A
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#------------------------------------------------------
 | 
			
		||||
sub pcmdiscover_stop{
 | 
			
		||||
    # Read DB to confirm the discover is started. 
 | 
			
		||||
    my @sitevalues = xCAT::TableUtils->get_site_attribute("__PCMDiscover");
 | 
			
		||||
    if (! $sitevalues[0]){
 | 
			
		||||
        setrsp_errormsg("PCM node discovery not started yet.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # remove site table records: discover flag.
 | 
			
		||||
    my $sitetab=xCAT::Table->new("site");
 | 
			
		||||
    my %keyhash;
 | 
			
		||||
    $keyhash{'key'} = "__PCMDiscover";
 | 
			
		||||
    $sitetab->delEntries(\%keyhash);
 | 
			
		||||
    $sitetab->commit();
 | 
			
		||||
    
 | 
			
		||||
    # Update node's attributes, remove from gruop "__PCMDiscover".
 | 
			
		||||
    # we'll call rmdef so that node's groupinfo in table nodelist will be updated automatically.
 | 
			
		||||
    my @nodes = xCAT::NodeRange::noderange('__PCMDiscover');
 | 
			
		||||
    if (@nodes){
 | 
			
		||||
        # There are some nodes discvoered.
 | 
			
		||||
        my $retref = xCAT::Utils->runxcmd({command=>["rmdef"], arg=>["-t", "group", "-o", "__PCMDiscover"]}, $request_command, 0, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  pcmdiscover_nodels
 | 
			
		||||
 | 
			
		||||
    Description : List all discovered PCM nodes.
 | 
			
		||||
    Arguments   : N/A
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub pcmdiscover_nodels{
 | 
			
		||||
    # Read DB to confirm the discover is started. 
 | 
			
		||||
    my @sitevalues = ();
 | 
			
		||||
    @sitevalues = xCAT::TableUtils->get_site_attribute("__PCMDiscover");
 | 
			
		||||
    if (! $sitevalues[0]){
 | 
			
		||||
        setrsp_errormsg("PCM node discovery not started yet.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my @nodes = xCAT::NodeRange::noderange('__PCMDiscover');
 | 
			
		||||
    my $mactab = xCAT::Table->new("mac");
 | 
			
		||||
    my $macsref = $mactab->getNodesAttribs(\@nodes, ['mac']);
 | 
			
		||||
    my $nodelisttab = xCAT::Table->new("nodelist");
 | 
			
		||||
    my $statusref = $nodelisttab->getNodesAttribs(\@nodes, ['status']);
 | 
			
		||||
 | 
			
		||||
    my %rsp = ();
 | 
			
		||||
    my %rspentry = ();
 | 
			
		||||
    foreach (@nodes){
 | 
			
		||||
        if (! $_){
 | 
			
		||||
            next;
 | 
			
		||||
        }
 | 
			
		||||
        $rspentry{"node"} = $_;
 | 
			
		||||
        #TODO: get provisioning mac.
 | 
			
		||||
        $rspentry{"mac"} = $macsref->{$_}->[0]->{"mac"};
 | 
			
		||||
 | 
			
		||||
        if ($statusref->{$_}->[0]){
 | 
			
		||||
            $rspentry{"status"} = $statusref->{$_}->[0];
 | 
			
		||||
        } else{
 | 
			
		||||
            $rspentry{"status"} = "defined";
 | 
			
		||||
        }
 | 
			
		||||
        $callback->(\%rspentry);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  findme
 | 
			
		||||
 | 
			
		||||
    Description : The default interface for node discovery. 
 | 
			
		||||
                  We must implement this method so that 
 | 
			
		||||
                  PCM nodes's findme request can be answered 
 | 
			
		||||
                  while PCM discovery is running.
 | 
			
		||||
    Arguments   : N/A
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub findme{
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]PCM discover: Start.\n");
 | 
			
		||||
    # Read DB to confirm the discover is started. 
 | 
			
		||||
    my @sitevalues = xCAT::TableUtils->get_site_attribute("__PCMDiscover");
 | 
			
		||||
    if (! @sitevalues){
 | 
			
		||||
        setrsp_errormsg("PCM node discovery not started yet.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # We store node profiles in site table, key is "__PCMDiscover"
 | 
			
		||||
    my @profilerecords = split(',', $sitevalues[0]);
 | 
			
		||||
    foreach (@profilerecords){
 | 
			
		||||
        if ($_){
 | 
			
		||||
            my ($profilename, $profilevalue) = split(':', $_);
 | 
			
		||||
            if ($profilename and $profilevalue){
 | 
			
		||||
                $args_dict{$profilename} = $profilevalue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Get database records: all hostnames, all ips, all racks...
 | 
			
		||||
    # To improve performance, we should initalize a daemon later??
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]PCM discover: Getting database records.\n");
 | 
			
		||||
    my $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('nodelist', 'node');
 | 
			
		||||
    %allhostnames = %$recordsref;
 | 
			
		||||
    $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('ipmi', 'bmc');
 | 
			
		||||
    %allbmcips = %$recordsref;
 | 
			
		||||
    $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('mac', 'mac');
 | 
			
		||||
    %allmacs = %$recordsref;
 | 
			
		||||
    foreach (keys %allmacs){
 | 
			
		||||
        my @hostentries = split(/\|/, $_);
 | 
			
		||||
        foreach my $hostandmac ( @hostentries){
 | 
			
		||||
            my ($macstr, $machostname) = split("!", $hostandmac);
 | 
			
		||||
            $allmacs{$macstr} = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('hosts', 'ip');
 | 
			
		||||
    %allinstallips = %$recordsref;
 | 
			
		||||
    $recordsref = xCAT::NetworkUtils->get_all_nicips(1);
 | 
			
		||||
    %allips = %$recordsref;
 | 
			
		||||
    # Merge all BMC IPs and install IPs into allips.
 | 
			
		||||
    %allips = (%allips, %allbmcips, %allinstallips);
 | 
			
		||||
 | 
			
		||||
    #$recordsref = xCAT::PCMNodeMgmtUtils->get_allnode_singleattrib_hash('rack', 'rackname');
 | 
			
		||||
    #%allracks = %$recordsref;
 | 
			
		||||
    %allracks = ();
 | 
			
		||||
    $recordsref =  xCAT::PCMNodeMgmtUtils->get_all_chassis(1);
 | 
			
		||||
    %allchassis = %$recordsref;
 | 
			
		||||
 | 
			
		||||
    my @enabledparams = ('networkprofile', 'hardwareprofile', 'imageprofile', 'hostnameformat', 'rack', 'chassis', 'u', 'height', 'rank');
 | 
			
		||||
    foreach my $argname (keys %args_dict){
 | 
			
		||||
        if (! grep{ $_ eq $argname} @enabledparams){
 | 
			
		||||
            setrsp_errormsg("Illegal attribute $argname specified.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    # mandatory arguments.
 | 
			
		||||
    foreach my $key ('networkprofile', 'imageprofile', 'hostnameformat'){
 | 
			
		||||
        if (! exists $args_dict{$key}){
 | 
			
		||||
            setrsp_errormsg("argument $key must be specified");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # set default value for rack, startunit and height if not specified.
 | 
			
		||||
    if (exists $args_dict{'rack'}){
 | 
			
		||||
        if (! exists $allracks{$args_dict{'rack'}}){
 | 
			
		||||
            setrsp_errormsg("Specified rack $args_dict{'rack'} not defined");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }else{
 | 
			
		||||
        # set default rack.
 | 
			
		||||
        #TODO : how to set default rack.
 | 
			
		||||
    }
 | 
			
		||||
    if (!exists $args_dict{'u'}){
 | 
			
		||||
        $args_dict{'u'} = 1;
 | 
			
		||||
    }
 | 
			
		||||
    if (!exists $args_dict{'height'}){
 | 
			
		||||
        $args_dict{'height'} = 1;
 | 
			
		||||
    }
 | 
			
		||||
    # chassis jdugement.
 | 
			
		||||
    if (exists $args_dict{'chassis'}){
 | 
			
		||||
        if (! exists $allchassis{$args_dict{'chassis'}}){
 | 
			
		||||
            setrsp_errormsg("Specified chassis $args_dict{'chassis'} not defined");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Get discovered client IP and MAC
 | 
			
		||||
    my $ip = $request->{'_xcat_clientip'};
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]PCM discover: _xcat_clientip is $ip.\n");
 | 
			
		||||
    my $mac = '';
 | 
			
		||||
    my $arptable = `/sbin/arp -n`;
 | 
			
		||||
    my @arpents = split /\n/,$arptable;
 | 
			
		||||
    foreach  (@arpents) {
 | 
			
		||||
        if (m/^($ip)\s+\S+\s+(\S+)\s/) {
 | 
			
		||||
            $mac=$2;
 | 
			
		||||
            last;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (! $mac){
 | 
			
		||||
        setrsp_errormsg("[PCM nodes mgmt]PCM discover: Can not get mac address of this node.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]PCM discover: mac is $mac.\n");
 | 
			
		||||
    if ( exists $allmacs{$mac}){
 | 
			
		||||
        setrsp_errormsg("Discovered MAC $mac already exists in database.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Assign TMPHOSTS9999 as a temporary hostname, in parse_hsots_string, 
 | 
			
		||||
    # it will detect this and arrange a real hostname for it.
 | 
			
		||||
    my $raw_hostinfo_str = "TMPHOSTS9999:\n  mac=$mac\n";
 | 
			
		||||
    # Append rack, chassis, unit, height into host info string.
 | 
			
		||||
    foreach my $key ('rack', 'chassis', 'u', 'height'){
 | 
			
		||||
        if(exists($args_dict{$key})){
 | 
			
		||||
            $raw_hostinfo_str .= "  $key=$args_dict{$key}\n";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    my ($hostinfo_dict_ref, $invalid_records_ref) = parse_hosts_string($raw_hostinfo_str);
 | 
			
		||||
    my %hostinfo_dict = %$hostinfo_dict_ref;
 | 
			
		||||
    # Create the real hostinfo string in stanza file format.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]PCM discover: Generating new hostinfo string.\n");
 | 
			
		||||
    my ($retcode_gen, $retstr_gen) = gen_new_hostinfo_string($hostinfo_dict_ref);
 | 
			
		||||
    unless ($retcode_gen){
 | 
			
		||||
        setrsp_errormsg($retstr_gen);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # call mkdef to create hosts and then call nodemgmt for node management plugins.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call mkdef to create pcm nodes.\n");
 | 
			
		||||
    my $retref = xCAT::Utils->runxcmd({command=>["mkdef"], stdin=>[$retstr_gen], arg=>['-z']}, $request_command, 0, 1);
 | 
			
		||||
    # increase unit automatically.
 | 
			
		||||
    $args_dict{'u'} = $args_dict{'u'} + $args_dict{'height'};
 | 
			
		||||
 | 
			
		||||
    my @nodelist = keys %hostinfo_dict;
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call nodemgmt plugins.\n");
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_add"], node=>\@nodelist}, $request_command, 0, 1);
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd({command=>["kitcmd_nodemgmt_finished"], node=>\@nodelist}, $request_command, 0, 1);
 | 
			
		||||
 | 
			
		||||
    # call discover to notify client.
 | 
			
		||||
    xCAT::MsgUtils->message('S', "[PCM nodes mgmt]call discovered request.\n");
 | 
			
		||||
    $request->{"command"} = ["discovered"];
 | 
			
		||||
    $request->{"node"} = \@nodelist;
 | 
			
		||||
    $retref = xCAT::Utils->runxcmd($request, $request_command, 0, 1);
 | 
			
		||||
 | 
			
		||||
    # Set discovered flag.
 | 
			
		||||
    my $nodegroupstr = $hostinfo_dict{$nodelist[0]}{"groups"};
 | 
			
		||||
    my $nodelstab = xCAT::Table->new('nodelist',-create=>1);
 | 
			
		||||
    $nodelstab->setNodeAttribs($nodelist[0],{groups=>$nodegroupstr.",__PCMDiscover"});
 | 
			
		||||
    $nodelstab->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  replace_item_in_array
 | 
			
		||||
 | 
			
		||||
    Description : Replace an item in a list with new value. This item should match specified pattern.
 | 
			
		||||
@@ -528,9 +872,7 @@ sub parse_hosts_string{
 | 
			
		||||
    my %hostinfo_dict;
 | 
			
		||||
    my @invalid_records;
 | 
			
		||||
 | 
			
		||||
    my $nicstab = xCAT::Table->new('nics');
 | 
			
		||||
    my $nodehashref = $nicstab->getNodeAttribs($args_dict{'networkprofile'}, ['hostnameformat']);
 | 
			
		||||
    my $nameformat = $nodehashref->{'hostnameformat'};
 | 
			
		||||
    my $nameformat = $args_dict{'hostnameformat'};
 | 
			
		||||
 | 
			
		||||
    my $nameformattype = xCAT::PCMNodeMgmtUtils->get_hostname_format_type($nameformat);
 | 
			
		||||
    my %freehostnames;
 | 
			
		||||
@@ -580,7 +922,11 @@ sub parse_hosts_string{
 | 
			
		||||
 | 
			
		||||
            # Generate hostnames based on numric hostname format.
 | 
			
		||||
            if (! exists $freehostnames{$numricformat}){
 | 
			
		||||
                $freehostnames{$numricformat} = xCAT::PCMNodeMgmtUtils->genhosts_with_numric_tmpl($numricformat);
 | 
			
		||||
                my $rank = 0;
 | 
			
		||||
                if (exists($args_dict{'rank'})){
 | 
			
		||||
                    $rank = $args_dict{'rank'};
 | 
			
		||||
                }
 | 
			
		||||
                $freehostnames{$numricformat} = xCAT::PCMNodeMgmtUtils->genhosts_with_numric_tmpl($numricformat, $rank);
 | 
			
		||||
            }
 | 
			
		||||
            my $hostnamelistref = $freehostnames{$numricformat};
 | 
			
		||||
            my $nexthostname = shift @$hostnamelistref;
 | 
			
		||||
@@ -651,19 +997,28 @@ sub validate_node_entry{
 | 
			
		||||
        }elsif ($_ eq "switch"){
 | 
			
		||||
            #TODO: xCAT switch discovery enhance: verify whether switch exists.
 | 
			
		||||
        }elsif ($_ eq "port"){
 | 
			
		||||
            #TODO: xCAT switch discovery enhance: verify whether port exists.
 | 
			
		||||
        }elsif ($_ eq "rack"){
 | 
			
		||||
            if (not exists $allracks{$node_entry{$_}}){
 | 
			
		||||
                return "Specified rack $node_entry{$_} not defined";
 | 
			
		||||
            }
 | 
			
		||||
            # rack must be specified with chassis or unit + height.
 | 
			
		||||
            if (exists $node_entry{"chassis"}){
 | 
			
		||||
            } elsif (exists $node_entry{"height"} and exists $node_entry{"u"}){
 | 
			
		||||
            } else {
 | 
			
		||||
                return "Rack must be specified together with chassis or height + u ";
 | 
			
		||||
            }
 | 
			
		||||
        }elsif ($_ eq "chassis"){
 | 
			
		||||
            if (not exists $allchassis{$node_entry{$_}}){
 | 
			
		||||
                return "Specified chassis $node_entry{$_} not defined";
 | 
			
		||||
            }
 | 
			
		||||
        }elsif ($_ eq "unit"){
 | 
			
		||||
            # Chassis must not be specified with unit and height.
 | 
			
		||||
            if (exists $node_entry{"height"} and exists $node_entry{"u"}){
 | 
			
		||||
                return "Chassis should not be specified together with height + u";
 | 
			
		||||
            }
 | 
			
		||||
        }elsif ($_ eq "u"){
 | 
			
		||||
            # Not a valid number.
 | 
			
		||||
            if (!($node_entry{$_} =~ /^\d+$/)){
 | 
			
		||||
                return "Specified unit $node_entry{$_} is a invalid number";
 | 
			
		||||
                return "Specified u $node_entry{$_} is a invalid number";
 | 
			
		||||
            }
 | 
			
		||||
        }elsif ($_ eq "height"){
 | 
			
		||||
            # Not a valid number.
 | 
			
		||||
@@ -674,15 +1029,6 @@ sub validate_node_entry{
 | 
			
		||||
           return "Invalid attribute $_ specified";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    # For blades, don't support specify unit and height.
 | 
			
		||||
    if(exists $node_entry{"chassis"} ){
 | 
			
		||||
        if(exists $node_entry{"unit"}){
 | 
			
		||||
            return "Can not specify 'unit' together with 'chassis'";
 | 
			
		||||
        }
 | 
			
		||||
        if(exists $node_entry{"height"}){
 | 
			
		||||
            return "can not specify 'height' together with 'chassis'";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    # push hostinfo into global dicts.
 | 
			
		||||
    $allhostnames{$node_name} = 0;
 | 
			
		||||
    return undef;
 | 
			
		||||
@@ -706,6 +1052,7 @@ sub setrsp_invalidrecords
 | 
			
		||||
    my $master=xCAT::TableUtils->get_site_Master();
 | 
			
		||||
    
 | 
			
		||||
    # The total number of invalid records.
 | 
			
		||||
    $rsp->{error} = "Some error records detected";
 | 
			
		||||
    $rsp->{invalid_records_num} = scalar @$recordsref;
 | 
			
		||||
 | 
			
		||||
    # We write details of invalid records into a file.
 | 
			
		||||
@@ -740,6 +1087,26 @@ sub setrsp_errormsg
 | 
			
		||||
    $callback->($rsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  setrsp_infostr
 | 
			
		||||
    
 | 
			
		||||
    Description : Set response for a info string.
 | 
			
		||||
    Arguments   : infostr - The info string..
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
sub setrsp_infostr
 | 
			
		||||
{
 | 
			
		||||
    my $infostr = shift;
 | 
			
		||||
    my $rsp;
 | 
			
		||||
    xCAT::MsgUtils->message('S', "$infostr\n");
 | 
			
		||||
    $rsp->{info}->[0] = $infostr;
 | 
			
		||||
    $callback->($rsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
=head3  setrsp_success
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user