mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	`rmdef` command do not help clean up the recousrces that related to the node when removing the node. this is a technical debt. This patch is only a work around to add -C|--cleanup option to help remove the entries in goconserver.
		
			
				
	
	
		
			4723 lines
		
	
	
		
			160 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4723 lines
		
	
	
		
			160 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl -w
 | |
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| #####################################################
 | |
| #
 | |
| #  xCAT plugin package to handle commands that manage the xCAT object
 | |
| #     definitions
 | |
| #
 | |
| #####################################################
 | |
| 
 | |
| package xCAT_plugin::DBobjectdefs;
 | |
| 
 | |
| BEGIN
 | |
| {
 | |
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
| }
 | |
| use xCAT::NodeRange;
 | |
| use xCAT::Schema;
 | |
| use xCAT::DBobjUtils;
 | |
| use Data::Dumper;
 | |
| use Getopt::Long;
 | |
| use xCAT::MsgUtils;
 | |
| use xCAT::Utils;
 | |
| use xCAT::SvrUtils;
 | |
| use xCAT::NetworkUtils;
 | |
| use File::Find;
 | |
| use strict;
 | |
| 
 | |
| # options can be bundled up like -vV
 | |
| Getopt::Long::Configure("bundling");
 | |
| $Getopt::Long::ignorecase = 0;
 | |
| 
 | |
| #
 | |
| # Globals
 | |
| #
 | |
| 
 | |
| # %::CLIATTRS;      # attr=values provided on the command line
 | |
| #%::FILEATTRS;     # attr=values provided in an input file
 | |
| #%::FINALATTRS;    # final set of attr=values that are used to set
 | |
| #    the object
 | |
| 
 | |
| #%::objfilehash;   #  hash of objects/types based of "-f" option
 | |
| #    (list in file)
 | |
| 
 | |
| #%::WhereHash;     # hash of attr=val from "-w" option
 | |
| #@::AttrList;      # list of attrs from "-i" option
 | |
| #%::NicsAttrHash;  # hash of nics attributes specified with "-i" option
 | |
| # e.g. $::NicsAttrHash{'nicips'} = ("eth0","eth1");
 | |
| 
 | |
| # object type lists
 | |
| #@::clobjtypes;      # list of object types derived from the command line.
 | |
| #@::fileobjtypes;    # list of object types from input file ("-x" or "-z")
 | |
| 
 | |
| #  object name lists
 | |
| #@::clobjnames;      # list of object names derived from the command line
 | |
| #@::fileobjnames;    # list of object names from an input file
 | |
| #@::objfilelist;     # list of object names from the "-f" option
 | |
| #@::allobjnames;     # combined list
 | |
| 
 | |
| my $doreq;
 | |
| 
 | |
| #@::noderange;       # list of nodes derived from command line
 | |
| 
 | |
| #------------------------------------------------------------------------------
 | |
| 
 | |
| =head1    DBobjectdefs
 | |
| 
 | |
| This program module file supports the management of the xCAT data object
 | |
| definitions.
 | |
| 
 | |
| Supported xCAT data object commands:
 | |
|      mkdef - create xCAT data object definitions.
 | |
|      lsdef - list xCAT data object definitions.
 | |
|      chdef - change xCAT data object definitions.
 | |
|      rmdef - remove xCAT data object definitions.
 | |
| 
 | |
| If adding to this file, please take a moment to ensure that:
 | |
| 
 | |
|     1. Your contrib has a readable pod header describing the purpose and use of
 | |
|       the subroutine.
 | |
| 
 | |
|     2. Your contrib is under the correct heading and is in alphabetical order
 | |
|     under that heading.
 | |
| 
 | |
|     3. You have run tidypod on your this file and saved the html file
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #------------------------------------------------------------------------------
 | |
| 
 | |
| =head2    xCAT data object definition support
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #------------------------------------------------------------------------------
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  handled_commands
 | |
| 
 | |
|         Return a list of commands handled by this plugin
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub handled_commands
 | |
