Commit new kit plugin samples
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@15168 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
a60ce4d483
commit
1f69def767
@ -1,3 +1,8 @@
|
||||
# IBM(c) 2012 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
#TEST: UNCOMMENT the first line, and COMMENT OUT the second line.
|
||||
#BUILD: COMMENT OUT the first line, and UNCOMMENT the second line.
|
||||
#package xCAT_plugin::imageprofile;
|
||||
package xCAT_plugin::<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile;
|
||||
|
||||
use strict;
|
||||
@ -7,27 +12,81 @@ require xCAT::Utils;
|
||||
require xCAT::Table;
|
||||
require xCAT::KitPluginUtils;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
# buildkit Processing
|
||||
# In order to avoid collisions with other plugins, the package
|
||||
# name for this plugin must contain the full kit name.
|
||||
# The buildkit buildtar command will copy this file from your plugins
|
||||
# directory to the the kit build directory, renaming the file with the
|
||||
# correct kit name. All strings in this file of the form
|
||||
# <<<buildkit_WILL_INSERT_kitname_HERE>>>
|
||||
# will be replaced with the full kit name. In order for buildkit to
|
||||
# correctly edit this file, do not remove these strings.
|
||||
#
|
||||
# KIT PLUGIN FOR IMAGE PROFILE MANAGEMENT
|
||||
# =======================================
|
||||
# What is this plugin used for?
|
||||
# This is an xCAT Perl plugin that lets you add custom code
|
||||
# which gets called during certain image profile management
|
||||
# operations.
|
||||
#
|
||||
#
|
||||
# What image profile management operations automatically call this plugin?
|
||||
#
|
||||
# - Generate image profile (pcmgenerateimageprofile / pcmmgtnodeimageprofile)
|
||||
# operation calls:
|
||||
# - kitimagepregenerate(): Any code added here gets called
|
||||
# before an image profile is created.
|
||||
#
|
||||
# - kitimagepostgenerate(): Any code added here gets called
|
||||
# after an image profile is created.
|
||||
#
|
||||
# - Copy image profile (pcmcopyimageprofile) operation calls:
|
||||
# - kitimageprecopy(): Any code added here gets called
|
||||
# before an image profile is copied.
|
||||
#
|
||||
# - kitimagepostcopy(): Any code added here gets called
|
||||
# after an image profile is copied.
|
||||
#
|
||||
# - Update image profile (pcmupdateimageprofile) operation calls:
|
||||
# - kitimagepreupdate(): Any code added here gets called
|
||||
# before an image profile is updated.
|
||||
#
|
||||
# - kitimagepostupdate(): Any code added here gets called
|
||||
# after an image profile is updated.
|
||||
#
|
||||
# - Delete image profile (pcmdeleteimageprofile) operation calls:
|
||||
# - kitimagepredelete(): Any code added here gets called
|
||||
# before an image profile is deleted.
|
||||
#
|
||||
# - kitimagepostdelete(): Any code added here gets called
|
||||
# after an image profile is deleted.
|
||||
#
|
||||
#
|
||||
# How to create a new plugin for your kit?
|
||||
#
|
||||
# 1) Copy the sample plugin
|
||||
# % cp plugins/sample/imageprofile.pm plugins
|
||||
#
|
||||
# 2) Modify the sample plugin by implementing one or more of
|
||||
# the plugin commands above.
|
||||
#
|
||||
# Refer to each command's comments for command parameters
|
||||
# and return values.
|
||||
#
|
||||
# For details on how to write plugin code, refer to:
|
||||
# http://sourceforge.net/apps/mediawiki/xcat/index.php?title=XCAT_Developer_Guide
|
||||
#
|
||||
# 3) To test the plugin commands:
|
||||
# a) Search this file for lines that start with "TEST:" and follow the
|
||||
# instructions
|
||||
#
|
||||
# b) Refer to each command's comments for test steps.
|
||||
#
|
||||
# 4) After you finish the test, you can build the the kit.
|
||||
# Before building, search this file for lines that start with "BUILD:" and
|
||||
# follow the instructions.
|
||||
#
|
||||
# 5) Run buildkit as normal to build the kit.
|
||||
#
|
||||
|
||||
|
||||
# Global Variables
|
||||
|
||||
# This is the full name of the kit which this plugin belongs
|
||||
# to. The kit name is used by some code in process_request()
|
||||
# to determine if the plugin should run. When you are testing
|
||||
# your plugin the kit name should be set to "TESTMODE" to
|
||||
# bypass the plugin check in process_request().
|
||||
|
||||
our ($PLUGIN_KITNAME);
|
||||
|
||||
#TEST: UNCOMMENT the first line, and COMMENT OUT the second line.
|
||||
#BUILD: COMMENT OUT the first line, and UNCOMMENT the second line.
|
||||
#$PLUGIN_KITNAME = "TESTMODE";
|
||||
$PLUGIN_KITNAME = "<<<buildkit_WILL_INSERT_kitname_HERE>>>";
|
||||
|
||||
@ -56,9 +115,27 @@ $PLUGIN_KITNAME = "<<<buildkit_WILL_INSERT_kitname_HERE>>>";
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub handled_commands {
|
||||
#TEST: UNCOMMENT the first return, and COMMENT OUT the second return.
|
||||
#BUILD: COMMENT OUT the first return, and UNCOMMENT the second return.
|
||||
#return {
|
||||
# kitimagepregenerate => 'imageprofile',
|
||||
# kitimagepostgenerate => 'imageprofile',
|
||||
# kitimageprecopy => 'imageprofile',
|
||||
# kitimagepostcopy => 'imageprofile',
|
||||
# kitimagepreupdate => 'imageprofile',
|
||||
# kitimagepostupdate => 'imageprofile',
|
||||
# kitimagepredelete => 'imageprofile',
|
||||
# kitimagepostdelete => 'imageprofile',
|
||||
#};
|
||||
return {
|
||||
kitimagevalidatecomps => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimageimport => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepregenerate => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepostgenerate => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimageprecopy => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepostcopy => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepreupdate => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepostupdate => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepredelete => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
kitimagepostdelete => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_imageprofile',
|
||||
};
|
||||
}
|
||||
|
||||
@ -76,33 +153,64 @@ sub handled_commands {
|
||||
sub process_request {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
|
||||
# This kit plugin is passed the name of an image profile.
|
||||
# We need to determine which kits is used by this
|
||||
# image profile to decide if this plugin should run or not.
|
||||
|
||||
my $imgprofilename = $request->{arg}->[0];
|
||||
|
||||
my $kitdata = $request->{kitdata};
|
||||
if (! defined($kitdata)) {
|
||||
$kitdata = xCAT::KitPluginUtils->get_kits_used_by_image_profiles([$imgprofilename]);
|
||||
$request->{kitdata} = $kitdata;
|
||||
}
|
||||
|
||||
if ($PLUGIN_KITNAME ne "TESTMODE" && ! exists($kitdata->{$PLUGIN_KITNAME})) {
|
||||
return;
|
||||
}
|
||||
my $rsp;
|
||||
|
||||
# Name of command and node list
|
||||
my $command = $request->{command}->[0];
|
||||
my $args = $request->{arg};
|
||||
|
||||
if($command eq 'kitimagevalidatecomps') {
|
||||
kitimagevalidatecomps($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimageimport') {
|
||||
kitimageimport($callback, $args);
|
||||
# This kit plugin is passed the name of an image profile.
|
||||
# Before running this plugin, we should check if the
|
||||
# image profile is using the kit which this plugin belongs to.
|
||||
|
||||
if ($PLUGIN_KITNAME eq "TESTMODE") {
|
||||
# Don't do the check in test mode
|
||||
} elsif ($command eq 'kitimagepregenerate' || $command eq 'kitimageprecopy') {
|
||||
# Also, don't do the check if the image profile doesn't yet exist
|
||||
} else {
|
||||
# Do the check
|
||||
my $imageprofile = parse_str_arg($request->{arg}->[0]);
|
||||
|
||||
my $kitdata = $request->{kitdata};
|
||||
if (! defined($kitdata)) {
|
||||
$kitdata = xCAT::KitPluginUtils->get_kits_used_by_image_profiles([$imageprofile]);
|
||||
$request->{kitdata} = $kitdata;
|
||||
}
|
||||
|
||||
if (! exists($kitdata->{$PLUGIN_KITNAME})) {
|
||||
# This image profile is not using this plugin's kit, so don't run the plugin.
|
||||
$rsp->{data}->[0] = "Skipped running \"$command\" plugin command for \"$PLUGIN_KITNAME\" kit.";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Run the command
|
||||
|
||||
if($command eq 'kitimagepregenerate') {
|
||||
kitimagepregenerate($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimagepostgenerate') {
|
||||
kitimagepostgenerate($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimageprecopy') {
|
||||
kitimageprecopy($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimagepostcopy') {
|
||||
kitimagepostcopy($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimagepreupdate') {
|
||||
kitimagepreupdate($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimagepostupdate') {
|
||||
kitimagepostupdate($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimagepredelete') {
|
||||
kitimagepredelete($callback, $args);
|
||||
}
|
||||
elsif ($command eq 'kitimagepostdelete') {
|
||||
kitimagepostdelete($callback, $args);
|
||||
} else {
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "Command is not supported";
|
||||
@ -113,63 +221,524 @@ sub process_request {
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimagevalidatecomps
|
||||
=head3 kitimagepregenerate
|
||||
|
||||
This command is called to validate new changes to an
|
||||
image profile's kit component list before the changes
|
||||
are committed.
|
||||
This command is called before an image profile
|
||||
is created with a specified set of parameters.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepregenerate imageprofile="<image profile name>"
|
||||
osdistro="<os distro name>"
|
||||
osdistroupdate="<os distro update name>"
|
||||
bootparams="<boot params string>"
|
||||
ospkgs="<comma-separated list of ospkgs>"
|
||||
custompkgs="<comma-separated list of custompkgs>"
|
||||
kitcomponents="<comma-separated list of kitcomponents>"
|
||||
modules="<comma-separated list of modules>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
$osdistro : os distro name
|
||||
$osdistroupdate : os distro update name
|
||||
$bootparams : boot params string
|
||||
@ospkgs : list of ospkg names
|
||||
@custompkgs : list of custompkg names
|
||||
@kitcomponents : list of kit component names
|
||||
@modules : list of module names
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepregenerate
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepregenerate <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimagevalidatecomps {
|
||||
sub kitimagepregenerate {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imgprofilename = $args->[0];
|
||||
my $newcomplist = $args->[1];
|
||||
my @newcomplist = ();
|
||||
if (defined($newcomplist)) {
|
||||
@newcomplist = split(/,/, $newcomplist);
|
||||
}
|
||||
my $newosdistro = $args->[2];
|
||||
my $newosdistroupdate = $args->[3];
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
my $osdistro = parse_str_arg(shift(@$args));
|
||||
my $osdistroupdate = parse_str_arg(shift(@$args));
|
||||
my $bootparams = parse_str_arg(shift(@$args));
|
||||
my @ospkgs = parse_list_arg(shift(@$args));
|
||||
my @custompkgs = parse_list_arg(shift(@$args));
|
||||
my @kitcomponents = parse_list_arg(shift(@$args));
|
||||
my @modules = parse_list_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimagevalidatecomps";
|
||||
$rsp->{data}->[0] = "Running kitimagepregenerate ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimageimport
|
||||
=head3 kitimagepostgenerate
|
||||
|
||||
This command is called after changes to an image profile
|
||||
have been committed.
|
||||
This command is called after an image profile
|
||||
is created.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepostgenerate imageprofile="<image profile name>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepostgenerate
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepostgenerate <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimageimport {
|
||||
sub kitimagepostgenerate {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imgprofilename = $args->[0];
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimageimport";
|
||||
$rsp->{data}->[0] = "Running kitimagepostgenerate ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimageprecopy
|
||||
|
||||
This command is called before an image profile
|
||||
is copied with a specified set of parameters.
|
||||
|
||||
Command-line interface:
|
||||
kitimageprecopy imageprofile="<image profile name>"
|
||||
osdistro="<os distro name>"
|
||||
osdistroupdate="<os distro update name>"
|
||||
bootparams="<boot params string>"
|
||||
ospkgs="<comma-separated list of ospkgs>"
|
||||
custompkgs="<comma-separated list of custompkgs>"
|
||||
kitcomponents="<comma-separated list of kitcomponents>"
|
||||
modules="<comma-separated list of modules>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
$osdistro : os distro name
|
||||
$osdistroupdate : os distro update name
|
||||
$bootparams : boot params string
|
||||
@ospkgs : list of ospkg names
|
||||
@custompkgs : list of custompkg names
|
||||
@kitcomponents : list of kit component names
|
||||
@modules : list of module names
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimageprecopy
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimageprecopy <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimageprecopy {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
my $osdistro = parse_str_arg(shift(@$args));
|
||||
my $osdistroupdate = parse_str_arg(shift(@$args));
|
||||
my $bootparams = parse_str_arg(shift(@$args));
|
||||
my @ospkgs = parse_list_arg(shift(@$args));
|
||||
my @custompkgs = parse_list_arg(shift(@$args));
|
||||
my @kitcomponents = parse_list_arg(shift(@$args));
|
||||
my @modules = parse_list_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimageprecopy ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimagepostcopy
|
||||
|
||||
This command is called after an image profile
|
||||
is copied.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepostcopy imageprofile="<image profile name>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepostcopy
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepostcopy <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimagepostcopy {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimagepostcopy ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimagepreupdate
|
||||
|
||||
This command is called before an image profile
|
||||
is updated with a specified set of parameters.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepreupdate imageprofile="<image profile name>"
|
||||
osdistro="<os distro name>"
|
||||
osdistroupdate="<os distro update name>"
|
||||
bootparams="<boot params string>"
|
||||
ospkgs="<comma-separated list of ospkgs>"
|
||||
custompkgs="<comma-separated list of custompkgs>"
|
||||
kitcomponents="<comma-separated list of kitcomponents>"
|
||||
modules="<comma-separated list of modules>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
$osdistro : os distro name
|
||||
$osdistroupdate : os distro update name
|
||||
$bootparams : boot params string
|
||||
@ospkgs : list of ospkg names
|
||||
@custompkgs : list of custompkg names
|
||||
@kitcomponents : list of kit component names
|
||||
@modules : list of module names
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepreupdate
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepreupdate <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimagepreupdate {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
my $osdistro = parse_str_arg(shift(@$args));
|
||||
my $osdistroupdate = parse_str_arg(shift(@$args));
|
||||
my $bootparams = parse_str_arg(shift(@$args));
|
||||
my @ospkgs = parse_list_arg(shift(@$args));
|
||||
my @custompkgs = parse_list_arg(shift(@$args));
|
||||
my @kitcomponents = parse_list_arg(shift(@$args));
|
||||
my @modules = parse_list_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimagepreupdate ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimagepostupdate
|
||||
|
||||
This command is called after an image profile
|
||||
is updated.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepostupdate imageprofile="<image profile name>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepostupdate
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepostupdate <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimagepostupdate {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimagepostupdate ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimagepredelete
|
||||
|
||||
This command is called before an image profile
|
||||
is deleted.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepredelete imageprofile="<image profile name>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepredelete
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepredelete <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimagepredelete {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimagepredelete ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitimagepostdelete
|
||||
|
||||
This command is called after an image profile
|
||||
is deleted.
|
||||
|
||||
Command-line interface:
|
||||
kitimagepostdelete imageprofile="<image profile name>"
|
||||
|
||||
Parameters:
|
||||
$imageprofile : image profile name
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclientnnr kitimagepostdelete
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitimagepostdelete <params ...>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitimagepostdelete {
|
||||
my $callback = shift;
|
||||
my $args = shift;
|
||||
my $rsp;
|
||||
|
||||
# Parameters
|
||||
my $imageprofile = parse_str_arg(shift(@$args));
|
||||
|
||||
$rsp->{data}->[0] = "Running kitimagepostdelete ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Image Profile: $imageprofile";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO: ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 parse_str_arg
|
||||
|
||||
Utility function to extract the string value of an
|
||||
argument in this format:
|
||||
PARAM=string1
|
||||
|
||||
Returns a string:
|
||||
'string1'
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub parse_str_arg {
|
||||
|
||||
my $arg = shift;
|
||||
my $result;
|
||||
|
||||
if (!defined($arg)) {
|
||||
return $arg;
|
||||
}
|
||||
|
||||
$arg =~ s/.*?=//;
|
||||
$result = $arg;
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 parse_list_arg
|
||||
|
||||
Utility function to extract the list of values of
|
||||
an argument in this format:
|
||||
PARAM=value1,value2,value3
|
||||
|
||||
Returns a list of values:
|
||||
('value1', 'value2', 'value3')
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub parse_list_arg {
|
||||
|
||||
my $arg = shift;
|
||||
my @result;
|
||||
|
||||
if (!defined($arg)) {
|
||||
return $arg;
|
||||
}
|
||||
|
||||
$arg =~ s/.*?=//;
|
||||
@result = split(/,/, $arg);
|
||||
|
||||
return @result;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
# IBM(c) 2012 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
#TEST: UNCOMMENT the first line, and COMMENT OUT the second line.
|
||||
#BUILD: COMMENT OUT the first line, and UNCOMMENT the second line.
|
||||
#package xCAT_plugin::nodemgmt;
|
||||
package xCAT_plugin::<<<buildkit_WILL_INSERT_kitname_HERE>>>_nodemgmt;
|
||||
|
||||
use strict;
|
||||
@ -7,25 +12,70 @@ require xCAT::Utils;
|
||||
require xCAT::Table;
|
||||
require xCAT::KitPluginUtils;
|
||||
|
||||
# buildkit Processing
|
||||
# In order to avoid collisions with other plugins, the package
|
||||
# name for this plugin must contain the full kit name.
|
||||
# The buildkit buildtar command will copy this file from your plugins
|
||||
# directory to the the kit build directory, renaming the file with the
|
||||
# correct kit name. All strings in this file of the form
|
||||
# <<<buildkit_WILL_INSERT_kitname_HERE>>>
|
||||
# will be replaced with the full kit name. In order for buildkit to
|
||||
# correctly edit this file, do not remove these strings.
|
||||
use Data::Dumper;
|
||||
|
||||
# Global Variables
|
||||
|
||||
# This is the full name of the kit which this plugin belongs
|
||||
# to. The kit name is used by some code in process_request()
|
||||
# to determine if the plugin should run. When you are testing
|
||||
# your plugin the kit name should be set to "TESTMODE" to
|
||||
# bypass the plugin check in process_request().
|
||||
#
|
||||
# KIT PLUGIN FOR NODE MANAGEMENT
|
||||
# ==============================
|
||||
# What is this plugin used for?
|
||||
# This is an xCAT Perl plugin that lets you add custom code
|
||||
# which gets called during certain node management operations.
|
||||
#
|
||||
#
|
||||
# What node management operations automatically call this plugin?
|
||||
#
|
||||
# - Import node (nodeimport) / Discover node (findme) operations call:
|
||||
# - kitnodeadd(): Any code added here gets called after
|
||||
# one or more nodes are added to the cluster.
|
||||
#
|
||||
# - Remove node (nodepurge) operation calls:
|
||||
# - kitnoderemove(): Any code added here gets called after
|
||||
# one or more nodes are removed from the cluster.
|
||||
#
|
||||
# - Update node's profiles (kitnodeupdate) / Update node's MAC (nodechmac)
|
||||
# operations call:
|
||||
# - kitnodeupdate(): Any code added here gets called after
|
||||
# a node's profile(s) or MAC address changes
|
||||
#
|
||||
# - Refresh node's configuration files (noderefresh) / Re-generate IPs
|
||||
# for nodes (noderegenips) operations call:
|
||||
# - kitnoderefresh(): Any code added here gets called when
|
||||
# node config files need to be regenerated.
|
||||
#
|
||||
#
|
||||
# How to create a new plugin for your kit?
|
||||
#
|
||||
# 1) Copy the sample plugin
|
||||
# % cp plugins/sample/nodemgmt.pm plugins
|
||||
#
|
||||
# 2) Modify the sample plugin by implementing one or more of
|
||||
# the plugin commands above.
|
||||
#
|
||||
# Refer to each command's comments for command parameters
|
||||
# and return values.
|
||||
#
|
||||
# For details on how to write plugin code, refer to:
|
||||
# http://sourceforge.net/apps/mediawiki/xcat/index.php?title=XCAT_Developer_Guide
|
||||
#
|
||||
# 3) To test the plugin commands:
|
||||
# a) Search this file for lines that start with "TEST:" and follow the
|
||||
# instructions
|
||||
#
|
||||
# b) Refer to each command's comments for test steps.
|
||||
#
|
||||
# 4) After you finish the test, you can build the kit with your new plugin.
|
||||
# Before building, search this file for lines that start with "BUILD:" and
|
||||
# follow the instructions.
|
||||
#
|
||||
# 5) Run buildkit as normal to build the kit.
|
||||
#
|
||||
|
||||
|
||||
our ($PLUGIN_KITNAME);
|
||||
|
||||
#TEST: UNCOMMENT the first line, and COMMENT OUT the second line.
|
||||
#BUILD: COMMENT OUT the first line, and UNCOMMENT the second line.
|
||||
#$PLUGIN_KITNAME = "TESTMODE";
|
||||
$PLUGIN_KITNAME = "<<<buildkit_WILL_INSERT_kitname_HERE>>>";
|
||||
|
||||
@ -54,12 +104,19 @@ $PLUGIN_KITNAME = "<<<buildkit_WILL_INSERT_kitname_HERE>>>";
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub handled_commands {
|
||||
#TEST: UNCOMMENT the first return, and COMMENT OUT the second return.
|
||||
#BUILD: COMMENT OUT the first return, and UNCOMMENT the second return.
|
||||
#return {
|
||||
# kitnodeadd => 'nodemgmt',
|
||||
# kitnoderemove => 'nodemgmt',
|
||||
# kitnodeupdate => 'nodemgmt',
|
||||
# kitnoderefresh => 'nodemgmt',
|
||||
#};
|
||||
return {
|
||||
kitnodeadd => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_nodemgmt',
|
||||
kitnoderemove => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_nodemgmt',
|
||||
kitnodeupdate => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_nodemgmt',
|
||||
kitnoderefresh => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_nodemgmt',
|
||||
kitnodefinished => '<<<buildkit_WILL_INSERT_kitname_HERE>>>_nodemgmt',
|
||||
};
|
||||
}
|
||||
|
||||
@ -77,43 +134,52 @@ sub handled_commands {
|
||||
sub process_request {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $rsp;
|
||||
|
||||
# Name of command and node list
|
||||
my $command = $request->{command}->[0];
|
||||
my $nodes = $request->{node};
|
||||
|
||||
# This kit plugin is passed a list of node names.
|
||||
# We need to determine which kits are used by these
|
||||
# nodes to decide if this plugin should run or not.
|
||||
# Before running this plugin, we should check which
|
||||
# nodes are using the kit which this plugin belongs to,
|
||||
# and run the plugin only on these nodes.
|
||||
|
||||
my $kitdata = $request->{kitdata};
|
||||
if (! defined($kitdata)) {
|
||||
$kitdata = xCAT::KitPluginUtils->get_kits_used_by_nodes($nodes);
|
||||
$request->{kitdata} = $kitdata;
|
||||
my $nodes2;
|
||||
|
||||
if ($PLUGIN_KITNAME eq "TESTMODE") {
|
||||
# Don't do the check in test mode
|
||||
$nodes2 = $nodes;
|
||||
} else {
|
||||
# Do the check
|
||||
my $kitdata = $request->{kitdata};
|
||||
if (! defined($kitdata)) {
|
||||
$kitdata = xCAT::KitPluginUtils->get_kits_used_by_nodes($nodes);
|
||||
$request->{kitdata} = $kitdata;
|
||||
}
|
||||
|
||||
if (! exists($kitdata->{$PLUGIN_KITNAME})) {
|
||||
# None of the nodes are using this plugin's kit, so don't run the plugin.
|
||||
$rsp->{data}->[0] = "Skipped running \"$command\" plugin command for \"$PLUGIN_KITNAME\" kit.";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
$nodes2 = $kitdata->{$PLUGIN_KITNAME};
|
||||
}
|
||||
|
||||
if ($PLUGIN_KITNAME ne "TESTMODE" && ! exists($kitdata->{$PLUGIN_KITNAME})) {
|
||||
return;
|
||||
}
|
||||
|
||||
# Get the nodes using this plugin's kit
|
||||
$nodes = $kitdata->{$PLUGIN_KITNAME};
|
||||
|
||||
# Run the command
|
||||
|
||||
if($command eq 'kitnodeadd') {
|
||||
kitnodeadd($callback, $nodes);
|
||||
kitnodeadd($callback, $nodes2);
|
||||
}
|
||||
elsif ($command eq 'kitnoderemove') {
|
||||
kitnoderemove($callback, $nodes);
|
||||
kitnoderemove($callback, $nodes2);
|
||||
}
|
||||
elsif ($command eq 'kitnodeupdate') {
|
||||
kitnodeupdate($callback, $nodes);
|
||||
kitnodeupdate($callback, $nodes2);
|
||||
}
|
||||
elsif ($command eq 'kitnoderefresh') {
|
||||
kitnoderefresh($callback, $nodes);
|
||||
}
|
||||
elsif ($command eq 'kitnodefinished') {
|
||||
kitnodefinished($callback);
|
||||
kitnoderefresh($callback, $nodes2);
|
||||
|
||||
} else {
|
||||
my $rsp;
|
||||
@ -130,6 +196,27 @@ sub process_request {
|
||||
This command is called when one or more nodes are added
|
||||
to the cluster.
|
||||
|
||||
Command-line interface:
|
||||
kitnodeadd <noderange>
|
||||
|
||||
Parameters:
|
||||
$nodes: list of nodes
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclient kitnodeadd
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitnodeadd <noderange>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
@ -141,11 +228,15 @@ sub kitnodeadd {
|
||||
# Parameters
|
||||
my $nodes = shift;
|
||||
|
||||
$rsp->{data}->[0] = "Running kitnodeadd";
|
||||
$rsp->{data}->[0] = "Running kitnodeadd ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Nodes: @$nodes";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
#
|
||||
}
|
||||
|
||||
|
||||
@ -156,6 +247,27 @@ sub kitnodeadd {
|
||||
This command is called when one or more nodes are
|
||||
removed from the cluster.
|
||||
|
||||
Command-line interface:
|
||||
kitnoderemove <noderange>
|
||||
|
||||
Parameters:
|
||||
$nodes: list of nodes
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclient kitnoderemove
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitnoderemove <noderange>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
@ -167,11 +279,15 @@ sub kitnoderemove {
|
||||
# Parameters
|
||||
my $nodes = shift;
|
||||
|
||||
$rsp->{data}->[0] = "Running kitnoderemove";
|
||||
$rsp->{data}->[0] = "Running kitnoderemove ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Nodes: @$nodes";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
#
|
||||
}
|
||||
|
||||
|
||||
@ -182,6 +298,27 @@ sub kitnoderemove {
|
||||
This command is called when the configuration of one
|
||||
or more nodes are updated.
|
||||
|
||||
Command-line interface:
|
||||
kitnodeupdate <noderange>
|
||||
|
||||
Parameters:
|
||||
$nodes: list of nodes
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclient kitnodeupdate
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitnodeupdate <noderange>
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
@ -193,11 +330,15 @@ sub kitnodeupdate {
|
||||
# Parameters
|
||||
my $nodes = shift;
|
||||
|
||||
$rsp->{data}->[0] = "Running kitnodeupdate";
|
||||
$rsp->{data}->[0] = "Running kitnodeupdate ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Nodes: @$nodes";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
#
|
||||
}
|
||||
|
||||
|
||||
@ -205,8 +346,29 @@ sub kitnodeupdate {
|
||||
|
||||
=head3 kitnoderefresh
|
||||
|
||||
This command is called when node-related configuration
|
||||
files are updated.
|
||||
This command is called to refresh node-related configuration
|
||||
files.
|
||||
|
||||
Command-line interface:
|
||||
kitnoderefresh <noderange>
|
||||
|
||||
Parameters:
|
||||
$nodes: list of nodes
|
||||
|
||||
Return value:
|
||||
Info/Debug messages should be returned like so:
|
||||
$rsp->{data}->[0] = "Info messsage";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
Errors should be returned like so:
|
||||
$rsp->{data}->[0] = "Error messsage";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
Test Steps:
|
||||
# cd /opt/xcat/bin
|
||||
# ln -s xcatclient kitnoderefresh
|
||||
# cd -
|
||||
# XCATBYPASS=/path/to/this/plugin kitnoderefresh <noderange>
|
||||
|
||||
=cut
|
||||
|
||||
@ -219,33 +381,14 @@ sub kitnoderefresh {
|
||||
# Parameters
|
||||
my $nodes = shift;
|
||||
|
||||
$rsp->{data}->[0] = "Running kitnoderefresh";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 kitnodefinished
|
||||
|
||||
This command is called at the end of a node management
|
||||
operation.
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub kitnodefinished {
|
||||
my $callback = shift;
|
||||
my $rsp;
|
||||
|
||||
$rsp->{data}->[0] = "Running kitnodefinished";
|
||||
$rsp->{data}->[0] = "Running kitnoderefresh ($PLUGIN_KITNAME) ...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
$rsp->{data}->[0] = "Nodes: @$nodes";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
|
||||
# TODO
|
||||
# ... ADD YOUR CODE HERE
|
||||
#
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user