| {
 | |
|     return {
 | |
|         mkdef => "DBobjectdefs",
 | |
|         lsdef => "DBobjectdefs",
 | |
|         chdef => "DBobjectdefs",
 | |
|         rmdef => "DBobjectdefs"
 | |
|     };
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3   process_request
 | |
| 
 | |
|         Check for xCAT command and call the appropriate subroutine.
 | |
| 
 | |
|         Arguments:
 | |
| 
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub process_request
 | |
| {
 | |
| 
 | |
|     $::request  = shift;
 | |
|     $::callback = shift;
 | |
|     $doreq = shift;
 | |
| 
 | |
|     my $ret;
 | |
|     my $msg;
 | |
| 
 | |
|     &initialize_variables();
 | |
| 
 | |
|     # globals used by all subroutines.
 | |
|     $::command  = $::request->{command}->[0];
 | |
|     $::args     = $::request->{arg};
 | |
|     $::filedata = $::request->{stdin}->[0];
 | |
| 
 | |
|     # figure out which cmd and call the subroutine to process
 | |
|     if ($::command eq "mkdef")
 | |
|     {
 | |
|         ($ret, $msg) = &defmk;
 | |
|     }
 | |
|     elsif ($::command eq "lsdef")
 | |
|     {
 | |
|         ($ret, $msg) = &defls;
 | |
|     }
 | |
|     elsif ($::command eq "chdef")
 | |
|     {
 | |
|         ($ret, $msg) = &defch;
 | |
|     }
 | |
|     elsif ($::command eq "rmdef")
 | |
|     {
 | |
|         ($ret, $msg) = &defrm;
 | |
|     }
 | |
| 
 | |
|     my $rsp;
 | |
|     if ($msg)
 | |
|     {
 | |
|         $rsp->{data}->[0] = $msg;
 | |
|     }
 | |
|     if ($ret > 0) {
 | |
|         $rsp->{errorcode}->[0] = $ret;
 | |
|     }
 | |
|     $::callback->($rsp);
 | |
| }
 | |
| 
 | |
| sub parse_attr_for_osimage {
 | |
|     my $command   = shift;
 | |
|     my $attr_hash = shift;
 | |
|     if (!exists($attr_hash->{profile}) or !exists($attr_hash->{provmethod})) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The profile and provmethod are all need to be specified.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return -1;
 | |
|     } else {
 | |
|         my $tmp_profile    = $attr_hash->{profile};
 | |
|         my $tmp_provmethod = $attr_hash->{provmethod};
 | |
|         if ($tmp_provmethod !~ /install|netboot|statelite/) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The provmethod: $tmp_provmethod is incorrect.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return -1;
 | |
|         }
 | |
|         my ($tmp_imagetype, $tmp_arch, $tmp_osname, $tmp_ostype, $tmp_osvers);
 | |
|         if (!exists($attr_hash->{osvers})) {
 | |
|             $tmp_osvers = xCAT::Utils->osver("all");
 | |
|             $tmp_osvers =~ s/,//;
 | |
|             $attr_hash->{osvers} = $tmp_osvers;
 | |
|         } else {
 | |
|             $tmp_osvers = $attr_hash->{osvers};
 | |
|         }
 | |
| 
 | |
|         if (!exists($attr_hash->{osarch})) {
 | |
|             $tmp_arch = `uname -m`;
 | |
|             chomp($tmp_arch);
 | |
|             $tmp_arch = "x86" if ($tmp_arch =~ /i.86$/);
 | |
|             $attr_hash->{osarch} = $tmp_arch;
 | |
|         } else {
 | |
|             $tmp_arch = $attr_hash->{osarch};
 | |
|         }
 | |
| 
 | |
|         #for ubuntu,the the arch attribute "ppc64le" should be modified to "ppc64el"
 | |
|         if (($tmp_osvers =~ /^ubuntu/i) && ($tmp_arch =~ /^ppc64le/i)) {
 | |
|             $tmp_arch = "ppc64el";
 | |
|             $attr_hash->{osarch} = "ppc64el";
 | |
|         }
 | |
| 
 | |
|         $tmp_osname    = $tmp_osvers;
 | |
|         $tmp_ostype    = "Linux";       #like Linux, Windows
 | |
|         $tmp_imagetype = "linux";
 | |
|         my $prov_dir = ($tmp_provmethod eq "install") ? "install" : "netboot";
 | |
|         if (($tmp_osvers =~ /^win/) || ($tmp_osvers =~ /^imagex/)) {
 | |
|             $tmp_osname    = "windows";
 | |
|             $tmp_ostype    = "Windows";
 | |
|             $tmp_imagetype = "windows";
 | |
|         } elsif ($tmp_osvers =~ /^hyperv/) {
 | |
|             $tmp_osname    = "hyperv";
 | |
|             $tmp_ostype    = "Windows";
 | |
|             $tmp_imagetype = "windows";
 | |
|         } else {
 | |
|             until (-r "$::XCATROOT/share/xcat/$prov_dir/$tmp_osname/" or not $tmp_osname) {
 | |
|                 chop($tmp_osname);
 | |
|             }
 | |
|             unless ($tmp_osname) {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Unable to find $::XCATROOT/share/xcat/$prov_dir directory for $tmp_osvers.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return -1;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #for rhels5.1  genos=rhel5
 | |
|         my $tmp_genos = $tmp_osvers;
 | |
|         $tmp_genos =~ s/\..*//;
 | |
|         if ($tmp_genos =~ /rh.*s(\d*)/) {
 | |
|             $tmp_genos = "rhel$1";
 | |
|         }
 | |
|         if (exists($attr_hash->{imagetype}) && ($attr_hash->{imagetype} !~ /^$tmp_imagetype/i)) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The input imagetype:$attr_hash->{imagetype} not match $tmp_imagetype.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return -1;
 | |
|         } elsif (!exists($attr_hash->{imagetype})) {
 | |
|             $attr_hash->{imagetype} = $tmp_imagetype;
 | |
|         }
 | |
|         if (exists($attr_hash->{osname}) && ($attr_hash->{osname} !~ /^$tmp_ostype/i)) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The input osname:$attr_hash->{osname} not match $tmp_ostype.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return -1;
 | |
|         } elsif (!exists($attr_hash->{osname})) {
 | |
|             $attr_hash->{osname} = $tmp_ostype;
 | |
|         }
 | |
| 
 | |
|         #if (!exists($attr_hash->{osdistroname})) {
 | |
|         $attr_hash->{osdistroname} = "$tmp_osvers-$tmp_arch";
 | |
| 
 | |
|         #}
 | |
|         if (!exists($attr_hash->{synclists}) || $command eq "chdef") {
 | |
|             my $tmp_synclist = xCAT::SvrUtils->getsynclistfile(undef, $tmp_osvers, $tmp_arch, $tmp_profile, "netboot");
 | |
|             if ($tmp_synclist) {
 | |
|                 $attr_hash->{synclists} = $tmp_synclist;
 | |
|             }
 | |
|         }
 | |
|         my @non_win_attr = qw(pkglist pkgdir otherpkglist otherpkgdir exlist postinstall rootimgdir template);
 | |
|         if ($tmp_osname =~ /^win/) {
 | |
|             my @invalid_attr = ();
 | |
|             foreach (@non_win_attr) {
 | |
|                 if (exists($attr_hash->{$_})) {
 | |
|                     push @invalid_attr, $_;
 | |
|                 }
 | |
|             }
 | |
|             if ($#invalid_attr) {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "$tmp_osvers can not work with @invalid_attr.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return -1;
 | |
|             }
 | |
|         } else {
 | |
|             my $installroot = xCAT::TableUtils->getInstallDir();
 | |
|             my @installdirs = xCAT::TableUtils->get_site_attribute("installdir");
 | |
|             my $tmp = $installdirs[0];
 | |
|             if (defined($tmp)) {
 | |
|                 $installroot = $tmp;
 | |
|             }
 | |
|             my $cuspath = "$installroot/custom/$prov_dir/$tmp_osname";
 | |
|             my $defpath = "$::XCATROOT/share/xcat/$prov_dir/$tmp_osname";
 | |
|             if ($tmp_provmethod eq "install") {
 | |
|                 $attr_hash->{exlist}      = '';
 | |
|                 $attr_hash->{postinstall} = '';
 | |
|                 $attr_hash->{rootimgdir}  = '';
 | |
|                 if ((!exists($attr_hash->{template})) || ($command eq "chdef")) {
 | |
|                     my $tmp_tmplfile = xCAT::SvrUtils->get_tmpl_file_name($cuspath, $tmp_profile, $tmp_osvers, $tmp_arch, $tmp_genos);
 | |
|                     if (!$tmp_tmplfile) {
 | |
|                         $tmp_tmplfile = xCAT::SvrUtils->get_tmpl_file_name($defpath, $tmp_profile, $tmp_osvers, $tmp_arch, $tmp_genos);
 | |
|                     }
 | |
|                     if ($tmp_tmplfile) {
 | |
|                         $attr_hash->{template} = $tmp_tmplfile;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             if ($tmp_provmethod ne "install") {
 | |
|                 $attr_hash->{template} = '';
 | |
|                 if (!exists($attr_hash->{exlist})) {
 | |
|                     my $tmp_exlist = xCAT::SvrUtils->get_exlist_file_name($cuspath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                     if (!$tmp_exlist) {
 | |
|                         $tmp_exlist = xCAT::SvrUtils->get_exlist_file_name($defpath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                     }
 | |
|                     if ($tmp_exlist) {
 | |
|                         $attr_hash->{exlist} = $tmp_exlist;
 | |
|                     }
 | |
|                 }
 | |
|                 if (!exists($attr_hash->{postinstall})) {
 | |
|                     my $tmp_post = xCAT::SvrUtils->get_postinstall_file_name($cuspath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                     if (!$tmp_post) {
 | |
|                         $tmp_post = xCAT::SvrUtils->get_postinstall_file_name($defpath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                     }
 | |
|                     if ($tmp_post) {
 | |
|                         $attr_hash->{postinstall} = $tmp_post;
 | |
|                     }
 | |
|                 }
 | |
|                 if (!exists($attr_hash->{rootimgdir})) {
 | |
|                     $attr_hash->{rootimgdir} = "$installroot/netboot/$tmp_osvers/$tmp_arch/$tmp_profile";
 | |
|                 }
 | |
|             }
 | |
|             if (!exists($attr_hash->{pkglist})) {
 | |
|                 my $tmp_pkglist = xCAT::SvrUtils->get_pkglist_file_name($cuspath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                 if (!$tmp_pkglist) {
 | |
|                     $tmp_pkglist = xCAT::SvrUtils->get_pkglist_file_name($defpath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                 }
 | |
|                 if ($tmp_pkglist) {
 | |
|                     $attr_hash->{pkglist} = $tmp_pkglist;
 | |
|                 }
 | |
|             }
 | |
|             if (!exists($attr_hash->{otherpkglist})) {
 | |
|                 my $tmp_othpkglist = xCAT::SvrUtils->get_otherpkgs_pkglist_file_name($cuspath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                 if (!$tmp_othpkglist) {
 | |
|                     $tmp_othpkglist = xCAT::SvrUtils->get_otherpkgs_pkglist_file_name($defpath, $tmp_profile, $tmp_osvers, $tmp_arch);
 | |
|                 }
 | |
|                 if ($tmp_othpkglist) {
 | |
|                     $attr_hash->{otherpkglist} = $tmp_othpkglist;
 | |
|                 }
 | |
|             }
 | |
|             if (!exists($attr_hash->{otherpkgdir})) {
 | |
|                 $attr_hash->{otherpkgdir} = "$installroot/post/otherpkgs/$tmp_osvers/$tmp_arch";
 | |
|             }
 | |
|             if (!exists($attr_hash->{pkgdir})) {
 | |
|                 $attr_hash->{pkgdir} = "$installroot/$tmp_osvers/$tmp_arch";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3   processArgs
 | |
| 
 | |
|         Process the command line. Covers all four commands.
 | |
| 
 | |
|         Also - Process any input files provided on cmd line.
 | |
| 
 | |
|         Arguments:
 | |
| 
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - just return
 | |
|                 2 - just print usage
 | |
|                 3 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub processArgs
 | |
| {
 | |
|     my $gotattrs = 0;
 | |
|     if (defined($::args) && @{$::args}) {
 | |
|         @ARGV = @{$::args};
 | |
|     } else {
 | |
|         if ($::command eq "lsdef") {
 | |
|             push @ARGV, "-t";
 | |
|             push @ARGV, "node";
 | |
|             push @ARGV, "-s";
 | |
|         } else {
 | |
|             return 2;
 | |
|         }
 | |
|     }
 | |
|     if (defined($::args) && @{$::args}) {
 | |
|         if (scalar(@{$::args}) == 1 and $::args->[0] eq '-S')
 | |
|         {
 | |
|             if ($::command eq "lsdef") {
 | |
|                 push @ARGV, "-t";
 | |
|                 push @ARGV, "node";
 | |
|                 push @ARGV, "-s";
 | |
|             } else {
 | |
|                 return 2;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($::command eq "lsdef") {
 | |
|         if (scalar(@ARGV) == 2 && (($ARGV[0] eq "-l" && $ARGV[1] eq "-S") || ($ARGV[0] eq "-S" && $ARGV[1] eq "-l"))) {
 | |
|             push @ARGV, "-t";
 | |
|             push @ARGV, "node";
 | |
|         }
 | |
|     }
 | |
|     if ($::command eq "lsdef") {
 | |
|         if (scalar(@ARGV) == 1 && $ARGV[0] eq "-l") {
 | |
|             push @ARGV, "-t";
 | |
|             push @ARGV, "node";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (scalar(@ARGV) <= 0) {
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # clean up all the global variables for each options
 | |
|     # so def command can be called multiple times in one process
 | |
|     undef $::opt_a;
 | |
|     undef $::opt_c;
 | |
|     undef $::opt_d;
 | |
|     undef $::opt_a;
 | |
|     undef $::opt_c;
 | |
|     undef $::opt_d;
 | |
|     undef $::opt_f;
 | |
|     undef $::opt_i;
 | |
|     undef $::opt_h;
 | |
|     undef $::opt_l;
 | |
|     undef $::opt_s;
 | |
|     undef $::opt_m;
 | |
|     undef $::opt_n;
 | |
|     undef $::opt_o;
 | |
|     undef $::opt_p;
 | |
|     undef $::opt_t;
 | |
|     undef $::opt_V;
 | |
|     undef $::opt_v;
 | |
|     undef $::opt_w;
 | |
|     undef $::opt_x;
 | |
|     undef $::opt_z;
 | |
|     undef $::opt_S;
 | |
|     undef $::opt_nc;
 | |
|     undef $::opt_osimg;
 | |
|     undef $::opt_nics;
 | |
|     undef $::opt_setattr;
 | |
|     undef $::opt_template;
 | |
|     undef $::opt_cleanup;
 | |
| 
 | |
|     # parse the options - include any option from all 4 cmds
 | |
|     Getopt::Long::Configure("no_pass_through");
 | |
|     if (
 | |
|         !GetOptions(
 | |
|             'all|a'      => \$::opt_a,
 | |
|             'compress|c' => \$::opt_c,
 | |
|             'dynamic|d'  => \$::opt_d,
 | |
|             'f|force'    => \$::opt_f,
 | |
|             'i=s'        => \$::opt_i,
 | |
|             'help|h|?'   => \$::opt_h,
 | |
|             'long|l'     => \$::opt_l,
 | |
|             'short|s'    => \$::opt_s,
 | |
|             'm|minus'    => \$::opt_m,
 | |
|             'n=s'        => \$::opt_n,
 | |
|             'o=s'        => \$::opt_o,
 | |
|             'p|plus'     => \$::opt_p,
 | |
|             't=s'        => \$::opt_t,
 | |
|             'verbose|V'  => \$::opt_V,
 | |
|             'version|v'  => \$::opt_v,
 | |
|             'w=s@'       => \$::opt_w,
 | |
|             'x|xml'      => \$::opt_x,
 | |
|             'z|stanza'   => \$::opt_z,
 | |
|             'nocache'    => \$::opt_nc,
 | |
|             'S'          => \$::opt_S,
 | |
|             'osimage'    => \$::opt_osimg,
 | |
|             'nics'       => \$::opt_nics,
 | |
|             'u'          => \$::opt_setattr,
 | |
|             'template:s' => \$::opt_template,
 | |
|             'C|cleanup'  => \$::opt_cleanup,
 | |
|         )
 | |
|       )
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Invalid option..";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     if (defined($::opt_setattr) && ($::command ne "chdef") && ($::command ne "mkdef")) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Option \'-u\' can not work with $::command.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     if (defined($::opt_cleanup) && ($::command ne "rmdef")) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Option \'-C\' can not be used with $::command.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     if (defined($::opt_setattr)) {
 | |
|         if (!$::opt_t && !$::filedata) {
 | |
|             $::opt_t = 'osimage';
 | |
|         } elsif ($::opt_t ne "osimage") {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Option \'-u\' only work for objtype \'osimage\'.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 2;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # -t node is the default value
 | |
|     if (!$::opt_t && !$::opt_a && !$::opt_h && ($::command eq "lsdef"))
 | |
|     {
 | |
|         $::opt_t = 'node';
 | |
|     }
 | |
| 
 | |
|     # Initialize some global arrays in case this is being called twice in the same process.
 | |
|     # Currently only doing this when --nocache is specified, but i think it should be done all of the time.
 | |
|     if ($::opt_nc) {
 | |
|         &initialize_variables();
 | |
|     }
 | |
| 
 | |
|     #  opt_x not yet supported
 | |
|     if ($::opt_x)
 | |
|     {
 | |
| 
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The \'-x\' (XML format) option is not yet implemented.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # -i and --osimage cannot be used together
 | |
|     if ($::opt_i && $::opt_osimg) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-i'\ and \'--osimage'\ cannot be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # -z and --osimage cannot be used together
 | |
|     if ($::opt_z && $::opt_osimg) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-z'\ and \'--osimage'\ cannot be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # -a and -t cannot be used together
 | |
|     if ($::opt_a && $::opt_t) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-a'\ and \'-t'\ cannot be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # -l and -s cannot be used together
 | |
|     if ($::opt_l && $::opt_s) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-l'\ and \'-s'\ cannot be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # -i and --nics cannot be used together
 | |
|     if ($::opt_nics && $::opt_i) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-i'\ and \'--nics'\ cannot be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # --nics is the equivalent of -i nicips,nichostnamesuffixes...
 | |
|     if ($::opt_nics) {
 | |
|         $::opt_i = "nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases,nicextraparams,nicdevices";
 | |
|     }
 | |
| 
 | |
|     # -i and -s cannot be used together
 | |
|     if ($::opt_i && $::opt_s) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-i'\ and \'-s'\ cannot be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # -c must be used together with -i
 | |
|     if ($::opt_c && !$::opt_i) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The flags \'-c'\ and \'-i'\ must be used together.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # check the new object name specified with -n
 | |
|     if ($::command eq "chdef" && $::opt_n && (!isobjnamevalid($::opt_n,$::opt_t))) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The new object name \'$::opt_n\' is not valid.Please refer to \"man xcatdb\" for the valid \"xCAT Object Name Format\" ";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     #"--template" can only be used with "mkdef" and "lsdef" command
 | |
|     if (defined $::opt_template && ($::command ne "mkdef" && $::command ne "lsdef")) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The option \'--template\' can not be used with \'$::command\'.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     #it is illegal to specify no object template for "mkdef --template",
 | |
|     if ($::command eq "mkdef" and defined $::opt_template and !$::opt_template) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "no object definition template specified for mkdef --template!";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     if ($::opt_template) {
 | |
| 
 | |
|         #for mkdef --template <object templates>, multiple template/nodes are illegal
 | |
|         if ($::opt_template =~ /,/ and $::command eq "mkdef") {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Only 1 template object definition should be specified for mkdef!";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 2;
 | |
|         }
 | |
| 
 | |
|         #when --template is specified,
 | |
|         #the piped stdin, such as "cat xx.stanza|mkdef -z -t node --template ...." is not supported
 | |
|         if ($::filedata) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The file input can not be used with --template option!";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 2;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (defined $::opt_template and ($::command eq "mkdef" or $::command eq "lsdef")) {
 | |
| 
 | |
|         #all the xCAT shipped object definition templates are installed
 | |
|         #under directory /opt/xcat/share/xcat/templates/objects/<object-type>/
 | |
|         my $objtmpldir = "$::XCATROOT/share/xcat/templates/objects/";
 | |
| 
 | |
|         #the path list to search the object definition templates
 | |
|         #for specified object types,the path is like /opt/xcat/share/xcat/templates/objects/<object-type>/
 | |
|         #for "-a" option, the path is /opt/xcat/share/xcat/templates/objects/
 | |
|         my @tmpldirlist;
 | |
|         if ($::command eq "lsdef") {
 | |
|             if (!$::opt_a) {
 | |
|                 if ($::opt_t) {
 | |
|                     my @tmpltypelist = split(",", $::opt_t);
 | |
|                     foreach my $objtype (@tmpltypelist) {
 | |
|                         push(@tmpldirlist, $objtmpldir . $objtype);
 | |
|                     }
 | |
|                 }
 | |
|             } else {
 | |
| 
 | |
|                 #if "-a" is specified, read all the object templates
 | |
|                 #under /opt/xcat/share/xcat/templates/objects/
 | |
|                 push(@tmpldirlist, $objtmpldir);
 | |
|             }
 | |
|         } elsif ($::command eq "mkdef") {
 | |
|             if ($::opt_t) {
 | |
|                 push(@tmpldirlist, $objtmpldir . $::opt_t);
 | |
|             } else {
 | |
| 
 | |
|                 #if "-t" is not specified, take the object type as "node"
 | |
|                 push(@tmpldirlist, $objtmpldir . "node");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #walk through the path list and get all the object templates file content;
 | |
|         #for "lsdef -a --template" read all the content of template files
 | |
|         #under "/opt/xcat/share/xcat/templates/objects/";
 | |
|         #if "-a" is not specified, read the template files content
 | |
|         #under "/opt/xcat/share/xcat/templates/objects/<object type>"
 | |
|         my $objfiledata;
 | |
|         my $wanted = sub {
 | |
|             if (-f $_) {
 | |
|                 my $line;
 | |
|                 open(FH, $_);
 | |
|                 while ($line = <FH>) {
 | |
|                     $objfiledata .= $line;
 | |
|                 }
 | |
|                 close(FH)
 | |
|             }
 | |
|         };
 | |
|         find($wanted, @tmpldirlist);
 | |
| 
 | |
| 
 | |
|         #save the template definitions in global variable $::filedata
 | |
|         #for the later parse
 | |
|         $::filedata = $objfiledata;
 | |
|     }
 | |
| 
 | |
|     # can get object names in many ways - easier to keep track
 | |
|     $::objectsfrom_args = 0;
 | |
|     $::objectsfrom_opto = 0;
 | |
|     $::objectsfrom_optt = 0;
 | |
|     $::objectsfrom_opta = 0;
 | |
|     $::objectsfrom_nr   = 0;
 | |
|     $::objectsfrom_file = 0;
 | |
| 
 | |
|     #
 | |
|     # process @ARGV
 | |
|     #
 | |
| 
 | |
|     #  - put attr=val operands in ATTRS hash
 | |
|     my $noderangespace = 0;
 | |
|     while (my $a = shift(@ARGV))
 | |
|     {
 | |
| 
 | |
|         if (!($a =~ /=/))
 | |
|         {
 | |
| 
 | |
|             # can not have spaces in the noderange
 | |
|             if ($noderangespace)
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "noderange can not contain spaces.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 2;
 | |
|             }
 | |
|             $noderangespace++;
 | |
| 
 | |
|             # the first arg could be a noderange or a list of args
 | |
|             if (($::opt_t) && ($::opt_t ne 'node'))
 | |
|             {
 | |
| 
 | |
|                 # if we know the type isn't "node" then set the object list
 | |
|                 @::clobjnames       = split(',', $a);
 | |
|                 @::noderange        = @::clobjnames;
 | |
|                 $::objectsfrom_args = 1;
 | |
|             }
 | |
|             elsif (!$::opt_t || ($::opt_t eq 'node'))
 | |
|             {
 | |
| 
 | |
|                 # if the type was not provided or it is "node"
 | |
|                 #    then set noderange
 | |
|                 if (($::command ne 'mkdef') && ($a =~ m/^\//))
 | |
|                 {
 | |
|                     @::noderange = &noderange($a, 1); # Use the "verify" option to support regular expression
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     @::noderange = &noderange($a, 0); # mkdef could not spport regular expression
 | |
|                 }
 | |
|                 if (scalar(@::noderange) == 0)
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "No node in \'$a\', check the noderange syntax.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     return 3;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
|         else
 | |
|         {
 | |
| 
 | |
|             # if it has an "=" sign its an attr=val - we hope
 | |
|             #   - this will handle "attr= "
 | |
|             # The attribute itself might contain "space", like "nics.Local Connection Adapter 1" on windows
 | |
|             my ($attr, $value) = $a =~ /^\s*(.*?)\s*=\s*(\S*.*)$/;
 | |
|             if (!defined($attr) || !defined($value))
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Incorrect \'attr=val\' pair - $a.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 3;
 | |
|             }
 | |
| 
 | |
|             $gotattrs = 1;
 | |
| 
 | |
|             # put attr=val in hash
 | |
|             $::ATTRS{$attr} = $value;
 | |
| 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ((!$::opt_t || $::opt_t eq 'node') && ($::command eq 'chdef') && ($::opt_m || $::opt_p))
 | |
|     {
 | |
|         my $nicattrs = 0;
 | |
|         foreach my $kattr (keys %::ATTRS)
 | |
|         {
 | |
|             if ($kattr =~ /^nic\w+\..*$/)
 | |
|             {
 | |
|                 $nicattrs = 1;
 | |
|             }
 | |
|             last;
 | |
|         }
 | |
|         if ($nicattrs)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "chdef does not support to change the nic related attributes with -m or -p flag.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 3;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # Check arguments for rmdef command
 | |
|     # rmdef is very dangerous if wrong flag is specified
 | |
|     # it may cause all the objects to be deleted, check the flags
 | |
|     # for example: rmdef -t node -d, the user want to delete the node named "-d",
 | |
|     # but it will delete all the nodes!
 | |
|     # use -o instead
 | |
|     if ($::command eq 'rmdef')
 | |
|     {
 | |
|         if (defined($::opt_d) || defined($::opt_i) || defined($::opt_l)
 | |
|             || defined($::opt_m) || defined($::opt_p) || defined($::opt_w)
 | |
|             || defined($::opt_x) || defined($::opt_z) || defined($::opt_s))
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Invalid flag specified, see rmdef manpage for details.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 2;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # Option -h for Help
 | |
|     # if user specifies "-t" & "-h" they want a list of valid attrs
 | |
|     if (defined($::opt_h) && !defined($::opt_t))
 | |
|     {
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     # Option -v for version - do we need this???
 | |
|     if (defined($::opt_v))
 | |
|     {
 | |
|         my $rsp;
 | |
|         my $version = xCAT::Utils->Version();
 | |
|         push @{ $rsp->{data} }, "$::command - $version";
 | |
|         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         return 1;    # no usage - just exit
 | |
|     }
 | |
| 
 | |
|     # Option -V for verbose output
 | |
|     if (defined($::opt_V))
 | |
|     {
 | |
|         $::verbose = 1;
 | |
|         $::VERBOSE = 1;
 | |
|     } else {
 | |
|         $::verbose = 0;
 | |
|         $::VERBOSE = 0;
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     # process the input file or object definition template files - if provided
 | |
|     #
 | |
|     if ($::filedata)
 | |
|     {
 | |
| 
 | |
|         #parse the $::filedata and initialize the following global variables
 | |
|         # %::FILEATTRS        : a global hash with the strcture <node>=>{<attributes>=><values>}
 | |
|         # @::fileobjtypes     : a list of the object types in %::FILEATTRS
 | |
|         # @::fileobjnames     : a list of the object names in %::FILEATTRS
 | |
|         my $rc = xCAT::DBobjUtils->readFileInput($::filedata);
 | |
| 
 | |
|         if ($rc)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Could not process file input data.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             return 3;
 | |
|         }
 | |
| 
 | |
|         if ($::opt_template) {
 | |
| 
 | |
|             #some xCAT shipped object definition templates are specified
 | |
|             #like "lsdef/mkdef --template xxxx"
 | |
|             #filter out the keys(template name) which are not specified from %::FILEATTRS
 | |
|             my %tmpfileattr;
 | |
|             my @tmpfileobjtypes;
 | |
|             my @tmpfileobjnames;
 | |
|             my @tmplobjlist = split(",", $::opt_template);
 | |
|             foreach my $key (@tmplobjlist) {
 | |
|                 if (exists $::FILEATTRS{$key}) {
 | |
|                     $tmpfileattr{$key} = \%{ $::FILEATTRS{$key} };
 | |
|                     push(@tmpfileobjnames, $key);
 | |
|                     push(@tmpfileobjtypes, $tmpfileattr{$key}{objtype});
 | |
|                 } else {
 | |
|                     if ($::command eq "lsdef") {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Could not find $key in xCAT templates.";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                         return 3;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (@tmpfileobjnames) {
 | |
| 
 | |
|                 #flag: some template object definitions are parsed from $::filedata
 | |
|                 %::FILEATTRS        = %tmpfileattr;
 | |
|                 @::fileobjtypes     = @tmpfileobjtypes;
 | |
|                 @::fileobjnames     = @tmpfileobjnames;
 | |
|                 $::objectsfrom_file = 1;
 | |
|             } else {
 | |
| 
 | |
|                 #the specified template can not be found in the pared $::filedata
 | |
|                 %::FILEATTRS    = ();
 | |
|                 @::fileobjtypes = ();
 | |
|                 @::fileobjnames = ();
 | |
|             }
 | |
|         } else {
 | |
| 
 | |
|             #flag: some object definitions are parsed from $::filedata
 | |
|             $::objectsfrom_file = 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     #  determine the object types
 | |
|     #
 | |
| 
 | |
|     # could have comma seperated list of types
 | |
|     if ($::opt_t)
 | |
|     {
 | |
|         my @tmptypes;
 | |
| 
 | |
|         if ($::opt_t =~ /,/)
 | |
|         {
 | |
| 
 | |
|             # can't have mult types when using attr=val
 | |
|             if ($gotattrs)
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Cannot combine multiple types with \'att=val\' pairs on the command line.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 3;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 @tmptypes = split(',', $::opt_t);
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             push(@tmptypes, $::opt_t);
 | |
|         }
 | |
| 
 | |
|         # check for valid types
 | |
|         my @xdeftypes;
 | |
|         foreach my $k (keys %{xCAT::Schema::defspec})
 | |
|         {
 | |
|             push(@xdeftypes, $k);
 | |
|         }
 | |
| 
 | |
|         foreach my $t (@tmptypes)
 | |
|         {
 | |
|             if (!grep(/^$t$/, @xdeftypes))
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "\nType \'$t\' is not a valid xCAT object type.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 3;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 chomp $t;
 | |
|                 push(@::clobjtypes, $t);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # must have object type(s) - default if not provided
 | |
|     if (!@::clobjtypes && (!@::fileobjtypes || (@::fileobjtypes && defined $::opt_template)) && !$::opt_a && !$::opt_t)
 | |
|     {
 | |
|         # make the default type = 'node' if not specified
 | |
|         push(@::clobjtypes, 'node');
 | |
| 
 | |
|         my $rsp;
 | |
|         if (!$::opt_z && !$::opt_x) {
 | |
| 
 | |
|             # don't want this msg in stanza or xml output
 | |
|             #$rsp->{data}->[0] = "Assuming an object type of \'node\'.";
 | |
|             #xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # if user specifies "-t" & "-h" they want valid type or attrs info
 | |
|     if ($::opt_h && $::opt_t)
 | |
|     {
 | |
| 
 | |
|         # give the list of attr names for each type specified
 | |
|         foreach my $t (@::clobjtypes)
 | |
|         {
 | |
|             my $rsp;
 | |
| 
 | |
|             if ($t eq 'site') {
 | |
|                 if ($::opt_i)
 | |
|                 {
 | |
|                     my $tmprsp;
 | |
|                     $tmprsp->{data}->[0] = "It is not supported to list the description of some specific site attributes, displaying the description for all site attributes instead.";
 | |
|                     xCAT::MsgUtils->message("W", $tmprsp, $::callback);
 | |
|                 }
 | |
|                 my $schema = xCAT::Table->getTableSchema('site');
 | |
|                 my $desc;
 | |
| 
 | |
|                 $rsp->{data}->[0] = "\nThere can only be one xCAT site definition. This definition consists \nof an unlimited list of user-defined attributes and values that represent \nglobal settings for the whole cluster. The following is a list \nof the attributes currently supported by xCAT.";
 | |
| 
 | |
|                 $desc = $schema->{descriptions}->{'key'};
 | |
|                 $rsp->{data}->[1] = $desc;
 | |
| 
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             # get the data type  definition from Schema.pm
 | |
|             my $datatype = $xCAT::Schema::defspec{$t};
 | |
| 
 | |
|             if (!$::opt_i)
 | |
|             {
 | |
|                 $rsp->{data}->[0] = "The valid attribute names for object type '$t' are:";
 | |
|             }
 | |
| 
 | |
|             # get the objkey for this type object (ex. objkey = 'node')
 | |
|             my $objkey = $datatype->{'objkey'};
 | |
| 
 | |
|             $rsp->{data}->[1] = "Attribute          Description\n";
 | |
| 
 | |
|             my @alreadydone;    # the same attr may appear more then once
 | |
|             my @attrlist;
 | |
|             my $outstr       = "";
 | |
|             my @dispattrs    = ();
 | |
|             my %dispattrhash = ();
 | |
|             if ($::opt_i)
 | |
|             {
 | |
|                 @dispattrs = split(/,/, $::opt_i);
 | |
|                 foreach my $dattr (@dispattrs)
 | |
|                 {
 | |
|                     # lsdef -t node -h -i nicips.eth0
 | |
|                     if ($dattr =~ /^(nic\w+)\..*$/)
 | |
|                     {
 | |
|                         $dattr = $1;
 | |
|                     }
 | |
|                     $dispattrhash{$dattr} = 1;
 | |
|                 }
 | |
|             }
 | |
|             foreach my $this_attr (@{ $datatype->{'attrs'} })
 | |
|             {
 | |
|                 my $attr = $this_attr->{attr_name};
 | |
| 
 | |
|                 # Only display the specified attributes
 | |
|                 if ($::opt_i)
 | |
|                 {
 | |
|                     if (!defined($dispattrhash{$attr}) || !$dispattrhash{$attr})
 | |
|                     {
 | |
|                         next;
 | |
|                     }
 | |
|                 }
 | |
|                 my $desc = $this_attr->{description};
 | |
|                 if (!defined($desc)) {
 | |
| 
 | |
|                     # description key not there, so go to the corresponding
 | |
|                     #    entry in tabspec to get the description
 | |
|                     my ($tab, $at) = split(/\./, $this_attr->{tabentry});
 | |
|                     my $schema = xCAT::Table->getTableSchema($tab);
 | |
|                     $desc = $schema->{descriptions}->{$at};
 | |
|                 }
 | |
| 
 | |
|                 # could display the table that the attr is in
 | |
|                 # however some attrs are in more than one table!!!
 | |
|                 #my ($tab, $junk) = split('\.', $this_attr->{tabentry});
 | |
| 
 | |
|                 if (!grep(/^$attr$/, @alreadydone))
 | |
|                 {
 | |
|                     my $space = (length($attr) < 7 ? "\t\t" : "\t");
 | |
|                     push(@attrlist, "$attr:$space$desc\n\n");
 | |
|                 }
 | |
|                 push(@alreadydone, $attr);
 | |
|             }
 | |
| 
 | |
|             # print the output in alphabetical order
 | |
|             foreach my $a (sort @attrlist) {
 | |
|                 $outstr .= "$a";
 | |
|             }
 | |
|             chop($outstr); chop($outstr);
 | |
|             $rsp->{data}->[2] = $outstr;
 | |
| 
 | |
|             # the monitoring table is  special
 | |
|             if ($t eq 'monitoring') {
 | |
|                 $rsp->{data}->[3] = "\nYou can also include additional monitoring plug-in specific settings. These settings will be used by the monitoring plug-in to customize the behavior such as event filter, sample interval, responses etc.";
 | |
|             }
 | |
| 
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
| 
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     #  determine the object names
 | |
|     #
 | |
| 
 | |
|     # -  get object names from the -o option or the noderange
 | |
|     if ($::opt_o)
 | |
|     {
 | |
| 
 | |
|         $::objectsfrom_opto = 1;
 | |
| 
 | |
|         # special handling for site table !!!!!
 | |
|         if (($::opt_t eq 'site') && ($::opt_o ne 'clustersite'))
 | |
|         {
 | |
|             push(@::clobjnames, $::opt_o);
 | |
|             push(@::clobjnames, 'clustersite');
 | |
| 
 | |
|         }
 | |
|         elsif ($::opt_t eq 'node')
 | |
|         {
 | |
|             if (($::command ne 'mkdef') && ($::opt_o =~ m/^\//))
 | |
|             {
 | |
|                 @::clobjnames = &noderange($::opt_o, 1); #Use the "verify" option to support regular expression
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 @::clobjnames = &noderange($::opt_o, 0); #mkdef can not support regular expression
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
| 
 | |
|             # make a list
 | |
|             if ($::opt_o =~ /,/)
 | |
|             {
 | |
|                 @::clobjnames = split(',', $::opt_o);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 push(@::clobjnames, $::opt_o);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     elsif (@::noderange && ($::clobjtypes[0] eq 'node'))
 | |
|     {
 | |
| 
 | |
|         # if there's no object list and the type is node then the
 | |
|         #   noderange list is assumed to be the object names list
 | |
|         @::clobjnames     = @::noderange;
 | |
|         $::objectsfrom_nr = 1;
 | |
|     }
 | |
| 
 | |
|     # special case for site table!!!!!!!!!!!!!!
 | |
|     if (($::opt_t eq 'site') && !$::opt_o)
 | |
|     {
 | |
|         push(@::clobjnames, 'clustersite');
 | |
|         $::objectsfrom_opto = 1;
 | |
|     }
 | |
| 
 | |
|     # if there is no other input for object names then we need to
 | |
|     #    find all the object names for the specified types
 | |
|     #   Do NOT do this for rmdef
 | |
|     if ($::opt_t
 | |
|         && !($::opt_o
 | |
|             || $::filedata
 | |
|             || $::opt_a
 | |
|             || @::noderange
 | |
|             || @::clobjnames))
 | |
|     {
 | |
|         my @tmplist;
 | |
| 
 | |
|         if (($::command eq 'rmdef') || ($::command eq 'chdef'))
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "No object names were provided.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 2;
 | |
|         }
 | |
| 
 | |
|         # also ne chdef ????????
 | |
|         if ($::command ne 'mkdef')
 | |
|         {
 | |
| 
 | |
|             $::objectsfrom_optt = 1;
 | |
| 
 | |
|             # could have multiple type
 | |
|             foreach my $t (@::clobjtypes)
 | |
|             {
 | |
| 
 | |
|                 # special case for site table !!!!
 | |
|                 if ($t eq 'site')
 | |
|                 {
 | |
|                     push(@tmplist, 'clustersite');
 | |
| 
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
| 
 | |
|                     #  look up all objects of this type in the DB ???
 | |
|                     @tmplist = xCAT::DBobjUtils->getObjectsOfType($t);
 | |
| 
 | |
|                     unless (@tmplist)
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Could not get objects of type \'$t\'.";
 | |
| 
 | |
|                         #$rsp->{data}->[1] = "Skipping to the next type.\n";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                         return 3;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 # add objname and type to hash and global list
 | |
|                 foreach my $o (@tmplist)
 | |
|                 {
 | |
|                     push(@::clobjnames, $o);
 | |
|                     $::ObjTypeHash{$o} = $t;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # can't have -a with other obj sources
 | |
|     if ($::opt_a
 | |
|         && ($::opt_o || ($::filedata && !defined $::opt_template) || @::noderange))
 | |
|     {
 | |
| 
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Cannot use \'-a\' with \'-o\', a noderange or file input.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 3;
 | |
|     }
 | |
| 
 | |
|     #  if -a then get a list of all DB objects
 | |
|     if ($::opt_a)
 | |
|     {
 | |
| 
 | |
|         if (!defined $::opt_template) {
 | |
|             my @tmplist;
 | |
| 
 | |
|             # for every type of data object get the list of defined objects
 | |
|             foreach my $t (keys %{xCAT::Schema::defspec})
 | |
|             {
 | |
|                 # exclude the auditlog and eventlog,
 | |
|                 # the auditlog and eventlog tables might be very big
 | |
|                 # use lsdef -t auditlog or lsdef -t eventlog instead
 | |
|                 if (($t eq 'auditlog') || ($t eq 'eventlog')) { next; }
 | |
| 
 | |
|                 $::objectsfrom_opta = 1;
 | |
| 
 | |
|                 my @tmplist;
 | |
|                 @tmplist = xCAT::DBobjUtils->getObjectsOfType($t);
 | |
| 
 | |
|                 # add objname and type to hash and global list
 | |
|                 if (scalar(@tmplist) > 0)
 | |
|                 {
 | |
|                     foreach my $o (@tmplist)
 | |
|                     {
 | |
|                         push(@::clobjnames, $o);
 | |
|                         $::AllObjTypeHash{$o} = $t;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             foreach my $fileobj (@::fileobjnames) {
 | |
|                 $::AllObjTypeHash{$fileobj} = $::FILEATTRS{$fileobj}{objtype};
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # must have object name(s) -
 | |
|     if ((scalar(@::clobjnames) == 0) && (scalar(@::fileobjnames) == 0))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "No object names were provided.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 3;
 | |
|     }
 | |
| 
 | |
|     # combine object name all object names provided
 | |
|     @::allobjnames = @::clobjnames;
 | |
|     if (scalar(@::fileobjnames) > 0 && !defined($::opt_template))
 | |
|     {
 | |
|         # add list from stanza or xml file
 | |
|         push @::allobjnames, @::fileobjnames;
 | |
|     }
 | |
|     elsif (scalar(@::objfilelist) > 0)
 | |
|     {
 | |
| 
 | |
|         # add list from "-f" file option
 | |
|         push @::allobjnames, @::objfilelist;
 | |
|     }
 | |
| 
 | |
|     #  check for the -w option
 | |
|     if ($::opt_w)
 | |
|     {
 | |
|         my $rc = xCAT::Utils->parse_selection_string($::opt_w, \%::WhereHash);
 | |
|         if ($rc != 0)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Incorrect selection string specified with -w flag.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 3;
 | |
|         }
 | |
| 
 | |
|         # For dynamic node groups, check the selection string
 | |
|         if (($::opt_t eq 'group') && ($::opt_d))
 | |
|         {
 | |
|             my $datatype  = $xCAT::Schema::defspec{'node'};
 | |
|             my @nodeattrs = ();
 | |
|             foreach my $this_attr (@{ $datatype->{'attrs'} })
 | |
|             {
 | |
|                 push @nodeattrs, $this_attr->{attr_name};
 | |
|             }
 | |
|             foreach my $whereattr (keys %::WhereHash)
 | |
|             {
 | |
|                 if (!grep(/^$whereattr$/, @nodeattrs))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Incorrect attribute \'$whereattr\' in the selection string specified with -w flag.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     return 1;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($::opt_template && ($::command eq 'mkdef'))
 | |
|     {
 | |
|         unless ($::objectsfrom_file) {
 | |
| 
 | |
|             #"mkdef --template" specifies an existing object as the template to create new object definition
 | |
|             my @myobjlist = xCAT::DBobjUtils->getObjectsOfType($::clobjtypes[0]);
 | |
|             unless (@myobjlist)
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Could not get objects of type \'$::clobjtypes[0]\'.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 3;
 | |
|             }
 | |
| 
 | |
|             unless (grep(/^$::opt_template$/, @myobjlist)) {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Could not find the template object named \'$::opt_template\' of type \'$::clobjtypes[0]\'.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 3;
 | |
|             }
 | |
| 
 | |
|             if (grep(/^$::opt_template$/, @::allobjnames)) {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "The template node cannot be the same as the node to create.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 3;
 | |
|             }
 | |
| 
 | |
|             my %objtypehash;
 | |
|             $objtypehash{$::opt_template} = $::clobjtypes[0];
 | |
|             $::ATTRLIST = "all";
 | |
| 
 | |
|             #the template object is an existing object, get the object definition
 | |
|             my %objattrhash = xCAT::DBobjUtils->getobjdefs(\%objtypehash);
 | |
| 
 | |
|             #the object attributes specified in the arguments of "mkdef" has been saved in %::ATTRS
 | |
|             #inherit the attributes not specified in arguments of "mkdef" from the template object definition
 | |
|             foreach my $key (keys %{ $objattrhash{$::opt_template} }) {
 | |
|                 if ($key ne "objtype" and not $::ATTRS{$key}) {
 | |
|                     $::ATTRS{$key} = $objattrhash{$::opt_template}{$key};
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
| 
 | |
|             #the object attribute specified in the arguments of "mkdef" has been saved in %::ATTRS
 | |
|             #the specified object template definition shipped by xCAT is save in %::FILEATTRS
 | |
|             #inherit the attributes which are not specified in arguments of "mkdef" from template
 | |
|             #"objtype" is not an object attribite, it is a field in stanza file
 | |
|             foreach my $key (keys %{ $::FILEATTRS{$::opt_template} }) {
 | |
|                 if ($key ne "objtype") {
 | |
|                     my $temlattr = $::FILEATTRS{$::opt_template}{$key};
 | |
|                     if ($temlattr =~ /^OPTIONAL:/) {
 | |
| 
 | |
|                         #the attributes with "(OPTIONAL)" in the template
 | |
|                         #can be specified on mkdef
 | |
|                         $temlattr = "";
 | |
|                     }
 | |
|                     elsif ($temlattr =~ /^MANDATORY:/) {
 | |
|                         unless ($::ATTRS{$key}) {
 | |
| 
 | |
|                             #the attributes with "(MANDATORY)" in the template
 | |
|                             #must be specified on mkdef
 | |
|                             my $rsp;
 | |
|                             $rsp->{data}->[0] = "The attribute \"$key\" must be specified!";
 | |
|                             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                             return 3;
 | |
|                         }
 | |
|                         $temlattr = "";
 | |
|                     }
 | |
| 
 | |
|                     unless ($::ATTRS{$key}) {
 | |
|                         $::ATTRS{$key} = $temlattr;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             #delete the template definition from %::FILEATTRS
 | |
|             delete $::FILEATTRS{$::opt_template};
 | |
|             @::fileobjtypes = ();
 | |
|             @::fileobjnames = ();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #  check for the -i option
 | |
|     if ($::opt_i && ($::command ne 'lsdef'))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The \'-i\' option is only valid for the lsdef command.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 3;
 | |
|     }
 | |
| 
 | |
|     #  just make a global list of the attr names provided
 | |
|     if ($::opt_i)
 | |
|     {
 | |
|         @::AttrList = split(',', $::opt_i);
 | |
| 
 | |
|         # nicips.<nic> should be changed to nicips
 | |
|         my $i = 0;
 | |
|         for ($i = 0 ; $i < (scalar @::AttrList) ; $i++)
 | |
|         {
 | |
|             if ($::AttrList[$i] =~ /^(nic\w+)\.(.*)$/)
 | |
|             {
 | |
|                 $::AttrList[$i] = $1;
 | |
|                 push @{ $::NicsAttrHash{ $::AttrList[$i] } }, $2;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3   defmk
 | |
| 
 | |
|         Support for the xCAT mkdef command.
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
|             Object names to create are derived from
 | |
|                 -o, -t, w, -z, -x, or noderange!
 | |
|             Attr=val pairs come from cmd line args or -z/-x files
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defmk
 | |
| {
 | |
| 
 | |
|     @::allobjnames = [];
 | |
| 
 | |
|     my $rc    = 0;
 | |
|     my $error = 0;
 | |
| 
 | |
|     my %objTypeLists;
 | |
| 
 | |
|     # process the command line
 | |
|     $rc = &processArgs;
 | |
| 
 | |
|     if ($rc != 0)
 | |
|     {
 | |
| 
 | |
|         # rc: 0 - ok, 1 - return, 2 - help, 3 - error
 | |
|         # 0 - continue
 | |
|         # 1 - return  (like for version option)
 | |
|         # 2 - return with usage
 | |
|         # 3 - return error
 | |
|         if ($rc == 1) {
 | |
|             return 0;
 | |
|         } elsif ($rc == 2) {
 | |
|             &defmk_usage;
 | |
|             return 0;
 | |
|         } elsif ($rc == 3) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # check options unique to these commands
 | |
|     if ($::opt_p || $::opt_m)
 | |
|     {
 | |
| 
 | |
|         # error
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The \'-p\' and \'-m\' options are not valid for the mkdef command.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defmk_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     if ($::opt_t && ($::opt_a || $::opt_z || $::opt_x))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Cannot combine \'-t\' and \'-a\', \'-z\', or \'-x\' options.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defmk_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # can't have -z with other obj sources
 | |
|     if ($::opt_z && ($::opt_o || @::noderange))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Cannot use \'-z\' with \'-o\' or a noderange.";
 | |
|         $rsp->{data}->[1] = "Example of -z usage:\n\t\'cat stanzafile | mkdef -z\'";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defmk_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # check to make sure we have a list of objects to work with
 | |
|     if (!@::allobjnames)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "No object names were provided.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defmk_usage;
 | |
|         return 1;
 | |
|     } else {
 | |
|         my $invalidobjname = ();
 | |
|         my $invalidnodename = ();
 | |
|         foreach my $node (@::allobjnames) {
 | |
|             my $myobjtype=$::opt_t;
 | |
|             if(!$myobjtype and $::FILEATTRS{$node}{'objtype'}){
 | |
|                 $myobjtype=$::FILEATTRS{$node}{'objtype'};
 | |
|             }
 | |
| 
 | |
|             unless(isobjnamevalid($node,$myobjtype)){
 | |
|                $invalidobjname .= ",$node";
 | |
|             }
 | |
|             if (($node =~ /[A-Z]/) && (((!$::opt_t) && (!$::FILEATTRS{$node}{'objtype'})) || ($::FILEATTRS{$node}{'objtype'} eq "node") || ($::opt_t eq "node"))) { 
 | |
|                $invalidnodename .= ",$node";
 | |
|             }
 | |
|         }
 | |
|         if ($invalidobjname) {
 | |
|             $invalidobjname =~ s/,//;
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The object name \'$invalidobjname\' is invalid, please refer to \"man xcatdb\" for the valid \"xCAT Object Name Format\"";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             $error = 1;
 | |
|             return 1;
 | |
|         }
 | |
|         if ($invalidnodename) {
 | |
|             $invalidnodename =~ s/,//;
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The node name \'$invalidnodename\' contains capital letters which may not be resolved correctly by the dns server.";
 | |
|             xCAT::MsgUtils->message("W", $rsp, $::callback);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # set $objtype & fill in cmd line hash
 | |
|     if (%::ATTRS || ($::opt_t eq "group"))
 | |
|     {
 | |
| 
 | |
|         # if attr=val on cmd line then could only have one type
 | |
|         $::objtype = $::clobjtypes[0];
 | |
| 
 | |
|         #
 | |
|         #  set cli attrs for each object definition
 | |
|         #
 | |
|         foreach my $objname (@::clobjnames)
 | |
|         {
 | |
| 
 | |
|             #  set the objtype attr - if provided
 | |
|             if ($::objtype)
 | |
|             {
 | |
|                 $::CLIATTRS{$objname}{objtype} = $::objtype;
 | |
|             }
 | |
| 
 | |
|             # get the data type definition from Schema.pm
 | |
|             my $datatype = $xCAT::Schema::defspec{$::objtype};
 | |
|             my @list;
 | |
|             foreach my $this_attr (sort @{ $datatype->{'attrs'} })
 | |
|             {
 | |
|                 my $a = $this_attr->{attr_name};
 | |
|                 push(@list, $a);
 | |
|             }
 | |
| 
 | |
|             # set the attrs from the attr=val pairs
 | |
|             foreach my $attr (keys %::ATTRS)
 | |
|             {
 | |
|                 my $attrorig = $attr;
 | |
| 
 | |
|                 # nicips.eth0 => nicips
 | |
|                 if ($attr =~ /^(nic\w+)\..*$/)
 | |
|                 {
 | |
|                     $attr = $1;
 | |
|                 }
 | |
|                 if (!grep(/^$attr$/, @list) && ($::objtype ne 'site') && ($::objtype ne 'monitoring'))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "\'$attr\' is not a valid attribute name for an object type of \'$::objtype\'.";
 | |
|                     $rsp->{data}->[1] = "Skipping to the next attribute.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     next;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     $::CLIATTRS{$objname}{$attrorig} = $::ATTRS{$attrorig};
 | |
|                     if ($::verbose)
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "\nFunction: defmk-->set the attrs for each object definition";
 | |
|                         $rsp->{data}->[1] = "defmk: objname=$objname, attr=$attrorig, value=$::ATTRS{$attrorig}";
 | |
|                         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                     }
 | |
|                 }
 | |
|             }    # end - foreach attr
 | |
| 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     #   Pull all the pieces together for the final hash
 | |
|     #        - combines the command line attrs and input file attrs if provided
 | |
|     #
 | |
|     if (&setFINALattrs != 0)
 | |
|     {
 | |
|         $error = 1;
 | |
|     }
 | |
| 
 | |
|     # we need a list of objects that are
 | |
|     #    already defined for each type.
 | |
|     foreach my $t (@::finalTypeList)
 | |
|     {
 | |
| 
 | |
|         # special case for site table !!!!!!!!!!!!!!!!!!!!
 | |
|         if ($t eq 'site')
 | |
|         {
 | |
|             @{ $objTypeLists{$t} } = 'clustersite';
 | |
|         }
 | |
|         else
 | |
|         {
 | |
| 
 | |
|             @{ $objTypeLists{$t} } = xCAT::DBobjUtils->getObjectsOfType($t);
 | |
|         }
 | |
|         if ($::verbose)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "\ndefmk: list objects that are defined for each type";
 | |
|             $rsp->{data}->[1] = "@{$objTypeLists{$t}}";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # Build up a hash for the array in objTypeLists
 | |
|     # for performance consideration, grep the array is not effective
 | |
|     my %objTypeListsHash;
 | |
|     foreach my $objk (keys %objTypeLists)
 | |
|     {
 | |
|         foreach my $obj (@{ $objTypeLists{$objk} }) {
 | |
|             $objTypeListsHash{$objk}{$obj} = 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|   OBJ: foreach my $obj (keys %::FINALATTRS)
 | |
|     {
 | |
| 
 | |
|         my $type = $::FINALATTRS{$obj}{objtype};
 | |
|         # check to make sure we have type
 | |
|         if (!$type)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "No type was provided for object \'$obj\'.";
 | |
|             $rsp->{data}->[1] = "Skipping to the next object.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             $error = 1;
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         # we don't want to overwrite any existing table row.  This could
 | |
|         #    happen if there are multiple table keys. (ex. networks table -
 | |
|         #        where the object name is not either of the table keys - net
 | |
|         #        & mask)
 | |
|         #  just handle network objects for now -
 | |
|         if ($type eq 'network') {
 | |
|             my @nets = xCAT::DBobjUtils->getObjectsOfType('network');
 | |
|             my %objhash;
 | |
|             foreach my $n (@nets) {
 | |
|                 # netname is duplicate
 | |
|                 if ( $obj eq $n ) {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "A network definition called \'$n\' already exists. Cannot create a definition for \'$obj\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     delete $::FINALATTRS{$obj};
 | |
|                     next OBJ;
 | |
|                 }
 | |
|                 $objhash{$n} = $type;
 | |
|             }
 | |
|             # When adding a new network entry, net and mask cannot be empty
 | |
|             if (!($::FINALATTRS{$obj}{net} && $::FINALATTRS{$obj}{mask}))
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Net or mask value should not be empty for xCAT network object \'$obj\'.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 $error = 1;
 | |
|                 delete $::FINALATTRS{$obj};
 | |
|                 next OBJ;
 | |
|             }
 | |
|             my %nethash = xCAT::DBobjUtils->getobjdefs(\%objhash);
 | |
|             foreach my $o (keys %nethash) {
 | |
|                 # there is a network entry contains the same net and mask
 | |
|                 if (($nethash{$o}{net} eq $::FINALATTRS{$obj}{net}) && ($nethash{$o}{mask} eq $::FINALATTRS{$obj}{mask})) {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "A network definition called \'$o\' already exists that contains the same net and mask values. Cannot create a definition for \'$obj\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     delete $::FINALATTRS{$obj};
 | |
|                     next OBJ;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         # if object already exists
 | |
|         if (defined($objTypeListsHash{$type}{$obj}) && ($objTypeListsHash{$type}{$obj} == 1))
 | |
|         {
 | |
|             if ($::opt_f)
 | |
|             {
 | |
|                 # remove the old object
 | |
|                 my %objhash;
 | |
|                 $objhash{$obj} = $type;
 | |
|                 if (xCAT::DBobjUtils->rmobjdefs(\%objhash) != 0)
 | |
|                 {
 | |
|                     $error = 1;
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Could not remove the definition for \'$obj\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
| 
 | |
|                 #  won't remove the old one unless the force option is used
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "A definition for \'$obj\' already exists. No changes will be made.  Run again with \'-f\' option to force replace.";
 | |
|                 xCAT::MsgUtils->message("W", $rsp, $::callback);
 | |
|                 delete $::FINALATTRS{$obj};
 | |
|                 next;
 | |
| 
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         # need to handle group definitions - special!
 | |
|         if ($type eq 'group')
 | |
|         {
 | |
| 
 | |
|             my @memberlist;
 | |
| 
 | |
|             # if the group type was not set then set it
 | |
|             if (!$::FINALATTRS{$obj}{grouptype})
 | |
|             {
 | |
|                 if ($::opt_d)
 | |
|                 {
 | |
|                     # For dynamic node group,
 | |
|                     # can not assign attributes for inherit
 | |
|                     # only the 'objtype' in %::FINALATTRS
 | |
|                     if (scalar(keys %{ $::FINALATTRS{$obj} }) > 1)
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Can not assign attributes to dynamic node group \'$obj\'.";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                         $error = 1;
 | |
|                         delete($::FINALATTRS{$obj});
 | |
|                         next;
 | |
|                     }
 | |
|                     $::FINALATTRS{$obj}{grouptype} = 'dynamic';
 | |
|                     $::FINALATTRS{$obj}{members}   = 'dynamic';
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     $::FINALATTRS{$obj}{grouptype} = 'static';
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             # if dynamic and wherevals not set then set to opt_w
 | |
|             if ($::FINALATTRS{$obj}{grouptype} eq 'dynamic')
 | |
|             {
 | |
|                 if (!$::FINALATTRS{$obj}{wherevals})
 | |
|                 {
 | |
|                     if ($::opt_w)
 | |
|                     {
 | |
|                         $::FINALATTRS{$obj}{wherevals} = join('::', @{$::opt_w});
 | |
| 
 | |
|                         #$::FINALATTRS{$obj}{wherevals} = $::opt_w;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "The \'where\' attributes and values were not provided for dynamic group \'$obj\'.";
 | |
|                         $rsp->{data}->[1] = "Skipping to the next group.";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                         next;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             # if static group then figure out memberlist
 | |
|             if ($::FINALATTRS{$obj}{grouptype} eq 'static')
 | |
|             {
 | |
|                 if ($::opt_w && $::FINALATTRS{$obj}{members})
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Cannot use a list of members together with the \'-w\' option.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     return 1;
 | |
|                 }
 | |
| 
 | |
|                 if ($::FINALATTRS{$obj}{members})
 | |
|                 {
 | |
|                     @memberlist = &noderange($::FINALATTRS{$obj}{members}, 0);
 | |
| 
 | |
|                     #  don't list all the nodes in the group table
 | |
|                     #    set the value to static and we'll figure out the list
 | |
|                     #     by looking in the nodelist table
 | |
|                     $::FINALATTRS{$obj}{members} = 'static';
 | |
| 
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if ($::opt_w)
 | |
|                     {
 | |
|                         $::FINALATTRS{$obj}{members} = 'static';
 | |
| 
 | |
|                         #  get a list of nodes whose attr values match the
 | |
|                         #   "where" values and make that the memberlist of
 | |
|                         #   the group.
 | |
| 
 | |
|                         # get a list of all node nodes
 | |
|                         my @tmplist =
 | |
|                           xCAT::DBobjUtils->getObjectsOfType('node');
 | |
| 
 | |
|                         # create a hash of obj names and types
 | |
|                         my %objhash;
 | |
|                         foreach my $n (@tmplist)
 | |
|                         {
 | |
|                             $objhash{$n} = 'node';
 | |
|                         }
 | |
| 
 | |
|                         # get all the attrs for these nodes
 | |
|                         my @whereattrs = keys %::WhereHash;
 | |
|                         my %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash, 0, \@whereattrs);
 | |
| 
 | |
|                         # see which ones match the where values
 | |
|                         foreach my $objname (keys %myhash)
 | |
|                         {
 | |
| 
 | |
|                             if (xCAT::Utils->selection_string_match(\%myhash, $objname, \%::WhereHash)) {
 | |
|                                 push(@memberlist, $objname);
 | |
| 
 | |
|                             }
 | |
|                         }
 | |
| 
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Cannot determine a member list for group \'$obj\'.";
 | |
|                         xCAT::MsgUtils->message("W", $rsp, $::callback);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 # mkdef -t group should not create new nodes
 | |
|                 my @tmpmemlist = ();
 | |
|                 my @allnodes   = xCAT::DBobjUtils->getObjectsOfType('node');
 | |
|                 foreach my $tmpnode (@memberlist)
 | |
|                 {
 | |
|                     if (!grep(/^$tmpnode$/, @allnodes))
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Could not find a node named \'$tmpnode\', skipping to the next node.";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         push @tmpmemlist, $tmpnode;
 | |
|                     }
 | |
|                 }
 | |
|                 @memberlist = @tmpmemlist;
 | |
| 
 | |
|                 #  need to add group name to all members in nodelist table
 | |
|                 my $tab =
 | |
|                   xCAT::Table->new('nodelist', -create => 1, -autocommit => 0);
 | |
| 
 | |
|                 my $newgroups;
 | |
|                 my $changed = 0;
 | |
|                 foreach my $n (@memberlist)
 | |
|                 {
 | |
|                     if ($::verbose)
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "defmk: add group name [$n] to nodelist table";
 | |
|                         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                     }
 | |
| 
 | |
|                     #  add this group name to the node entry in
 | |
|                     #        the nodelist table
 | |
|                     #$nodehash{$n}{groups} = $obj;
 | |
| 
 | |
|                     # get the current value
 | |
|                     my $grps = $tab->getNodeAttribs($n, ['groups']);
 | |
| 
 | |
|                     # if it's not already in the "groups" list then add it
 | |
|                     my @tmpgrps = split(/,/, $grps->{'groups'});
 | |
| 
 | |
|                     if (!grep(/^$obj$/, @tmpgrps))
 | |
|                     {
 | |
|                         if ($grps and $grps->{'groups'})
 | |
|                         {
 | |
|                             $newgroups = "$grps->{'groups'},$obj";
 | |
| 
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             $newgroups = $obj;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     #  add this group name to the node entry in
 | |
|                     #       the nodelist table
 | |
|                     if ($newgroups)
 | |
|                     {
 | |
|                         $tab->setNodeAttribs($n, { groups => $newgroups });
 | |
|                         $changed = 1;
 | |
|                     }
 | |
| 
 | |
|                 }
 | |
|                 if ($changed) {
 | |
|                     $tab->commit;
 | |
|                 }
 | |
| 
 | |
| 
 | |
|             }
 | |
|         }    # end - if group type
 | |
| 
 | |
|         # If none of the attributes in nodelist is defined: groups,status,appstatus,primarysn,comments,disable
 | |
|         # the nodelist table will not be updated, caused mkdef failed.
 | |
|         # We give a restriction that the "groups" must be specified with mkdef.
 | |
|         if (($type eq "node") && (!defined($::FINALATTRS{$obj}{groups}) || !$::FINALATTRS{$obj}{groups}))
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Attribute \'groups\' is not specified for node \'$obj\', skipping to the next node.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             $error = 1;
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         # Removed the code to handle the nodegroup table with mkdef -t node groups=xxx
 | |
|         # Only dynamic groups should be in nodegroup table
 | |
|         # Do not try to add static group into the nodegroup table
 | |
|         # performance!!!!
 | |
|         if (defined($::opt_setattr) && $type eq "osimage") {
 | |
|             my $rc = &parse_attr_for_osimage($::command, $::FINALATTRS{$obj});
 | |
|             if ($rc) {
 | |
|                 $error = $rc;
 | |
|                 next;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     }    # end of each obj
 | |
| 
 | |
|     #
 | |
|     #  write each object into the tables in the xCAT database
 | |
|     #
 | |
| 
 | |
|     if (xCAT::DBobjUtils->setobjdefs(\%::FINALATTRS) != 0)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Could not write data to the xCAT database.";
 | |
| 
 | |
|         #        xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         $error = 1;
 | |
|     }
 | |
| 
 | |
|     if ($error)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "One or more errors occured when attempting to create or modify xCAT \nobject definitions.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         my $nodenum = 0;
 | |
|         my $ret = 0;
 | |
|         my @nodes_updated = ();
 | |
|         foreach my $node (keys %::FINALATTRS) {
 | |
|             if ($::FINALATTRS{$node}{updated}) {
 | |
|                 $nodenum++;
 | |
|                 push @nodes_updated, $node;
 | |
|             }
 | |
|             if ($::FINALATTRS{$node}{error}) {
 | |
|                 $ret = 1;
 | |
|             }
 | |
|         }
 | |
|         if ($::verbose)
 | |
|         {
 | |
| 
 | |
|             #  give results
 | |
|             my $rsp;
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
| 
 | |
|             my $n = 1;
 | |
|             foreach my $o (sort( @nodes_updated))
 | |
|             {
 | |
|                 $rsp->{data}->[$n] = "$o";
 | |
|                 $n++;
 | |
|             }
 | |
|             if ($n > 1) {
 | |
|                 # Some objects were created ($n was increased), report as success
 | |
|                 $rsp->{data}->[0] = "The database was updated for the following objects:";
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             }
 | |
|             else {
 | |
|                 # No objects were created, report as error
 | |
|                 $rsp->{data}->[0] = "The database was not updated.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             }
 | |
|         }
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "$nodenum object definitions have been created or modified.";
 | |
|         if ($nodenum > 0) {
 | |
|             # Some objects were created, report as success
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
|         else {
 | |
|             # No objects were created, report as error
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         }
 | |
|         return $ret;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3   defch
 | |
| 
 | |
|         Support for the xCAT chdef command.
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
|             Object names to create are derived from
 | |
|                 -o, -t, w, -z, -x, or noderange!
 | |
|             Attr=val pairs come from cmd line args or -z/-x files
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defch
 | |
| {
 | |
| 
 | |
|     @::allobjnames = [];
 | |
| 
 | |
|     my $rc        = 0;
 | |
|     my $error     = 0;
 | |
|     my $firsttime = 1;
 | |
| 
 | |
|     my %objTypeLists;
 | |
| 
 | |
|     # hash that contains all the new objects that are being created
 | |
|     my %newobjects;
 | |
| 
 | |
|     # process the command line
 | |
|     $rc = &processArgs;
 | |
| 
 | |
|     if ($rc != 0)
 | |
|     {
 | |
| 
 | |
|         # rc: 0 - ok, 1 - return, 2 - help, 3 - error
 | |
|         # 0 - continue
 | |
|         # 1 - return  (like for version option)
 | |
|         # 2 - return with usage
 | |
|         # 3 - return error
 | |
|         if ($rc == 1) {
 | |
|             return 0;
 | |
|         } elsif ($rc == 2) {
 | |
|             &defch_usage;
 | |
|             return 0;
 | |
|         } elsif ($rc == 3) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     #
 | |
|     # check options unique to this command
 | |
|     #
 | |
|     if ($::opt_n) {
 | |
| 
 | |
|         # check the option for changing object name
 | |
|         if ($::opt_n && ($::opt_d || $::opt_p || $::opt_m || $::opt_z || $::opt_w)) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Cannot combine \'-n\' and \'-d\',\'-p\',\'-m\',\'-z\',\'-w\' options.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             &defch_usage;
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         if (scalar(@::clobjnames) > 1) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The \'-n\' option (changing object name) can only work on one object.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             &defch_usage;
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         my %objhash = ($::clobjnames[0] => $::clobjtypes[0]);
 | |
| 
 | |
|         my @validnode = xCAT::DBobjUtils->getObjectsOfType($::clobjtypes[0]);
 | |
|         if (!grep /^$::clobjnames[0]$/, @validnode) {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The $::clobjnames[0] is not a valid object.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         # Ensure that the target object doesn't exist
 | |
|         if (grep /^$::opt_n$/, @validnode) {
 | |
|             my $rsp;
 | |
|             push @{ $rsp->{data} }, "Object $::opt_n already exists.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         # Use the getobjdefs function to get a hash which including
 | |
|         # all the records in the table that should be changed
 | |
|         my %chnamehash = ();
 | |
|         xCAT::DBobjUtils->getobjdefs(\%objhash, $::VERBOSE, undef, \%chnamehash);
 | |
| 
 | |
|         foreach my $tb (keys %chnamehash) {
 | |
|             my $tab = xCAT::Table->new($tb);
 | |
|             unless ($tab) {
 | |
|                 my $rsp;
 | |
|                 push @{ $rsp->{data} }, "Unable to open $tb table.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 1;
 | |
|             }
 | |
| 
 | |
|             my $index = 0;
 | |
|             my @taben = @{ $chnamehash{$tb} };
 | |
| 
 | |
|             # In the @taben, there are several pair of value for
 | |
|             # changing the key value of a table entry
 | |
|             my @keystrs = ();
 | |
|             while ($taben[$index]) {
 | |
| 
 | |
|                 # Make a key word string to avoid that changing
 | |
|                 # one table record multiple times
 | |
|                 my $keystr;
 | |
|                 foreach my $key (sort(keys %{ $taben[$index] })) {
 | |
|                     $keystr .= "$key:$taben[$index]{$key}:";
 | |
|                 }
 | |
|                 if (grep /^$keystr$/, @keystrs) {
 | |
|                     $index += 2;
 | |
|                     next;
 | |
|                 }
 | |
|                 push @keystrs, $keystr;
 | |
| 
 | |
|                 my %chname = ($taben[ $index + 1 ] => $::opt_n);
 | |
|                 $tab->setAttribs($taben[$index], \%chname);
 | |
|                 $index += 2;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         my $rsp;
 | |
|         push @{ $rsp->{data} }, "Changed the object name from $::clobjnames[0] to $::opt_n.";
 | |
|         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
| 
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     if ($::opt_f)
 | |
|     {
 | |
| 
 | |
|         # error
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The \'-f\' option is not valid for the chdef command.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defch_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     if ($::opt_t && ($::opt_a || $::opt_z || $::opt_x))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Cannot combine \'-t\' and \'-a\', \'-z\', or \'-x\' options.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defch_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # can't have -z with other obj sources
 | |
|     if ($::opt_z && ($::opt_o || @::noderange))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Cannot use \'-z\' with \'-o\' or a noderange.";
 | |
|         $rsp->{data}->[1] = "Example of -z usage:\n\t\'cat stanzafile | chdef -z\'";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defch_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     if ($::opt_t eq "osimage" && $::opt_setattr && ($::opt_p || $::opt_m)) {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Cannot use \'-u\' with \'-p\' or \'-m\'.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # check to make sure we have a list of objects to work with
 | |
|     if (!@::allobjnames)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "No object names were provided.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defch_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     # set $objtype & fill in cmd line hash
 | |
|     if (%::ATTRS || ($::opt_t eq "group"))
 | |
|     {
 | |
| 
 | |
|         # if attr=val on cmd line then could only have one type
 | |
|         $::objtype = $::clobjtypes[0];
 | |
| 
 | |
|         #
 | |
|         #  set cli attrs for each object definition
 | |
|         #
 | |
|         foreach my $objname (@::clobjnames)
 | |
|         {
 | |
| 
 | |
|             #  set the objtype attr - if provided
 | |
|             if ($::objtype)
 | |
|             {
 | |
|                 chomp $::objtype;
 | |
|                 $::CLIATTRS{$objname}{objtype} = $::objtype;
 | |
|             }
 | |
| 
 | |
|             # get the data type definition from Schema.pm
 | |
|             my $datatype = $xCAT::Schema::defspec{$::objtype};
 | |
|             my %list;
 | |
|             foreach my $this_attr (sort @{ $datatype->{'attrs'} })
 | |
|             {
 | |
|                 my $a = $this_attr->{attr_name};
 | |
|                 $list{$a} = 1;
 | |
|             }
 | |
| 
 | |
|             # set the attrs from the attr=val pairs
 | |
|             foreach my $attr (keys %::ATTRS)
 | |
|             {
 | |
|                 my $attrorig = $attr;
 | |
| 
 | |
|                 # nicips.eth0 => nicips
 | |
|                 if ($attr =~ /^(nic\w+)\..*$/)
 | |
|                 {
 | |
|                     $attr = $1;
 | |
|                 }
 | |
|                 if (!defined($list{$attr}) && ($::objtype ne 'site') && ($::objtype ne 'monitoring'))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "\'$attr\' is not a valid attribute name for an object type of \'$::objtype\'.";
 | |
|                     $rsp->{data}->[1] = "Skipping to the next attribute.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     next;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     $::CLIATTRS{$objname}{$attrorig} = $::ATTRS{$attrorig};
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     #   Pull all the pieces together for the final hash
 | |
|     #        - combines the command line attrs and input file attrs if provided
 | |
|     #
 | |
|     if (&setFINALattrs != 0)
 | |
|     {
 | |
|         $error = 1;
 | |
|     }
 | |
| 
 | |
|     # we need a list of objects that are
 | |
|     #   already defined for each type.
 | |
|     foreach my $t (@::finalTypeList)
 | |
|     {
 | |
| 
 | |
|         # special case for site table !!!!!!!!!!!!!!!!!!!!
 | |
|         if ($t eq 'site')
 | |
|         {
 | |
|             @{ $objTypeLists{$t} } = 'clustersite';
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             @{ $objTypeLists{$t} } = xCAT::DBobjUtils->getObjectsOfType($t);
 | |
|         }
 | |
|         if ($::verbose)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "\ndefch: list objects that are defined for each type";
 | |
|             $rsp->{data}->[1] = "@{$objTypeLists{$t}}";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # Build up a hash for the array in objTypeLists
 | |
|     # for performance consideration, grep the array is not effective
 | |
|     my %objTypeListsHash;
 | |
|     foreach my $objk (keys %objTypeLists)
 | |
|     {
 | |
|         foreach my $obj (@{ $objTypeLists{$objk} }) {
 | |
|             $objTypeListsHash{$objk}{$obj} = 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     foreach my $obj (keys %::FINALATTRS)
 | |
|     {
 | |
| 
 | |
|         my $isDefined = 0;
 | |
|         my $type      = $::FINALATTRS{$obj}{objtype};
 | |
|         my %attrhash;
 | |
|         my @img_attrs = qw(imagetype provmethod profile osname osvers osarch);
 | |
|         if ($::opt_setattr && $type eq "osimage") {
 | |
|             my %tmp_objhash = ();
 | |
|             %attrhash = xCAT::DBobjUtils->getobjdefs({ $obj => $type }, $::VERBOSE, \@img_attrs);
 | |
|         }
 | |
| 
 | |
|         # check to make sure we have type
 | |
|         if (!$type)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "No type was provided for object \'$obj\'.";
 | |
|             $rsp->{data}->[1] = "Skipping to the next object.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             $error = 1;
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         if (defined($objTypeListsHash{$type}{$obj}) && ($objTypeListsHash{$type}{$obj} == 1))
 | |
|         {
 | |
|             $isDefined = 1;
 | |
|         }
 | |
| 
 | |
|         if ($type eq 'network')
 | |
|         {
 | |
|             my $isInvalid = 0;
 | |
|             # When adding a new network entry, net and mask cannot be empty
 | |
|             if (!$isDefined && !($::FINALATTRS{$obj}{'net'} && $::FINALATTRS{$obj}{'mask'}))
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Net or mask value should not be empty for xCAT network object \'$obj\'.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 $error = 1;
 | |
|                 $isInvalid = 1;
 | |
|                 delete($::FINALATTRS{$obj});
 | |
|                 next;
 | |
|             }
 | |
|             my @nets = xCAT::DBobjUtils->getObjectsOfType('network');
 | |
|             my %objhash;
 | |
|             foreach my $n (@nets) {
 | |
|                 $objhash{$n} = $type;
 | |
|             }
 | |
|             # get original networks data
 | |
|             my %nethash = xCAT::DBobjUtils->getobjdefs(\%objhash);
 | |
|             foreach my $o (keys %nethash) {
 | |
|                 # the netname already exists
 | |
|                 if ($isDefined)
 | |
|                 {
 | |
|                     # when net is empty, chdef command should add net value, $::FINALATTRS{$obj}{net} should have value 
 | |
|                     if ((!$nethash{$o}{net}) && (!$::FINALATTRS{$obj}{net}))                
 | |
|                     {
 | |
|                         $isInvalid=1; 
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Attribute \'net\' is not specified for network entry \'$obj\', skipping.";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                         $error = 1;
 | |
|                         last;
 | |
|                      }
 | |
|                      # when mask is empty, chdef command should add mask value, $::FINALATTRS{$obj}{mask} should have value
 | |
|                      if ((!$nethash{$o}{mask}) && (!$::FINALATTRS{$obj}{mask}))
 | |
|                      {
 | |
|                          $isInvalid=1;
 | |
|                          my $rsp;
 | |
|                          $rsp->{data}->[0] = "Attribute \'mask\' is not specified for network entry \'$obj\', skipping.";
 | |
|                          xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                          $error = 1;
 | |
|                          last;
 | |
|                      }
 | |
|                 }
 | |
|                 # the netname does not exist 
 | |
|                 else {
 | |
|                      # there is a network definition already contains the same net and mask, it is duplicate
 | |
|                      if (($nethash{$o}{net} eq $::FINALATTRS{$obj}{net}) && ($nethash{$o}{mask} eq $::FINALATTRS{$obj}{mask})) 
 | |
|                      {
 | |
|                          $isInvalid=1;
 | |
|                          my $rsp;
 | |
|                          $rsp->{data}->[0] = "A network definition called \'$o\' already exists that contains the same net and mask values. Cannot create a definition for \'$obj\'.";
 | |
|                          xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                          $error = 1;
 | |
|                          last;
 | |
|                      }
 | |
|  
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             if($isInvalid)
 | |
|             {
 | |
|                delete($::FINALATTRS{$obj});
 | |
|                next;
 | |
|             }
 | |
|         }
 | |
|         if (!$isDefined && ($type eq 'node') && (!defined($::FINALATTRS{$obj}{'groups'}) || !$::FINALATTRS{$obj}{'groups'}))
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Attribute \'groups\' is not specified for node \'$obj\', skipping to the next node.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             $error = 1;
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         if (!$isDefined)
 | |
|         {
 | |
|             $newobjects{$obj} = $type;
 | |
|         }
 | |
| 
 | |
|         if (!$isDefined && $::opt_m)
 | |
|         {
 | |
| 
 | |
|             #error - cannot remove items from an object that does not exist.
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "The \'-m\' option is not valid since the \'$obj\' definition does not exist.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             $error = 1;
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         #
 | |
|         # need to handle group definitions - special!
 | |
|         #    - may need to update the node definitions for the group members
 | |
|         #
 | |
|         if ($type eq 'group')
 | |
|         {
 | |
|             my %grphash;
 | |
|             my @memberlist;
 | |
| 
 | |
|             # what kind of group is this? - static or dynamic
 | |
|             my $grptype;
 | |
|             my %objhash;
 | |
|             if ($::opt_d)
 | |
|             {
 | |
|                 # For dynamic node group,
 | |
|                 # can not assign attributes for inherit
 | |
|                 # only the 'objtype' in %::FINALATTRS
 | |
|                 if (scalar(keys %{ $::FINALATTRS{$obj} }) > 1)
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Can not assign attributes to dynamic node group \'$obj\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     delete($::FINALATTRS{$obj});
 | |
|                     next;
 | |
|                 }
 | |
|             }
 | |
|             if ($isDefined)
 | |
|             {
 | |
|                 $objhash{$obj} = $type;
 | |
|                 my @finalattrs = keys %{ $::FINALATTRS{$obj} };
 | |
|                 push @finalattrs, 'grouptype';
 | |
|                 %grphash = xCAT::DBobjUtils->getobjdefs(\%objhash, 0, \@finalattrs);
 | |
|                 if (!(%grphash))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Could not get xCAT object definitions.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     return 1;
 | |
| 
 | |
|                 }
 | |
|                 $grptype = $grphash{$obj}{grouptype};
 | |
|                 if (($grptype eq "dynamic") && (scalar(keys %{ $::FINALATTRS{$obj} }) > 1))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Can not assign attributes to dynamic node group \'$obj\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     delete($::FINALATTRS{$obj});
 | |
|                     next;
 | |
|                 }
 | |
| 
 | |
|                 # for now all groups are static
 | |
|                 #$grptype = 'static';
 | |
|             }
 | |
|             else
 | |
|             {    #not defined
 | |
|                 if ($::FINALATTRS{$obj}{grouptype})
 | |
|                 {
 | |
|                     $grptype = $::FINALATTRS{$obj}{grouptype};
 | |
|                 }
 | |
|                 elsif ($::opt_d)
 | |
|                 {
 | |
|                     $grptype = 'dynamic';
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     $grptype = 'static';
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             # make sure wherevals was set - if info provided
 | |
|             if (!$::FINALATTRS{$obj}{wherevals})
 | |
|             {
 | |
|                 if ($::opt_w)
 | |
|                 {
 | |
|                     $::FINALATTRS{$obj}{wherevals} = join('::', @{$::opt_w});
 | |
| 
 | |
|                     #$::FINALATTRS{$obj}{wherevals} = $::opt_w;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             #  get the @memberlist for static group
 | |
|             #    - if provided - to use below
 | |
|             #  if the static group is not defined in the nodegroup table
 | |
|             #  the grptype will be undef
 | |
|             if (!$grptype || ($grptype eq 'static'))
 | |
|             {
 | |
| 
 | |
|                 # check for bad cmd line options
 | |
|                 if ($::opt_w && $::FINALATTRS{$obj}{members})
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Cannot use a list of members together with the \'-w\' option.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     next;
 | |
|                 }
 | |
| 
 | |
|                 if ($::FINALATTRS{$obj}{members})
 | |
|                 {
 | |
|                     @memberlist = &noderange($::FINALATTRS{$obj}{members}, 0);
 | |
| 
 | |
|                     #  don't list all the nodes in the group table
 | |
|                     #   set the value to static and we figure out the list
 | |
|                     #   by looking in the nodelist table
 | |
|                     $::FINALATTRS{$obj}{members} = 'static';
 | |
| 
 | |
|                 }
 | |
|                 elsif ($::FINALATTRS{$obj}{wherevals})
 | |
|                 {
 | |
|                     $::FINALATTRS{$obj}{members} = 'static';
 | |
| 
 | |
|                     #  get a list of nodes whose attr values match the
 | |
|                     #   "where" values and make that the memberlist of
 | |
|                     #   the group.
 | |
| 
 | |
|                     # get a list of all node nodes
 | |
|                     my @tmplist = xCAT::DBobjUtils->getObjectsOfType('node');
 | |
| 
 | |
|                     # create a hash of obj names and types
 | |
|                     my %objhash;
 | |
|                     foreach my $n (@tmplist)
 | |
|                     {
 | |
|                         $objhash{$n} = 'node';
 | |
|                     }
 | |
| 
 | |
|                     # get a list of attr=val pairs, is it really necessary??
 | |
|                     my @wherevals = split(/::/, $::FINALATTRS{$obj}{wherevals});
 | |
|                     my $rc = xCAT::Utils->parse_selection_string(\@wherevals, \%::WhereHash);
 | |
|                     if ($rc != 0)
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Incorrect selection string";
 | |
|                         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                         return 3;
 | |
|                     }
 | |
| 
 | |
|                     # get the attrs for these nodes
 | |
|                     my @whereattrs = keys %::WhereHash;
 | |
|                     my %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash, 0, \@whereattrs);
 | |
| 
 | |
|                     # see which ones match the where values
 | |
|                     foreach my $objname (keys %myhash)
 | |
|                     {
 | |
| 
 | |
|                         if (xCAT::Utils->selection_string_match(\%myhash, $objname, \%::WhereHash)) {
 | |
|                             push(@memberlist, $objname);
 | |
|                         }
 | |
| 
 | |
|                     }
 | |
| 
 | |
|                 }
 | |
| 
 | |
|             }    # end - get memberlist for static group
 | |
| 
 | |
|             # chdef -t group should not create new nodes
 | |
|             my @tmpmemlist = ();
 | |
|             my @allnodes   = xCAT::DBobjUtils->getObjectsOfType('node');
 | |
|             foreach my $tmpnode (@memberlist)
 | |
|             {
 | |
|                 if (!grep(/^$tmpnode$/, @allnodes))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Could not find a node named \'$tmpnode\', skipping to the next node.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     push @tmpmemlist, $tmpnode;
 | |
|                 }
 | |
|             }
 | |
|             @memberlist = @tmpmemlist;
 | |
| 
 | |
|             if (!$isDefined)
 | |
|             {
 | |
| 
 | |
|                 # if the group type was not set then set it
 | |
|                 if (!$::FINALATTRS{$obj}{grouptype})
 | |
|                 {
 | |
|                     if ($::opt_d)
 | |
|                     {
 | |
|                         $::FINALATTRS{$obj}{grouptype} = 'dynamic';
 | |
|                         $::FINALATTRS{$obj}{members}   = 'dynamic';
 | |
|                         if (!$::FINALATTRS{$obj}{wherevals})
 | |
|                         {
 | |
|                             my $rsp;
 | |
|                             $rsp->{data}->[0] = "The \'where\' attributes and values were not provided for dynamic group \'$obj\'.";
 | |
|                             $rsp->{data}->[1] = "Skipping to the next group.";
 | |
|                             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                             $error = 1;
 | |
|                             next;
 | |
|                         }
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         $::FINALATTRS{$obj}{grouptype} = 'static';
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 # if this is a static group
 | |
|                 #    then update the "groups" attr of each member node
 | |
|                 if ($::FINALATTRS{$obj}{grouptype} eq 'static')
 | |
|                 {
 | |
| 
 | |
|                     # for each node in memberlist add this group
 | |
|                     # name to the groups attr of the node
 | |
|                     my %membhash;
 | |
|                     foreach my $n (@memberlist)
 | |
|                     {
 | |
| 
 | |
|                         $membhash{$n}{groups}  = $obj;
 | |
|                         $membhash{$n}{objtype} = 'node';
 | |
|                     }
 | |
|                     $::plus_option  = 1;
 | |
|                     $::minus_option = 0;
 | |
|                     if (xCAT::DBobjUtils->setobjdefs(\%membhash) != 0)
 | |
|                     {
 | |
|                         $error = 1;
 | |
|                     }
 | |
|                     $::plus_option = 0;
 | |
| 
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             else
 | |
|             {    # group is defined
 | |
| 
 | |
|                 # if a list of members is provided then update the node entries
 | |
|                 #   note: the members attr of the group def will be set
 | |
|                 #    to static
 | |
|                 if (@memberlist)
 | |
|                 {
 | |
| 
 | |
|                     #  options supported
 | |
|                     if ($::opt_m)
 | |
|                     {    # removing these members
 | |
| 
 | |
|                         # for each node in memberlist - remove this group
 | |
|                         #  from the groups attr
 | |
|                         my %membhash;
 | |
|                         foreach my $n (@memberlist)
 | |
|                         {
 | |
|                             $membhash{$n}{groups}  = $obj;
 | |
|                             $membhash{$n}{objtype} = 'node';
 | |
|                         }
 | |
| 
 | |
|                         $::plus_option  = 0;
 | |
|                         $::minus_option = 1;
 | |
|                         if (xCAT::DBobjUtils->setobjdefs(\%membhash) != 0)
 | |
|                         {
 | |
|                             $error = 1;
 | |
|                         }
 | |
|                         $::minus_option = 0;
 | |
| 
 | |
|                     }
 | |
|                     elsif ($::opt_p)
 | |
|                     {    #adding these new members
 | |
|                             # for each node in memberlist add this group
 | |
|                             # name to the groups attr
 | |
|                         my %membhash;
 | |
|                         foreach my $n (@memberlist)
 | |
|                         {
 | |
|                             $membhash{$n}{groups}  = $obj;
 | |
|                             $membhash{$n}{objtype} = 'node';
 | |
|                         }
 | |
|                         $::plus_option  = 1;
 | |
|                         $::minus_option = 0;
 | |
|                         if (xCAT::DBobjUtils->setobjdefs(\%membhash) != 0)
 | |
|                         {
 | |
|                             $error = 1;
 | |
|                         }
 | |
|                         $::plus_option = 0;
 | |
| 
 | |
|                     }
 | |
|                     else
 | |
|                     {    # replace the members list altogether
 | |
| 
 | |
|                         # this is the default for the chdef command
 | |
|                         if ($firsttime) {
 | |
| 
 | |
|                             # get the current members list
 | |
| 
 | |
|                             $grphash{$obj}{'grouptype'} = "static";
 | |
|                             my $list =
 | |
|                               xCAT::DBobjUtils->getGroupMembers($obj, \%grphash);
 | |
|                             my @currentlist = split(',', $list);
 | |
| 
 | |
|                             # for each node in currentlist - remove group name
 | |
|                             #    from groups attr
 | |
| 
 | |
|                             my %membhash;
 | |
|                             foreach my $n (@currentlist)
 | |
|                             {
 | |
|                                 $membhash{$n}{groups}  = $obj;
 | |
|                                 $membhash{$n}{objtype} = 'node';
 | |
|                             }
 | |
| 
 | |
|                             $::plus_option  = 0;
 | |
|                             $::minus_option = 1;
 | |
| 
 | |
| 
 | |
|                             if (xCAT::DBobjUtils->setobjdefs(\%membhash) != 0)
 | |
|                             {
 | |
|                                 $error = 1;
 | |
|                             }
 | |
|                             $firsttime = 0;
 | |
|                         }    # end - first time
 | |
|                         $::minus_option = 0;
 | |
| 
 | |
|                         # for each node in memberlist add this group
 | |
|                         # name to the groups attr
 | |
| 
 | |
|                         my %membhash;
 | |
|                         foreach my $n (@memberlist)
 | |
|                         {
 | |
|                             $membhash{$n}{groups}  = $obj;
 | |
|                             $membhash{$n}{objtype} = 'node';
 | |
|                         }
 | |
|                         $::plus_option  = 1;
 | |
|                         $::minus_option = 0;
 | |
| 
 | |
| 
 | |
|                         if (xCAT::DBobjUtils->setobjdefs(\%membhash) != 0)
 | |
|                         {
 | |
|                             $error = 1;
 | |
|                         }
 | |
|                         $::plus_option = 0;
 | |
| 
 | |
|                     }
 | |
| 
 | |
|                 }    # end - if memberlist
 | |
| 
 | |
|             }    # end - if group is defined
 | |
| 
 | |
|         }    # end - if group type
 | |
|         if ($type eq 'osimage' && !$::opt_m && !$::opt_p && $::opt_setattr && exists($attrhash{$obj})) {
 | |
|             foreach my $tmp_attr (@img_attrs) {
 | |
|                 if (!exists($::FINALATTRS{$obj}{$tmp_attr}) && exists($attrhash{$obj}{$tmp_attr}) &&
 | |
|                     defined($attrhash{$obj}{$tmp_attr})) {
 | |
|                     $::FINALATTRS{$obj}{$tmp_attr} = $attrhash{$obj}{$tmp_attr};
 | |
|                 }
 | |
|             }
 | |
|             my $rc = &parse_attr_for_osimage($::command, $::FINALATTRS{$obj});
 | |
| 
 | |
|             if ($rc) {
 | |
|                 next;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         # Removed the code to handle the nodegroup table with chdef -t node groups=xxx
 | |
|         # Only dynamic groups should be in nodegroup table
 | |
|         # Do not try to add static group into the nodegroup table
 | |
|         # performance!!!!
 | |
| 
 | |
|         #special case for osimage, if the osimage was not defined,
 | |
|         #chdef can not create it correctly if no attribute in osimage table is defined
 | |
|         #set the default imagetype 'NIM' if it is not specified
 | |
|         if ((!$isDefined) && ($type eq 'osimage') && (!defined($::FINALATTRS{$obj}{imagetype})))
 | |
|         {
 | |
|             $::FINALATTRS{$obj}{imagetype} = 'NIM';
 | |
|         }
 | |
| 
 | |
|     }    # end - for each object to update
 | |
| 
 | |
|     #
 | |
|     #  write each object into the tables in the xCAT database
 | |
|     #
 | |
| 
 | |
|     # set update option
 | |
|     $::plus_option  = 0;
 | |
|     $::minus_option = 0;
 | |
|     if ($::opt_p)
 | |
|     {
 | |
|         $::plus_option = 1;
 | |
|     }
 | |
|     elsif ($::opt_m)
 | |
|     {
 | |
|         $::minus_option = 1;
 | |
|     }
 | |
| 
 | |
|     if (xCAT::DBobjUtils->setobjdefs(\%::FINALATTRS) != 0)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Could not write data to the xCAT database.";
 | |
| 
 | |
|         #        xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         $error = 1;
 | |
|     }
 | |
| 
 | |
|     if ($error)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "One or more errors occured when attempting to create or modify xCAT \nobject definitions.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         my $nodenum = 0;
 | |
|         my $ret = 0;
 | |
|         my @nodes_updated = ();
 | |
|         foreach my $node (keys %::FINALATTRS) {
 | |
|             if ($::FINALATTRS{$node}{updated}) {
 | |
|                 $nodenum++;
 | |
|                 push @nodes_updated, $node;
 | |
|             }
 | |
|             if ($::FINALATTRS{$node}{error}) {
 | |
|                 $ret = 1;
 | |
|             }
 | |
|         }
 | |
|         if ($::verbose)
 | |
|         {
 | |
| 
 | |
|             #  give results
 | |
|             my $rsp;
 | |
|             if ($nodenum) {
 | |
|                 $rsp->{data}->[0] = "The database was updated for the following objects:";
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
| 
 | |
|                 my $n = 1;
 | |
|                 foreach my $o (sort(@nodes_updated))
 | |
|                 {
 | |
|                     $rsp->{data}->[$n] = "$o\n";
 | |
|                     $n++;
 | |
|                 }
 | |
|             } else {
 | |
|                 $rsp->{data}->[0] = "No database was updated";
 | |
|             }
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             my $rsp;
 | |
| 
 | |
|             if ($nodenum) {
 | |
|                 $rsp->{data}->[0] = "$nodenum object definitions have been created or modified.";
 | |
|             } else {
 | |
|                 $rsp->{data}->[0] = "No object definitions have been created or modified.";
 | |
|             }
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             if (scalar(keys %newobjects) > 0)
 | |
|             {
 | |
|                 my $newobj          = ();
 | |
|                 my $invalidnodename = ();
 | |
|                 foreach my $node (keys %newobjects) {
 | |
|                     if (($node =~ /[A-Z]/) && (((!$::opt_t) && (!$::FILEATTRS{$node}{'objtype'})) || ($::FILEATTRS{$node}{'objtype'} eq "node") || ($::opt_t eq "node"))) {
 | |
|                         $invalidnodename .= ",$node";
 | |
|                     }
 | |
|                     $newobj .= ",$node";
 | |
|                 }
 | |
| 
 | |
|                 if ($newobj) {
 | |
|                     $newobj =~ s/,//;
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "New object definitions \'$newobj\' have been created.";
 | |
|                     xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                 }
 | |
|                 if ($invalidnodename) {
 | |
|                     $invalidnodename =~ s/,//;
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "The node name \'$invalidnodename\' contains capital letters which may not be resolved correctly by the dns server.";
 | |
|                     xCAT::MsgUtils->message("W", $rsp, $::callback);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return $ret;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3   setFINALattrs
 | |
| 
 | |
|         create %::FINALATTRS{objname}{attr}=val hash
 | |
|         conbines %::FILEATTRS, and %::CLIATTR
 | |
| 
 | |
|         Arguments:
 | |
| 
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| sub setFINALattrs
 | |
| {
 | |
| 
 | |
|     my $error = 0;
 | |
| 
 | |
|     # set the final hash based on the info from the file hash and cmd line hash
 | |
|     @::finalTypeList = ();
 | |
| 
 | |
|     # set the final hash based on the info from the input file
 | |
|     if (@::fileobjnames)
 | |
|     {
 | |
|         foreach my $objname (@::fileobjnames)
 | |
|         {
 | |
| 
 | |
|             #  check if this object is one of the type specified
 | |
|             if (@::clobtypes)
 | |
|             {
 | |
|                 if (!grep(/^$::FILEATTRS{$objname}{objtype}$/, @::clobtypes))
 | |
|                 {
 | |
|                     next;
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|             # get the data type definition from Schema.pm
 | |
| 
 | |
|             if (!$::FILEATTRS{$objname}{objtype}) {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "\nNo objtype value was specified for \'$objname\'. Cannot create object definition.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 $error = 1;
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             # special case for the nic* attributes
 | |
|             # merge nic*.eth0, nic*.eth1
 | |
|             if (($::FILEATTRS{$objname}{objtype} eq 'node') || ($::FILEATTRS{$objname}{objtype} eq 'group'))
 | |
|             {
 | |
|                 xCAT::DBobjUtils->collapsenicsattr($::FILEATTRS{$objname}, $objname);
 | |
|             }
 | |
| 
 | |
|             my $datatype =
 | |
|               $xCAT::Schema::defspec{ $::FILEATTRS{$objname}{objtype} };
 | |
|             my @list;
 | |
|             foreach my $this_attr (sort @{ $datatype->{'attrs'} })
 | |
|             {
 | |
|                 my $a = $this_attr->{attr_name};
 | |
|                 push(@list, $a);
 | |
|             }
 | |
|             push(@list, "objtype");
 | |
| 
 | |
|             # if so then add it to the final hash
 | |
|             foreach my $attr (keys %{ $::FILEATTRS{$objname} })
 | |
|             {
 | |
| 
 | |
|                 # see if valid attr
 | |
|                 if (!grep(/^$attr$/, @list) && ($::FILEATTRS{$objname}{objtype} ne 'site') && ($::FILEATTRS{$objname}{objtype} ne 'monitoring'))
 | |
|                 {
 | |
| 
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "\'$attr\' is not a valid attribute name for an object type of \'$::objtype\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     $error = 1;
 | |
|                     next;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     $::FINALATTRS{$objname}{$attr} =
 | |
|                       $::FILEATTRS{$objname}{$attr};
 | |
|                     if ($attr eq 'objtype')
 | |
|                     {
 | |
|                         if (!grep(/^$::FINALATTRS{$objname}{objtype}$/, @::finalTypeList))
 | |
|                         {
 | |
|                             my $type = $::FINALATTRS{$objname}{objtype};
 | |
|                             chomp $type;
 | |
|                             push @::finalTypeList, $type;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|             # need to make sure the node attr is set otherwise nothing
 | |
|             #    gets set in the nodelist table
 | |
|             if ($::FINALATTRS{$objname}{objtype} eq "node") {
 | |
|                 $::FINALATTRS{$objname}{node} = $objname;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     foreach my $objname (@::clobjnames)
 | |
|     {
 | |
|         # special case for the nic* attributes
 | |
|         # merge nic*.eth0, nic*.eth1
 | |
|         unless (exists($::CLIATTRS{$objname})) {
 | |
|             next;
 | |
|         }
 | |
|         if (($::CLIATTRS{$objname}{objtype} eq 'node') || ($::CLIATTRS{$objname}{objtype} eq 'group'))
 | |
|         {
 | |
|             # Even if only the nicips.eth0 is specified with CLI,
 | |
|             # need to read the whole nicips attribute from the nics table,
 | |
|             # then merge the nicips.eth0 into the nicips attribute,
 | |
|             my %tmphash = ();
 | |
|             foreach my $nodeattr (keys %{ $::CLIATTRS{$objname} })
 | |
|             {
 | |
|                 if ($nodeattr =~ /^(nic\w+)\..*$/)
 | |
|                 {
 | |
|                     my $tmpnicattr = $1;
 | |
|                     if (!defined($tmphash{$tmpnicattr}))
 | |
|                     {
 | |
|                         my $nicstable = xCAT::Table->new("nics", -create => 1, -autocommit => 0);
 | |
|                         if (!$nicstable) {
 | |
|                             my $rsp;
 | |
|                             $rsp->{data}->[0] = "Could not open the \'nics\' table.";
 | |
|                             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                             return 1;
 | |
|                         }
 | |
|                         my $nichash = $nicstable->getNodeAttribs($objname, [$tmpnicattr]);
 | |
|                         if ($nichash && $nichash->{$tmpnicattr})
 | |
|                         {
 | |
|                             $tmphash{$tmpnicattr} = $nichash->{$tmpnicattr};
 | |
|                         }
 | |
|                         $nicstable->close();
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             # $tmphash{nicips} = "eth0!1.1.1.1|1.2.1.1,eth1!2.1.1.1|2.2.1.1"
 | |
|             foreach my $nicattr (keys %tmphash)
 | |
|             {
 | |
|                 # eth0!1.1.1.1|1.2.1.1,eth1!2.1.1.1|2.2.1.1
 | |
|                 my $nicval = $tmphash{$nicattr};
 | |
|                 my @nicarray = split(/,/, $nicval);
 | |
|                 foreach my $nicv (@nicarray)
 | |
|                 {
 | |
|                     my @nica = split(/!/, $nicv);
 | |
| 
 | |
|                     # put the additional nicips.eth1, nicips.eth2 into %::CLIATTRS
 | |
|                     if (!defined $::CLIATTRS{$objname}{"$nicattr.$nica[0]"})
 | |
|                     {
 | |
|                         $::CLIATTRS{$objname}{"$nicattr.$nica[0]"} = $nica[1];
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             xCAT::DBobjUtils->collapsenicsattr($::CLIATTRS{$objname}, $objname);
 | |
|         }
 | |
| 
 | |
|         foreach my $attr (keys %{ $::CLIATTRS{$objname} })
 | |
|         {
 | |
| 
 | |
|             $::FINALATTRS{$objname}{$attr} = $::CLIATTRS{$objname}{$attr};
 | |
|             if ($attr eq 'objtype')
 | |
|             {
 | |
|                 if (
 | |
|                     !grep(/^$::FINALATTRS{$objname}{objtype}$/, @::finalTypeList)
 | |
|                   )
 | |
|                 {
 | |
|                     my $type = $::FINALATTRS{$objname}{objtype};
 | |
|                     chomp $type;
 | |
|                     push @::finalTypeList, $type;
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         # need to make sure the node attr is set otherwise nothing
 | |
|         #   gets set in the nodelist table
 | |
|         if ($::FINALATTRS{$objname}{objtype} eq "node") {
 | |
|             $::FINALATTRS{$objname}{node} = $objname;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($error)
 | |
|     {
 | |
|         return 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         return 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3   defls
 | |
| 
 | |
|         Support for the xCAT defls command.
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
|             Object names derived from -o, -t, w, -a or noderange!
 | |
|             List of attrs to display is given by -i.
 | |
|             Output goes to standard out or a stanza/xml file (-z or -x)
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defls
 | |
| {
 | |
|     my $long = 0;
 | |
|     my %myhash;
 | |
|     my %objhash;
 | |
| 
 | |
|     my @objectlist;
 | |
| 
 | |
|     #    @::allobjnames;
 | |
|     my @displayObjList;
 | |
| 
 | |
|     my $numtypes = 0;
 | |
|     my $rsp_info;
 | |
| 
 | |
|     # process the command line
 | |
|     my $rc = &processArgs;
 | |
|     if ($rc != 0)
 | |
|     {
 | |
| 
 | |
|         # rc: 0 - ok, 1 - return, 2 - help, 3 - error
 | |
|         # 0 - continue
 | |
|         # 1 - return  (like for version option)
 | |
|         # 2 - return with usage
 | |
|         # 3 - return error
 | |
|         if ($rc == 1) {
 | |
|             return 0;
 | |
|         } elsif ($rc == 2) {
 | |
|             &defls_usage;
 | |
|             return 0;
 | |
|         } elsif ($rc == 3) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # do we want just the object names or all the attr=val
 | |
|     if ($::opt_l || @::noderange || $::opt_o || $::opt_i || $::opt_template)
 | |
|     {
 | |
| 
 | |
|         # assume we want the the details - not just the names
 | |
|         #     - if provided object names or noderange
 | |
|         $long++;
 | |
| 
 | |
|     }
 | |
|     if ($::opt_s) {
 | |
|         $long = 0;
 | |
|     }
 | |
| 
 | |
|     # which attrs do we want?
 | |
|     # this is a temp hack to help scaling when you only
 | |
|     #   want a list of nodes - needs to be fully implemented
 | |
|     if ($::opt_l || $::opt_w) {
 | |
| 
 | |
|         # if long or -w then get all the attrs
 | |
|         $::ATTRLIST = "all";
 | |
|     } elsif ($::opt_i) {
 | |
| 
 | |
|         # is -i then just get the ones in the list
 | |
|         $::ATTRLIST = $::opt_i;
 | |
|     } elsif (@::noderange || $::opt_o) {
 | |
| 
 | |
|         # if they gave a list of objects then they must want more
 | |
|         # than the object names!
 | |
|         if ($::opt_s) {
 | |
|             $::ATTRLIST = "none";
 | |
|         } else {
 | |
|             $::ATTRLIST = "all";
 | |
|         }
 | |
|     } else {
 | |
| 
 | |
|         # otherwise just get a list of object names
 | |
|         $::ATTRLIST = "none";
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     #    put together a hash with the list of objects and the associated types
 | |
|     #          - need to figure out which objects to look up
 | |
|     #
 | |
| 
 | |
|     # if a set of objects was provided on the cmd line then there can
 | |
|     #    be only one type value
 | |
| 
 | |
|     # Figure out the attributes that needed in the def operation
 | |
|     my @neededattrs = ();
 | |
|     if ($::opt_i) {
 | |
|         @neededattrs = (@neededattrs, @::AttrList);
 | |
|         if ($::opt_w) {
 | |
|             my @whereattrs = keys %::WhereHash;
 | |
|             @neededattrs = (@neededattrs, @whereattrs);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (defined $::opt_template) {
 | |
|         unless ($::opt_template) {
 | |
| 
 | |
|             #when the "--template" option is specified, but no object template is specified
 | |
|             %myhash = %::FILEATTRS;
 | |
|         } else {
 | |
| 
 | |
|             #some object template are specified
 | |
|             my @templatelist = split(",", $::opt_template);
 | |
|             foreach my $mytemplate (@templatelist) {
 | |
|                 if (exists $::FILEATTRS{$mytemplate}) {
 | |
|                     $myhash{$mytemplate} = \%{ $::FILEATTRS{$mytemplate} };
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if ($::objectsfrom_opto || $::objectsfrom_nr || $::objectsfrom_args)
 | |
|     {
 | |
|         my $type = $::clobjtypes[0];
 | |
| 
 | |
|         $numtypes = 1;
 | |
| 
 | |
|         foreach my $obj (sort @::clobjnames)
 | |
|         {
 | |
|             $objhash{$obj} = $type;
 | |
| 
 | |
|         }
 | |
| 
 | |
|         %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash, $::VERBOSE, \@neededattrs);
 | |
|         if (!(%myhash))
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Could not get xCAT object definitions.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 1;
 | |
| 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #  if just provided type list then find all objects of these types
 | |
|     if (!defined $::opt_template && $::objectsfrom_optt)
 | |
|     {
 | |
|         %objhash = %::ObjTypeHash;
 | |
| 
 | |
|         %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash, $::VERBOSE, \@neededattrs);
 | |
|         if (!(%myhash))
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Could not get xCAT object definitions.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # if specify all
 | |
|     if ($::opt_a)
 | |
|     {
 | |
|         if (!defined $::opt_template) {
 | |
| 
 | |
|             # could be modified by type
 | |
|             if ($::opt_t)
 | |
|             {
 | |
|                 # get all objects matching type list
 | |
|                 # Get all object in this type list
 | |
|                 foreach my $t (@::clobjtypes)
 | |
|                 {
 | |
|                     my @tmplist = xCAT::DBobjUtils->getObjectsOfType($t);
 | |
| 
 | |
|                     if (scalar(@tmplist) > 1)
 | |
|                     {
 | |
|                         foreach my $obj (@tmplist)
 | |
|                         {
 | |
| 
 | |
|                             $objhash{$obj} = $t;
 | |
|                         }
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "Could not get objects of type \'$t\'.";
 | |
|                         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash);
 | |
|                 if (!(%myhash))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Could not get xCAT object definitions.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     return 1;
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             else
 | |
|             {
 | |
| 
 | |
|                 %myhash = xCAT::DBobjUtils->getobjdefs(\%::AllObjTypeHash, $::VERBOSE);
 | |
|                 if (!(%myhash))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Could not get xCAT object definitions.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     return 1;
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             foreach my $t (keys %{xCAT::Schema::defspec})
 | |
|             {
 | |
|                 push(@::clobjtypes, $t);
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             #push the unique object types from @::fileobjtypes to @::clobjtypes
 | |
|             my %objtypehash = map { $_ => 1 } @::fileobjtypes;
 | |
|             push @::clobjtypes, keys(%objtypehash);
 | |
|         }
 | |
|     }    # end - if specify all
 | |
| 
 | |
| 
 | |
|     if (!(%myhash))
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "Could not find any objects to display.";
 | |
|         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     # need a special case for the node postscripts attribute,
 | |
|     # The 'xcatdefaults' postscript should be added to the postscripts and postbootscripts attribute
 | |
|     my $getnodes = 0;
 | |
|     if (!$::opt_z) {    #if -z flag is specified, do not add the xcatdefaults
 | |
|         foreach my $objtype (@::clobjtypes)
 | |
|         {
 | |
|             if ($objtype eq 'node')
 | |
|             {
 | |
|                 $getnodes = 1;
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     my %nodeosimagehash = ();
 | |
|     if ($getnodes)
 | |
|     {
 | |
|         # Show osimage information
 | |
|         if ($::opt_osimg)
 | |
|         {
 | |
|             my %nodeosimgname;
 | |
|             my %imghash;
 | |
|             my %imglist;
 | |
|             my %tmpprofilelist;
 | |
| 
 | |
|             # get the site.installdir for osimage searching with nodes prvomethod= install/netboot/statelite
 | |
|             # it might not be used at all, but should not do this for each node
 | |
|             my $installroot = "/install";
 | |
|             my @ents     = xCAT::TableUtils->get_site_attribute("installdir");
 | |
|             my $site_ent = $ents[0];
 | |
|             if (defined($site_ent))
 | |
|             {
 | |
|                 $installroot = $site_ent;
 | |
|             }
 | |
| 
 | |
|             foreach my $obj (keys %myhash)
 | |
|             {
 | |
|                 if ($myhash{$obj}{'objtype'} eq 'node')
 | |
|                 {
 | |
|                     my $osimagename;
 | |
| 
 | |
|                     #provmethod can be set to osimage name
 | |
|                     if ($myhash{$obj}{'provmethod'} && ($myhash{$obj}{'provmethod'} ne 'install')
 | |
|                         && ($myhash{$obj}{'provmethod'} ne 'netboot') && ($myhash{$obj}{'provmethod'} ne 'statelite'))
 | |
|                     {
 | |
|                         $osimagename = $myhash{$obj}{'provmethod'};
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         # prvomethod = install/netboot/statelite,
 | |
|                         # search /opt/xcat/share/xcat/<provmethod/<platform>
 | |
|                         # and /install/custom/<provmethod/<platform>
 | |
|                         my $profile    = $myhash{$obj}{'profile'};
 | |
|                         my $os         = $myhash{$obj}{'os'};
 | |
|                         my $arch       = $myhash{$obj}{'arch'};
 | |
|                         my $provmethod = $myhash{$obj}{'provmethod'};
 | |
| 
 | |
|                         # tmp hash for performance considerations,
 | |
|                         # do not search paths for each node.
 | |
|                         if (defined($tmpprofilelist{$os}{$arch}{$provmethod}{$profile}))
 | |
|                         {
 | |
|                             $nodeosimagehash{$obj}{'template'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'template'};
 | |
|                             $nodeosimagehash{$obj}{'pkglist'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'pkglist'};
 | |
|                             $nodeosimagehash{$obj}{'otherpkglist'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'otherpkglist'};
 | |
|                             $nodeosimagehash{$obj}{'postinstall'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'postinstall'};
 | |
|                             $nodeosimagehash{$obj}{'extlist'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'extlist'};
 | |
|                             $nodeosimagehash{$obj}{'synclists'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'synclists'};
 | |
|                             $nodeosimagehash{$obj}{'pkgdir'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'pkgdir'};
 | |
|                             $nodeosimagehash{$obj}{'otherpkgdir'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'otherpkgdir'};
 | |
|                             $nodeosimagehash{$obj}{'rootimgdir'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'rootimgdir'};
 | |
|                             $nodeosimagehash{$obj}{'osvers'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'osvers'};
 | |
|                             $nodeosimagehash{$obj}{'osarch'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'osarch'};
 | |
|                             $nodeosimagehash{$obj}{'imagetype'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'imagetype'};
 | |
|                             $nodeosimagehash{$obj}{'osname'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'osname'};
 | |
|                             $nodeosimagehash{$obj}{'profile'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'profile'};
 | |
|                             $nodeosimagehash{$obj}{'provmethod'} = $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'provmethod'};
 | |
|                             next;
 | |
|                         }
 | |
|                         if ($myhash{$obj}{'os'} && $myhash{$obj}{'arch'}
 | |
|                             && $myhash{$obj}{'provmethod'} && $myhash{$obj}{'profile'})
 | |
|                         {
 | |
|                             #$osimagename = "$myhash{$obj}{'os'}-$myhash{$obj}{'arch'}-$myhash{$obj}{'provmethod'}-$myhash{$obj}{'profile'}";
 | |
|                             my $platform = xCAT::SvrUtils->getplatform($myhash{$obj}{'os'});
 | |
|                             my $pm = $myhash{$obj}{'provmethod'};
 | |
|                             if ($pm eq 'statelite') { $pm = 'netboot'; }
 | |
|                             my $custpath = "$installroot/custom/$pm/$platform";
 | |
|                             my $defpath = "$::XCATROOT/share/xcat/$pm/$platform";
 | |
| 
 | |
|                             $nodeosimagehash{$obj}{'osvers'} = $os;
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'osvers'} = $os;
 | |
|                             $nodeosimagehash{$obj}{'osarch'} = $arch;
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'osarch'} = $arch;
 | |
|                             $nodeosimagehash{$obj}{'imagetype'} = "linux";
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'imagetype'} = "linux";
 | |
|                             $nodeosimagehash{$obj}{'osname'} = "Linux";
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'osname'} = "Linux";
 | |
|                             $nodeosimagehash{$obj}{'profile'} = $profile;
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'profile'} = $profile;
 | |
|                             $nodeosimagehash{$obj}{'provmethod'} = $provmethod;
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'provmethod'} = $provmethod;
 | |
| 
 | |
|                             # pkgdir both diskful and diskless
 | |
|                             $nodeosimagehash{$obj}{'pkgdir'} = "$installroot/$os/$arch";
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'pkgdir'} = "$installroot/$os/$arch";
 | |
| 
 | |
|                             # rootimgdir only for diskless
 | |
|                             if (($provmethod eq 'netboot') || ($provmethod eq 'statelite'))
 | |
|                             {
 | |
|                                 $nodeosimagehash{$obj}{'rootimgdir'} = "$installroot/netboot/$os/$arch/$profile";
 | |
|                                 $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'rootimgdir'} = "$installroot/netboot/$os/$arch/$profile";
 | |
|                             }
 | |
| 
 | |
|                             # otherpkgdir for both diskful and diskless
 | |
|                             $nodeosimagehash{$obj}{'otherpkgdir'} = "$installroot/post/otherpkgs/$os/$arch";
 | |
|                             $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'otherpkgdir'} = "$installroot/post/otherpkgs/$os/$arch";
 | |
| 
 | |
|                             # template file only for diskful
 | |
|                             if ($provmethod eq 'install')
 | |
|                             {
 | |
|                                 my $tmplfile = xCAT::SvrUtils->get_tmpl_file_name($custpath, $profile, $os, $arch, $os);
 | |
|                                 if (!$tmplfile)
 | |
|                                 {
 | |
|                                     $tmplfile = xCAT::SvrUtils->get_tmpl_file_name($defpath, $profile, $os, $arch, $os);
 | |
|                                 }
 | |
|                                 if ($tmplfile)
 | |
|                                 {
 | |
|                                     $nodeosimagehash{$obj}{'template'} = $tmplfile;
 | |
|                                     $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'template'} = $tmplfile;
 | |
|                                 }
 | |
|                             }
 | |
| 
 | |
|                             # pkglist for both diskful and diskless
 | |
|                             my $pkglistfile = xCAT::SvrUtils->get_pkglist_file_name($custpath, $profile, $os, $arch, $os);
 | |
|                             if (!$pkglistfile)
 | |
|                             {
 | |
|                                 $pkglistfile = xCAT::SvrUtils->get_pkglist_file_name($defpath, $profile, $os, $arch, $os);
 | |
|                             }
 | |
|                             if ($pkglistfile)
 | |
|                             {
 | |
|                                 $nodeosimagehash{$obj}{'pkglist'} = $pkglistfile;
 | |
|                                 $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'pkglist'} = $pkglistfile;
 | |
|                             }
 | |
| 
 | |
|                             #otherpkglist for both diskful and diskless
 | |
|                             my $otherpkgsfile = xCAT::SvrUtils->get_otherpkgs_pkglist_file_name($custpath, $profile, $os, $arch);
 | |
|                             if (!$otherpkgsfile)
 | |
|                             {
 | |
|                                 $otherpkgsfile = xCAT::SvrUtils->get_otherpkgs_pkglist_file_name($defpath, $profile, $os, $arch);
 | |
|                             }
 | |
|                             if ($otherpkgsfile)
 | |
|                             {
 | |
|                                 $nodeosimagehash{$obj}{'otherpkglist'} = $otherpkgsfile;
 | |
|                                 $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'otherpkglist'} = $otherpkgsfile;
 | |
|                             }
 | |
| 
 | |
|                             # postinstall and exlist only for diskless
 | |
|                             if (($provmethod eq 'netboot') || ($provmethod eq 'statelite'))
 | |
|                             {
 | |
|                                 # Get postinstall file
 | |
|                                 my $postfile = xCAT::SvrUtils->get_postinstall_file_name($custpath, $profile, $os, $arch);
 | |
|                                 if (!$postfile)
 | |
|                                 {
 | |
|                                     $postfile = xCAT::SvrUtils->get_postinstall_file_name($defpath, $profile, $os, $arch);
 | |
|                                 }
 | |
|                                 if ($postfile)
 | |
|                                 {
 | |
|                                     $nodeosimagehash{$obj}{'postinstall'} = $postfile;
 | |
|                                     $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'postinstall'} = $postfile;
 | |
|                                 }
 | |
| 
 | |
|                                 # Get exclude list
 | |
|                                 my $extfile = xCAT::SvrUtils->get_exlist_file_name($custpath, $profile, $os, $arch);
 | |
|                                 if (!$extfile)
 | |
|                                 {
 | |
|                                     $extfile = xCAT::SvrUtils->get_exlist_file_name($defpath, $profile, $os, $arch);
 | |
|                                 }
 | |
|                                 if ($extfile)
 | |
|                                 {
 | |
|                                     $nodeosimagehash{$obj}{'extlist'} = $extfile;
 | |
|                                     $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'extlist'} = $extfile;
 | |
|                                 }
 | |
|                             }
 | |
| 
 | |
|                             # Get synclist
 | |
|                             my $synclist = xCAT::SvrUtils->getsynclistfile(undef, $os, $arch, $profile, $provmethod);
 | |
|                             if ($synclist)
 | |
|                             {
 | |
|                                 $nodeosimagehash{$obj}{'synclists'} = $synclist;
 | |
|                                 $tmpprofilelist{$os}{$arch}{$provmethod}{$profile}{'synclists'} = $synclist;
 | |
|                             }
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             my $rsp;
 | |
|                             $rsp->{data}->[0] = "Missing attributes for node $obj, check the node attributes \'os\', \'arch\',\'profile\' and \'provmethod\'.";
 | |
|                             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                             next;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     # do not call xCAT::DBobjUtils->getobjdefs for each object
 | |
|                     # for performance consideration
 | |
|                     if ($osimagename)
 | |
|                     {
 | |
|                         if (!defined($imglist{$osimagename}))
 | |
|                         {
 | |
|                             $imglist{$osimagename} = 'osimage';
 | |
|                         }
 | |
|                         $nodeosimgname{$obj} = $osimagename;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
| 
 | |
| 
 | |
|             # Get osimage definition info in one invocation
 | |
|             if (scalar(keys %imglist) > 0)
 | |
|             {
 | |
|                 my @attrs = ();
 | |
|                 %imghash = xCAT::DBobjUtils->getobjdefs(\%imglist, 0, \@attrs);
 | |
|             }
 | |
| 
 | |
|             # Put the osimage definition in %nodeosimagehash
 | |
|             foreach my $obj (keys %myhash)
 | |
|             {
 | |
|                 if ($myhash{$obj}{'objtype'} eq 'node')
 | |
|                 {
 | |
|                     my $imgname = $nodeosimgname{$obj};
 | |
|                     if ($imgname && defined($imghash{$imgname}))
 | |
|                     {
 | |
|                         my %imgentry = %{ $imghash{$imgname} };
 | |
|                         foreach my $imgattr (keys %imgentry)
 | |
|                         {
 | |
|                             # Only store the attributes that are not in general node attributes
 | |
|                             # This is not the right thing to do, list all the osimage attributes instead,
 | |
|                             # like the postscripts and postbootscripts attributes,
 | |
|                             #if(!defined($myhash{$obj}{$imgattr}) && defined($imgentry{$imgattr}))
 | |
|                             #{
 | |
|                             $nodeosimagehash{$obj}{$imgattr} = $imgentry{$imgattr};
 | |
| 
 | |
|                             #}
 | |
|                         }
 | |
|                     }
 | |
|                     if (scalar(keys %{ $nodeosimagehash{$obj} }) == 0)
 | |
|                     {
 | |
|                         my $rsp;
 | |
|                         $rsp->{data}->[0] = "$obj: could not find information for osimage $nodeosimgname{$obj}";
 | |
|                         xCAT::MsgUtils->message("W", $rsp, $::callback);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         my $xcatdefaultsps;
 | |
|         my $xcatdefaultspbs;
 | |
|         my @TableRowArray = xCAT::DBobjUtils->getDBtable('postscripts');
 | |
|         if (@TableRowArray)
 | |
|         {
 | |
|             foreach my $tablerow (@TableRowArray)
 | |
|             {
 | |
|                 if (($tablerow->{node} eq 'xcatdefaults') && !($tablerow->{disable}))
 | |
|                 {
 | |
|                     $xcatdefaultsps  = $tablerow->{postscripts};
 | |
|                     $xcatdefaultspbs = $tablerow->{postbootscripts};
 | |
|                     last;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         foreach my $obj (keys %myhash)
 | |
|         {
 | |
|             if ($myhash{$obj}{objtype} eq 'node')
 | |
|             {
 | |
|                 if ($xcatdefaultsps)
 | |
|                 {
 | |
|                     if ($myhash{$obj}{postscripts})
 | |
|                     {
 | |
|                         $myhash{$obj}{postscripts} = $xcatdefaultsps . ',' . $myhash{$obj}{postscripts};
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         $myhash{$obj}{postscripts} = $xcatdefaultsps;
 | |
|                         if ($::opt_V) {
 | |
|                             $myhash{$obj}{postscripts} .= "     (Table:postscripts - Key:node - Column:postscripts)";
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 if ($xcatdefaultspbs)
 | |
|                 {
 | |
|                     if ($myhash{$obj}{postbootscripts})
 | |
|                     {
 | |
|                         $myhash{$obj}{postbootscripts} = $xcatdefaultspbs . ',' . $myhash{$obj}{postbootscripts};
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         $myhash{$obj}{postbootscripts} = $xcatdefaultspbs;
 | |
|                     }
 | |
|                     if ($::opt_V && ($myhash{$obj}{postbootscripts} eq $xcatdefaultspbs))
 | |
|                     {
 | |
|                         $myhash{$obj}{postbootscripts} .= "       (Table:postscripts - Key:node - Column:postbootscripts)";
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # the list of objects may be limited by the "-w" option
 | |
|     # see which objects have attr/val that match the where values
 | |
|     #        - if provided
 | |
|     if ($::opt_w)
 | |
|     {
 | |
|         foreach my $obj (sort (keys %myhash))
 | |
|         {
 | |
|             if (xCAT::Utils->selection_string_match(\%myhash, $obj, \%::WhereHash)) {
 | |
|                 push(@displayObjList, $obj);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     # output in specified format
 | |
|     #
 | |
| 
 | |
|     my @foundobjlist;
 | |
| 
 | |
|     if ($::opt_z)
 | |
|     {
 | |
|         push(@{ $rsp_info->{data} }, "# <xCAT data object stanza file>");
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # group the objects by type to make the output easier to read
 | |
|     my $numobjects = 0;    # keep track of how many object we want to display
 | |
|                            # for each type
 | |
| 
 | |
|     foreach my $type (@::clobjtypes)
 | |
|     {
 | |
|         # Check if -i specifies valid attributes
 | |
|         # get the data type definition from Schema.pm
 | |
|         my %validattrslist;
 | |
|         if ($::opt_i)
 | |
|         {
 | |
|             my $datatype = $xCAT::Schema::defspec{$type};
 | |
|             foreach my $this_attr (sort @{ $datatype->{'attrs'} })
 | |
|             {
 | |
|                 my $a = $this_attr->{attr_name};
 | |
|                 $validattrslist{$a} = 1;
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         my %defhash;
 | |
| 
 | |
|         foreach my $obj (keys %myhash)
 | |
|         {
 | |
|             if ($obj)
 | |
|             {
 | |
|                 $numobjects++;
 | |
|                 if ($myhash{$obj}{'objtype'} eq $type)
 | |
|                 {
 | |
|                     $defhash{$obj} = $myhash{$obj};
 | |
| 
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ($numobjects == 0)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Could not find any object definitions to display.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         if ($type eq "node") {
 | |
|             my %newhash;
 | |
|             my $listtab = xCAT::Table->new('nodelist');
 | |
|             if (!$listtab) {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Could not open nodelist table.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 return 1;
 | |
|             }
 | |
| 
 | |
|             if (!defined($::opt_S)) {
 | |
|                 my @def_nodes = keys %defhash;
 | |
|                 my $hidden_nodes = $listtab->getNodesAttribs(\@def_nodes, ['hidden']);
 | |
|                 foreach my $n (keys %{$hidden_nodes}) {
 | |
|                     if (defined($hidden_nodes->{$n}->[0]->{'hidden'}) && $hidden_nodes->{$n}->[0]->{'hidden'} == 1) {
 | |
|                         delete $defhash{$n};
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         # Get all the objects of this type
 | |
|         my @allobjoftype;
 | |
|         @allobjoftype = xCAT::DBobjUtils->getObjectsOfType($type);
 | |
| 
 | |
|         unless (@allobjoftype)
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Could not find any objects of type \'$type\'.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         my @attrlist;
 | |
|         if (($type ne 'site') && ($type ne 'monitoring'))
 | |
|         {
 | |
|             # -i is specified
 | |
|             if (scalar(@::AttrList) > 0) {
 | |
|                 foreach my $attr (@::AttrList)
 | |
|                 {
 | |
|                     # For site and monitoring, does not check if -i attributes are valid
 | |
|                     if (($type eq 'site') || ($type eq 'monitoring'))
 | |
|                     {
 | |
|                         @attrlist = @::AttrList;
 | |
|                     } else {
 | |
|                         if (defined($validattrslist{$attr}))
 | |
|                         {
 | |
|                             if (!grep(/^$attr$/, @attrlist))
 | |
|                             {
 | |
|                                 push @attrlist, $attr;
 | |
|                             }
 | |
|                         } else {
 | |
|                             my $rsp;
 | |
|                             $rsp->{data}->[0] = "\'$attr\' is not a valid attribute name for an object type of \'$type\'.";
 | |
|                             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                             next;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             } else {
 | |
| 
 | |
|                 # get the list of all attrs for this type object
 | |
|                 # get the data type  definition from Schema.pm
 | |
|                 my $datatype =
 | |
|                   $xCAT::Schema::defspec{$type};
 | |
| 
 | |
|                 foreach my $this_attr (@{ $datatype->{'attrs'} })
 | |
|                 {
 | |
|                     if (!grep(/^$this_attr->{attr_name}$/, @attrlist)) {
 | |
|                         push(@attrlist, $this_attr->{attr_name});
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         # for each object
 | |
|         foreach my $obj (sort keys %defhash)
 | |
|         {
 | |
| 
 | |
|             unless ($obj)
 | |
|             {
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             #  Return if this obj does not match the filter string
 | |
|             if ($::opt_w)
 | |
|             {
 | |
|                 #  just display objects that match -w
 | |
|                 if (!grep /^$obj$/, @displayObjList)
 | |
|                 {
 | |
|                     next;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             # check the object names only if
 | |
|             # the object names are passed in through command line
 | |
|             if ($::objectsfrom_args || $::opt_o || (($type eq 'node') && ($::opt_o || @::noderange)))
 | |
|             {
 | |
|                 if (!grep(/^$obj$/, @allobjoftype))
 | |
|                 {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "Could not find an object named \'$obj\' of type \'$type\'.";
 | |
|                     xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                     next;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             # special handling for site table - for now !!!!!!!
 | |
|             if (($type eq 'site') || ($type eq 'monitoring'))
 | |
|             {
 | |
|                 foreach my $a (keys %{ $defhash{$obj} })
 | |
|                 {
 | |
|                     push(@attrlist, $a);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if ($::opt_x)
 | |
|             {
 | |
| 
 | |
|                 # TBD - do output in XML format
 | |
|             }
 | |
|             else
 | |
|             {
 | |
| 
 | |
|                 # display all data
 | |
|                 # do we want the short or long output?
 | |
|                 if ($long)
 | |
|                 {
 | |
|                     if ($::opt_z)
 | |
|                     {
 | |
|                         push(@{ $rsp_info->{data} }, "\n$obj:");
 | |
|                         push(@{ $rsp_info->{data} }, "    objtype=$defhash{$obj}{'objtype'}");
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         if ($#::clobjtypes > 0)
 | |
|                         {
 | |
|                             push(@{ $rsp_info->{data} }, "Object name: $obj  ($defhash{$obj}{'objtype'})");
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             if (!$::opt_c)
 | |
|                             {
 | |
|                                 push(@{ $rsp_info->{data} }, "Object name: $obj");
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     foreach my $showattr (sort @attrlist)
 | |
|                     {
 | |
|                         if ($showattr eq 'objtype')
 | |
|                         {
 | |
|                             next;
 | |
|                         }
 | |
| 
 | |
|                         my $attrval;
 | |
|                         if (exists($defhash{$obj}{$showattr}))
 | |
|                         {
 | |
|                             $attrval = $defhash{$obj}{$showattr};
 | |
|                         }
 | |
| 
 | |
|                         # if an attr list was provided then just display those
 | |
|                         if ($::opt_i)
 | |
|                         {
 | |
|                             if (grep (/^$showattr$/, @::AttrList))
 | |
|                             {
 | |
| 
 | |
|                                 if (($defhash{$obj}{'objtype'} eq 'group') && ($showattr eq 'members'))
 | |
|                                 {
 | |
|                                     my $memberlist =
 | |
|                                       xCAT::DBobjUtils->getGroupMembers(
 | |
|                                         $obj,
 | |
|                                         \%defhash);
 | |
|                                     push(@{ $rsp_info->{data} }, "    $showattr=$memberlist");
 | |
|                                 }
 | |
|                                 else
 | |
|                                 {
 | |
|                                     # nics attributes, like nicips, nichostnamesuffix.
 | |
|                                     if ($showattr =~ /^nic/)
 | |
|                                     {
 | |
|                                         my $nicval = "$showattr=$attrval";
 | |
|                                         my $nicnames;
 | |
|                                         if (defined($::NicsAttrHash{$showattr}))
 | |
|                                         {
 | |
|                                             $nicnames = join(',', @{ $::NicsAttrHash{$showattr} });
 | |
|                                         }
 | |
|                                         my $nicsstr;
 | |
|                                         my $is_group = $defhash{$obj}{'objtype'} eq 'group';
 | |
|                                         if ($nicnames)
 | |
|                                         {
 | |
|                                             $nicsstr = xCAT::DBobjUtils->expandnicsattr($nicval, $obj, $nicnames, $is_group);
 | |
|                                         }
 | |
|                                         else
 | |
|                                         {
 | |
|                                             $nicsstr = xCAT::DBobjUtils->expandnicsattr($nicval, $obj, undef, $is_group);
 | |
|                                         }
 | |
| 
 | |
|                                         # Compress mode, format the output
 | |
|                                         if ($::opt_c)
 | |
|                                         {
 | |
|                                             $nicsstr =~ s/^\s+/$obj: /;
 | |
|                                             $nicsstr =~ s/\n\s+/\n$obj: /g;
 | |
|                                         }
 | |
|                                         if ($nicsstr)
 | |
|                                         {
 | |
|                                             push(@{ $rsp_info->{data} }, "$nicsstr");
 | |
|                                         }
 | |
|                                     }
 | |
|                                     else
 | |
|                                     {
 | |
|                                         # since they asked for this attr
 | |
|                                         #   show it even if not set
 | |
|                                         if (!$::opt_c)
 | |
|                                         {
 | |
|                                             push(@{ $rsp_info->{data} }, "    $showattr=$attrval");
 | |
|                                         }
 | |
|                                         else
 | |
|                                         {
 | |
|                                             push(@{ $rsp_info->{data} }, "$obj: $showattr=$attrval");
 | |
| 
 | |
|                                         }
 | |
|                                     }
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
| 
 | |
|                             if (($defhash{$obj}{'objtype'} eq 'group')
 | |
|                                 && ($showattr eq 'members'))
 | |
| 
 | |
|                             {
 | |
|                                 #$defhash{$obj}{'grouptype'} = "static";
 | |
|                                 my $memberlist =
 | |
|                                   xCAT::DBobjUtils->getGroupMembers($obj, \%defhash);
 | |
|                                 push(@{ $rsp_info->{data} }, "    $showattr=$memberlist");
 | |
|                             }
 | |
|                             else
 | |
|                             {
 | |
| 
 | |
|                                 # don't print unless set
 | |
|                                 if ((defined($attrval)) && ($attrval ne ''))
 | |
|                                 {
 | |
|                                     # nics attributes, like nicips, nichostnamesuffix.
 | |
|                                     if ($showattr =~ /^nic/)
 | |
|                                     {
 | |
|                                         my $nicval = "$showattr=$attrval";
 | |
|                                         my $is_group = $defhash{$obj}{'objtype'} eq 'group';
 | |
|                                         my $nicsstr = xCAT::DBobjUtils->expandnicsattr($nicval, $obj, undef, $is_group);
 | |
|                                         if ($nicsstr)
 | |
|                                         {
 | |
|                                             push(@{ $rsp_info->{data} }, "$nicsstr");
 | |
|                                         }
 | |
|                                     }
 | |
|                                     else
 | |
|                                     {
 | |
|                                         push(@{ $rsp_info->{data} }, "    $showattr=$attrval");
 | |
|                                     }
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     # Additional osimage attributes
 | |
|                     if (($type eq "node") && $::opt_osimg)
 | |
|                     {
 | |
|                         if (defined($nodeosimagehash{$obj}))
 | |
|                         {
 | |
|                             foreach my $attr (keys %{ $nodeosimagehash{$obj} })
 | |
|                             {
 | |
|                                 if ($nodeosimagehash{$obj}{$attr})
 | |
|                                 {
 | |
|                                     push(@{ $rsp_info->{data} }, "    $attr=$nodeosimagehash{$obj}{$attr}");
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
| 
 | |
|                     if ($::opt_a)
 | |
|                     {
 | |
|                         if ($::opt_z)
 | |
|                         {
 | |
|                             push(@{ $rsp_info->{data} }, "\n$obj:");
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             # give the type also
 | |
|                             push(@{ $rsp_info->{data} }, "$obj ($::AllObjTypeHash{$obj})");
 | |
|                         }
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
| 
 | |
|                         # just give the name
 | |
|                         if ($::opt_z)
 | |
|                         {
 | |
|                             push(@{ $rsp_info->{data} }, "\n$obj:");
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             if (scalar(@::clobjtypes) > 0)
 | |
|                             {
 | |
|                                 push(@{ $rsp_info->{data} }, "$obj  ($defhash{$obj}{'objtype'})");
 | |
|                             }
 | |
|                             else
 | |
|                             {
 | |
|                                 push(@{ $rsp_info->{data} }, "$obj");
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }    # end - for each object
 | |
|     }    # end - for each type
 | |
| 
 | |
| 
 | |
|     # Display the definition of objects
 | |
|     if (defined($rsp_info->{data}) && scalar(@{ $rsp_info->{data} }) > 0) {
 | |
|         xCAT::MsgUtils->message("I", $rsp_info, $::callback);
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  defrm
 | |
| 
 | |
|         Support for the xCAT defrm command.
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|                 0 - OK
 | |
|                 1 - error
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
|             Object names to remove are derived from -o, -t, w, -a, -f,
 | |
|                  or noderange!
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defrm
 | |
| {
 | |
| 
 | |
|     my %objhash;
 | |
|     my $error = 0;
 | |
|     my %rmhash;
 | |
|     my %myhash;
 | |
|     my %childrenhash;
 | |
|     my %typehash;
 | |
| 
 | |
|     # process the command line
 | |
|     my $rc = &processArgs;
 | |
| 
 | |
|     # Issue info message if more than cleanup_msg_trigger nodes are being removed with --cleanup option
 | |
|     my $cleanup_msg_trigger = 100;
 | |
| 
 | |
|     if ($rc != 0)
 | |
|     {
 | |
| 
 | |
|         # rc: 0 - ok, 1 - return, 2 - help, 3 - error
 | |
|         # 0 - continue
 | |
|         # 1 - return  (like for version option)
 | |
|         # 2 - return with usage
 | |
|         # 3 - return error
 | |
|         if ($rc == 1) {
 | |
|             return 0;
 | |
|         } elsif ($rc == 2) {
 | |
|             &defrm_usage;
 | |
|             return 0;
 | |
|         } elsif ($rc == 3) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if ($::opt_a && !$::opt_f)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "You must use the \'-f\' option when using the \'-a\' option.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         &defrm_usage;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     #
 | |
|     #  build a hash of object names and their types
 | |
|     #
 | |
| 
 | |
|     # the list of objects to remove could have come from: the arg list,
 | |
|     #    opt_o, a noderange, opt_t, or opt_a. (rmdef doesn't take file
 | |
|     #    input)
 | |
| 
 | |
|     # if a set of objects was specifically provided on the cmd line then
 | |
|     #    there can only be one type value
 | |
|     if ($::objectsfrom_opto || $::objectsfrom_nr || $::objectsfrom_args)
 | |
|     {
 | |
|         my $type = $::clobjtypes[0];
 | |
| 
 | |
|         foreach my $obj (sort @::clobjnames)
 | |
|         {
 | |
|             $objhash{$obj} = $type;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # if we derived a list of objects from a list of types
 | |
|     if ($::objectsfrom_optt)
 | |
|     {
 | |
|         %objhash = %::ObjTypeHash;
 | |
|     }
 | |
| 
 | |
|     # if we derived the list of objects from the "all" option
 | |
|     if ($::objectsfrom_opta)
 | |
|     {
 | |
|         %objhash = %::AllObjTypeHash;
 | |
|     }
 | |
| 
 | |
|     # handle the "-w" value - if provided
 | |
|     # the list of objects may be limited by the "-w" option
 | |
|     # see which objects have attr/val that match the where values
 | |
|     #       - if provided
 | |
|     #  !!!!! don't support -w for now - gets way too complicated with groups!!!!
 | |
|     if ($::opt_w)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "The \'-w\' option is not supported for the rmdef command.";
 | |
|         xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         $error = 1;
 | |
|         return 1;
 | |
|     }
 | |
|     if (0)
 | |
|     {
 | |
| 
 | |
|         # need to get object defs from DB
 | |
|         %myhash = xCAT::DBobjUtils->getobjdefs(\%objhash);
 | |
|         if (!(%myhash))
 | |
|         {
 | |
|             $error = 1;
 | |
|         }
 | |
| 
 | |
|         foreach my $obj (sort (keys %objhash))
 | |
|         {
 | |
|             foreach my $testattr (keys %::WhereHash)
 | |
|             {
 | |
|                 if ($myhash{$obj}{$testattr} eq $::WhereHash{$testattr})
 | |
|                 {
 | |
| 
 | |
|                     # add this object to the remove hash
 | |
|                     $rmhash{$obj} = $objhash{$obj};
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
|         %objhash = %rmhash;
 | |
|     }
 | |
| 
 | |
|     # if the object to remove is a group then the "groups" attr of
 | |
|     #    the memberlist nodes must be updated.
 | |
| 
 | |
|     my $numobjects = 0;
 | |
|     my %objTypeLists;
 | |
|     foreach my $obj (keys %objhash)
 | |
|     {
 | |
|         my $objtype = $objhash{$obj};
 | |
|         if (!defined($objTypeLists{$objtype})) # Do no call getObjectsOfType for the same objtype more than once.
 | |
|         {
 | |
|             @{ $objTypeLists{$objtype} } = xCAT::DBobjUtils->getObjectsOfType($objtype);
 | |
|         }
 | |
|         if (!grep(/^$obj$/, @{ $objTypeLists{$objtype} })) #Object is not in the db, do not need to delete
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "Could not find an object named \'$obj\' of type \'$objtype\'.";
 | |
|             xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
| 
 | |
|             # Remove the object we could not find from the hash, this way the count of the objects
 | |
|             # and the content of the hash (for the verbose option), can be used for printing results at the end
 | |
|             delete($objhash{$obj});
 | |
|             next;
 | |
|         }
 | |
|         $numobjects++;
 | |
| 
 | |
|         if ($objhash{$obj} eq 'group')
 | |
|         {
 | |
| 
 | |
|             # get the group object definition
 | |
|             my %ghash;
 | |
|             $ghash{$obj} = 'group';
 | |
|             my @attrs = ('grouptype', 'wherevals');
 | |
|             my %grphash = xCAT::DBobjUtils->getobjdefs(\%ghash, 0, \@attrs);
 | |
|             if (!(%grphash))
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Could not get xCAT object definition for \'$obj\'.";
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             # Dynamic node group stores in nodegroup table
 | |
|             # do not need to update the nodelist table
 | |
|             if ($grphash{$obj}{'grouptype'} eq 'dynamic')
 | |
|             {
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             # get the members list
 | |
|             #  all groups are "static" for now
 | |
|             $grphash{$obj}{'grouptype'} = "static";
 | |
|             my $memberlist = xCAT::DBobjUtils->getGroupMembers($obj, \%grphash);
 | |
|             my @members = split(',', $memberlist);
 | |
| 
 | |
|             # No node in the group
 | |
|             if (scalar(@members) == 0)
 | |
|             {
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             # foreach member node of the group
 | |
|             my %nodehash;
 | |
|             my %nhash;
 | |
|             my @gprslist;
 | |
|             foreach my $m (@members)
 | |
|             {
 | |
|                 # get the def of this node
 | |
|                 $nhash{$m} = 'node';
 | |
|             }
 | |
| 
 | |
|             # Performance: Only call getobjdefs once
 | |
|             @attrs = ('groups');
 | |
|             %nodehash = xCAT::DBobjUtils->getobjdefs(\%nhash, 0, \@attrs);
 | |
|             if (!(%nodehash))
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 my @nodes = keys %nhash;
 | |
|                 my $m = join ',', @nodes;
 | |
|                 $rsp->{data}->[0] = "Could not get xCAT object definition for \'$m\'.";
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             foreach my $m (keys %nodehash)
 | |
|             {
 | |
|                 # need to update the "groups" attr of the node def
 | |
|                 # split the "groups" to get a list
 | |
|                 @gprslist = split(',', $nodehash{$m}{groups});
 | |
| 
 | |
|                 # make a new "groups" list for the node without the
 | |
|                 #      group that is being removed
 | |
|                 my $first   = 1;
 | |
|                 my $newgrps = "";
 | |
|                 foreach my $grp (@gprslist)
 | |
|                 {
 | |
|                     chomp($grp);
 | |
|                     if ($grp eq $obj)
 | |
|                     {
 | |
|                         next;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
| 
 | |
|                         # set new groups list for node
 | |
|                         if (!$first)
 | |
|                         {
 | |
|                             $newgrps .= ",";
 | |
|                         }
 | |
|                         $newgrps .= "$grp";
 | |
|                         $first = 0;
 | |
| 
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 # make the change to %nodehash
 | |
|                 $nodehash{$m}{groups} = $newgrps;
 | |
|             }
 | |
| 
 | |
|             # set the new node attr values
 | |
|             if (xCAT::DBobjUtils->setobjdefs(\%nodehash) != 0)
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "Could not write data to xCAT database.";
 | |
|                 xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|                 $error = 1;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # find the children of the node.
 | |
|     for my $tob (keys %objhash) {
 | |
|         if ($objhash{$tob} eq 'node') {
 | |
|             my $ntype = xCAT::DBobjUtils->getnodetype($tob);
 | |
|             if ($ntype =~ /^(cec|frame)$/) {
 | |
|                 my $cnodep = xCAT::DBobjUtils->getchildren($tob);
 | |
|                 if ($cnodep) {
 | |
|                     my $cnode = join ',', @$cnodep;
 | |
|                     $childrenhash{$tob} = $cnode;
 | |
|                     $typehash{$tob}     = $ntype;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($::opt_cleanup) {
 | |
|         # Call nodeset offline on each node to cleanup its boot configuration files from /tftpboot directory
 | |
|         if ($doreq) {
 | |
|             # Go through each object and make sure it is a node type
 | |
|             my @allnodes;
 | |
|             foreach my $single_object (keys %objhash) {
 | |
|                 if ($objhash{$single_object} eq "node") {
 | |
|                     # build a list of nodes to offline
 | |
|                     push @allnodes, $single_object;
 | |
|                 }
 | |
|             }
 | |
|             # If cleaning up (issuing nodeset offline) for more than cleanup_msg_trigger node, 
 | |
|             # issue info message
 | |
|             if (@allnodes > $cleanup_msg_trigger) {
 | |
|                my $rsp;
 | |
|                $rsp->{data}->[0] = "Performing configuration cleanup. This might take a some time.";
 | |
|                xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             }
 | |
|             # Run nodeset offline and capture output.
 | |
|             # But the output can be ignored since we do not want to prevent user from doing rmdef if
 | |
|             # nodeset returns some error.
 | |
|             my @output = xCAT::Utils->runxcmd({
 | |
|                 command => ['nodeset'],
 | |
|                 node => [@allnodes],
 | |
|                 arg  => ['offline'],
 | |
|             }, $doreq, 0 ,1);
 | |
| 
 | |
|             # Run makeconservercf -d <node>
 | |
|             @output = xCAT::Utils->runxcmd({
 | |
|                 command => ['makeconservercf'],
 | |
|                 node => [@allnodes],
 | |
|                 arg => ['-d'],}, $doreq, 0, 1);
 | |
|             if (-x "/usr/bin/goconserver") {
 | |
|                 require xCAT::Goconserver;
 | |
|                 if (xCAT::Goconserver::is_goconserver_running()) {
 | |
|                     xCAT::Goconserver::cleanup_nodes(undef);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # remove the objects
 | |
|     if (xCAT::DBobjUtils->rmobjdefs(\%objhash) != 0)
 | |
|     {
 | |
|         $error = 1;
 | |
|     }
 | |
| 
 | |
|     if ($error)
 | |
|     {
 | |
|         my $rsp;
 | |
|         $rsp->{data}->[0] = "One or more errors occured when attempting to remove xCAT object definitions.";
 | |
|         xCAT::MsgUtils->message("E", $rsp, $::callback);
 | |
|         return 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if ($numobjects > 0)
 | |
|         {
 | |
|             if ($::verbose)
 | |
|             {
 | |
| 
 | |
|                 #  give results
 | |
|                 my $rsp;
 | |
|                 $rsp->{data}->[0] = "The following objects were removed:";
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
| 
 | |
|                 my $n = 1;
 | |
|                 foreach my $o (sort(keys %objhash))
 | |
|                 {
 | |
|                     $rsp->{data}->[$n] = "$o";
 | |
|                     $n++;
 | |
|                 }
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 my $rsp;
 | |
|                 my $nodenum = scalar(keys %objhash);
 | |
|                 $rsp->{data}->[0] = "$nodenum object definitions have been removed.";
 | |
|                 xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|             }
 | |
| 
 | |
|             # Give a warning message to the user to remove the children of the node.
 | |
|             for my $tn (keys %objhash) {
 | |
|                 if ($childrenhash{$tn}) {
 | |
|                     my $rsp;
 | |
|                     $rsp->{data}->[0] = "You have removed a $typehash{$tn} node, please remove these nodes belongs to it manually: $childrenhash{$tn} .";
 | |
|                     xCAT::MsgUtils->message("W", $rsp, $::callback);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             my $rsp;
 | |
|             $rsp->{data}->[0] = "No objects have been removed from the xCAT database.";
 | |
|             xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|         }
 | |
|         return 0;
 | |
| 
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  defmk_usage
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| # subroutines to display the usage
 | |
| sub defmk_usage
 | |
| {
 | |
|     my $rsp;
 | |
|     $rsp->{data}->[0] = "\nUsage: mkdef - Create xCAT data object definitions.\n";
 | |
|     $rsp->{data}->[1] = "  mkdef [-h | --help ] [-t object-types]\n";
 | |
|     $rsp->{data}->[2] = "  mkdef [-V | --verbose] [-t object-types] [--template template-object-name]";
 | |
|     $rsp->{data}->[3] = "      [-o object-names] [-z|--stanza ]";
 | |
|     $rsp->{data}->[4] = "      [-d | --dynamic] [-w attr==val [-w attr=~val] ...]";
 | |
|     $rsp->{data}->[5] = "      [-f | --force] [noderange] [attr=val [attr=val...]]";
 | |
|     $rsp->{data}->[6] = "\nThe following data object types are supported by xCAT.\n";
 | |
|     my $n = 6;
 | |
| 
 | |
|     foreach my $t (sort(keys %{xCAT::Schema::defspec}))
 | |
|     {
 | |
|         $rsp->{data}->[$n] = "$t";
 | |
|         $n++;
 | |
|     }
 | |
|     $rsp->{data}->[$n] = "\nUse the \'-h\' option together with the \'-t\' option to";
 | |
|     $n++;
 | |
|     $rsp->{data}->[$n] = "get a list of valid attribute names for each object type.\n";
 | |
|     xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  defch_usage
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defch_usage
 | |
| {
 | |
|     my $rsp;
 | |
|     $rsp->{data}->[0] = "\nUsage: chdef - Change xCAT data object definitions.\n";
 | |
|     $rsp->{data}->[1] = "  chdef [-h | --help ] [-t object-types]\n";
 | |
|     $rsp->{data}->[2] = "  chdef [-t object-types] [-o object-names] [-n new-name] [node]\n";
 | |
|     $rsp->{data}->[3] = "  chdef [-V | --verbose] [-t object-types] [-o object-names] [-d | --dynamic]";
 | |
|     $rsp->{data}->[4] = "    [-z | --stanza] [-m | --minus] [-p | --plus]";
 | |
|     $rsp->{data}->[5] = "    [-w attr==val [-w attr=~val] ... ] [noderange] [attr=val [attr=val...]]\n";
 | |
|     $rsp->{data}->[6] = "\nThe following data object types are supported by xCAT.\n";
 | |
|     my $n = 7;
 | |
| 
 | |
|     foreach my $t (sort(keys %{xCAT::Schema::defspec}))
 | |
|     {
 | |
|         $rsp->{data}->[$n] = "$t";
 | |
|         $n++;
 | |
|     }
 | |
|     $rsp->{data}->[$n] = "\nUse the \'-h\' option together with the \'-t\' option to";
 | |
|     $n++;
 | |
|     $rsp->{data}->[$n] = "get a list of valid attribute names for each object type.\n";
 | |
|     xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  defls_usage
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defls_usage
 | |
| {
 | |
|     my $rsp;
 | |
|     $rsp->{data}->[0] = "\nUsage: lsdef - List xCAT data object definitions.\n";
 | |
|     $rsp->{data}->[1] = "  lsdef [-h | --help ] [-t object-types]\n";
 | |
|     $rsp->{data}->[2] = "  lsdef [-l|--long] [-a|--all] [-t *object-types*] [-z|--stanza]";
 | |
|     $rsp->{data}->[3] = "        [-i attr-list] [--template [template-object-name]] \n";
 | |
|     $rsp->{data}->[4] = "  lsdef [-V | --verbose] [-t object-types] [-o object-names]";
 | |
|     $rsp->{data}->[5] = "        [ -l | --long] [-s | --short] [-a | --all] [-z | --stanza ] [-S]";
 | |
|     $rsp->{data}->[6] = "        [-i attr-list] [-w attr==val [-w attr=~val] ...] [noderange]\n";
 | |
|     $rsp->{data}->[7] = "\nThe following data object types are supported by xCAT.\n";
 | |
|     my $n = 6;
 | |
| 
 | |
|     foreach my $t (sort(keys %{xCAT::Schema::defspec}))
 | |
|     {
 | |
|         $rsp->{data}->[$n] = "$t";
 | |
|         $n++;
 | |
|     }
 | |
|     $rsp->{data}->[$n] = "\nUse the \'-h\' option together with the \'-t\' option to";
 | |
|     $n++;
 | |
|     $rsp->{data}->[$n] = "get a list of valid attribute names for each object type.\n";
 | |
|     xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  defrm_usage
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| 
 | |
| sub defrm_usage
 | |
| {
 | |
|     my $rsp;
 | |
|     $rsp->{data}->[0] = "\nUsage: rmdef - Remove xCAT data object definitions.\n";
 | |
|     $rsp->{data}->[1] = "  rmdef [-h | --help ] [-t object-types]\n";
 | |
|     $rsp->{data}->[2] = "  rmdef [-V | --verbose] [-t object-types] [-a | --all] [-f | --force]";
 | |
|     $rsp->{data}->[3] = "    [-o object-names] [-C | --cleanup] [noderange]\n";
 | |
|     $rsp->{data}->[4] = "\nThe following data object types are supported by xCAT.\n";
 | |
|     my $n = 5;
 | |
| 
 | |
|     foreach my $t (sort(keys %{xCAT::Schema::defspec}))
 | |
|     {
 | |
|         $rsp->{data}->[$n] = "$t";
 | |
|         $n++;
 | |
|     }
 | |
|     $rsp->{data}->[$n] = "\nUse the \'-h\' option together with the \'-t\' option to";
 | |
|     $n++;
 | |
|     $rsp->{data}->[$n] = "get a list of valid attribute names for each object type.\n";
 | |
|     xCAT::MsgUtils->message("I", $rsp, $::callback);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| =head3  initialize_variables
 | |
|             Initialize the global variables
 | |
| 
 | |
|         Arguments:
 | |
|         Returns:
 | |
|         Globals:
 | |
| 
 | |
|         Error:
 | |
| 
 | |
|         Example:
 | |
| 
 | |
|         Comments:
 | |
| =cut
 | |
| 
 | |
| #-----------------------------------------------------------------------------
 | |
| sub initialize_variables
 | |
| {
 | |
|     %::CLIATTRS   = ();
 | |
|     %::FILEATTRS  = ();
 | |
|     %::FINALATTRS = ();
 | |
| 
 | |
|     #    %::objfilehash = ();
 | |
|     %::WhereHash    = ();
 | |
|     @::AttrList     = ();
 | |
|     %::NicsAttrHash = ();
 | |
|     @::clobjtypes   = ();
 | |
|     @::fileobjtypes = ();
 | |
|     @::clobjnames   = ();
 | |
|     @::fileobjnames = ();
 | |
|     @::objfilelist  = ();
 | |
|     @::allobjnames  = ();
 | |
|     @::noderange    = ();
 | |
| }
 | |
| 
 | |
| 
 | |
| #-----------------------
 | |
| #isobjnamevalid:
 | |
| #description: check whether the object name is valid
 | |
| #argument:
 | |
| #          $objname: the object name string 
 | |
| #          $objtype: the object type string
 | |
| #return:
 | |
| #          1: valid
 | |
| #          0: invalid
 | |
| #-----------------------
 | |
| sub isobjnamevalid{
 | |
|     my $objname=shift;
 | |
|     my $objtype=shift;
 | |
|     $objtype="node" unless(defined $objtype and ($objtype ne ""));
 | |
|     if($objtype eq "node"){
 | |
|         #the ip address as a valid node object name is a hack for p7IH support   
 | |
|         if(($objname !~ /^[a-zA-Z0-9-_]+$/) and !xCAT::NetworkUtils->isIpaddr($objname)){
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| 1;
 | |
| 
 |