diff --git a/perl-xCAT/xCAT/DHCP/OmapiRunner.pm b/perl-xCAT/xCAT/DHCP/OmapiRunner.pm new file mode 100644 index 000000000..63c5ea59a --- /dev/null +++ b/perl-xCAT/xCAT/DHCP/OmapiRunner.pm @@ -0,0 +1,77 @@ +package xCAT::DHCP::OmapiRunner; + +use strict; +use warnings; + +use File::Temp qw(tempfile); +use POSIX qw(WNOHANG); +use Time::HiRes qw(sleep); + +sub open_command_file { + my ($class, $directory) = @_; + + $directory ||= $class->_command_directory(); + mkdir $directory unless -d $directory; + + my ($handle, $path) = tempfile('omshell.XXXXXX', DIR => $directory, UNLINK => 0); + return { handle => $handle, path => $path }; +} + +sub run_command_file { + my ( $class, $command_file, $omshell_path ) = @_; + + my $pid = $class->_fork(); + return 'fork_error' unless defined $pid; + + if ( $pid == 0 ) { + open( STDIN, '<', $command_file ) or exit 127; ## no critic (InputOutput::RequireCheckedOpen) + open( STDOUT, '>', '/dev/null' ) or exit 127; ## no critic (InputOutput::RequireCheckedOpen) + open( STDERR, '>', '/dev/null' ) or exit 127; ## no critic (InputOutput::RequireCheckedOpen) + exec {$omshell_path} $omshell_path; + exit 127; + } + + for ( 1 .. $class->_completion_attempts() ) { + if ( waitpid( $pid, WNOHANG ) == $pid ) { + sleep $class->_completion_delay(); + return 'completed'; + } + sleep $class->_poll_interval(); + } + + kill 'TERM', $pid; + for ( 1 .. $class->_termination_attempts() ) { + return 'terminated' if waitpid( $pid, WNOHANG ) == $pid; + sleep $class->_poll_interval(); + } + + kill 'KILL', $pid; + waitpid( $pid, 0 ); + return 'killed'; +} + +sub _fork { + return fork(); +} + +sub _completion_attempts { + return 100; +} + +sub _termination_attempts { + return 20; +} + +sub _poll_interval { + return 0.1; +} + +sub _completion_delay { + return 1.0; +} + +sub _command_directory { + return '/tmp/xcat'; +} + +1; diff --git a/xCAT-server/lib/xcat/plugins/dhcp.pm b/xCAT-server/lib/xcat/plugins/dhcp.pm index 5ce2b0888..3b3807ffd 100644 --- a/xCAT-server/lib/xcat/plugins/dhcp.pm +++ b/xCAT-server/lib/xcat/plugins/dhcp.pm @@ -11,7 +11,6 @@ use strict; use IPC::Open2; use IPC::Open3; use IO::Select; -use File::Temp qw(tempfile); use Symbol qw/gensym/; use POSIX qw/WNOHANG/; use Time::HiRes qw(sleep); @@ -36,6 +35,7 @@ use xCAT::SvrUtils; use xCAT::DHCP::BootPolicy; use xCAT::DHCP::Backend; use xCAT::DHCP::OmapiPolicy; +use xCAT::DHCP::OmapiRunner; use xCAT::DHCP::Range; use xCAT::TableUtils; use xCAT::NetworkUtils qw/getipaddr/; @@ -412,45 +412,10 @@ sub _open_omshell_writer { my $settings = shift; - mkdir "/tmp/xcat" unless -d "/tmp/xcat"; - my ($omshell_stdin, $command_file) = tempfile('omshell.XXXXXX', DIR => '/tmp/xcat', UNLINK => 0); - return unless $omshell_stdin; + my $command = xCAT::DHCP::OmapiRunner->open_command_file(); + return unless ref($command) eq 'HASH' && $command->{handle}; - return ($omshell_stdin, { command_file => $command_file, omshell_path => $settings->{omshell_path} }); -} - -sub _run_omshell_command_file -{ - my ($command_file, $omshell_path) = @_; - - my $pid = fork(); - return unless defined $pid; - - if ($pid == 0) { - open(STDIN, '<', $command_file) or exit 127; ## no critic (InputOutput::RequireCheckedOpen) - open(STDOUT, '>', '/dev/null') or exit 127; ## no critic (InputOutput::RequireCheckedOpen) - open(STDERR, '>', '/dev/null') or exit 127; ## no critic (InputOutput::RequireCheckedOpen) - exec { $omshell_path } $omshell_path; - exit 127; - } - - for (1 .. 100) { - if (waitpid($pid, WNOHANG) == $pid) { - sleep 1.0; - return 1; - } - sleep 0.1; - } - - kill 'TERM', $pid; - for (1 .. 20) { - return if waitpid($pid, WNOHANG) == $pid; - sleep 0.1; - } - - kill 'KILL', $pid; - waitpid($pid, 0); - return; + return ($command->{handle}, { command_file => $command->{path}, omshell_path => $settings->{omshell_path} }); } sub _close_omshell_writer @@ -461,9 +426,12 @@ sub _close_omshell_writer return unless ref($writer) eq 'HASH'; - my $ok = _run_omshell_command_file($writer->{command_file}, $writer->{omshell_path}); + my $status = xCAT::DHCP::OmapiRunner->run_command_file( + $writer->{command_file}, $writer->{omshell_path} + ); unlink $writer->{command_file}; - syslog("local4|err", "omshell did not complete while updating DHCP reservations") unless $ok; + syslog("local4|err", "omshell did not complete while updating DHCP reservations") + unless $status eq 'completed'; } ###################################################### diff --git a/xCAT-server/share/xcat/tools/dhcpop b/xCAT-server/share/xcat/tools/dhcpop index f19435a6f..e69a16153 100755 --- a/xCAT-server/share/xcat/tools/dhcpop +++ b/xCAT-server/share/xcat/tools/dhcpop @@ -10,13 +10,9 @@ BEGIN use lib "$::XCATROOT/lib/perl"; use Getopt::Long; -use File::Temp qw(tempfile); use Fcntl ':flock'; -use IPC::Open3; -use POSIX qw/WNOHANG/; -use Symbol qw/gensym/; -use Time::HiRes qw(sleep); use xCAT::DHCP::OmapiPolicy; +use xCAT::DHCP::OmapiRunner; use xCAT::Table; sub usage{ @@ -146,41 +142,17 @@ if($help){ $omshell_commands .= "close\n"; } - mkdir "/tmp/xcat" unless -d "/tmp/xcat"; - my ($omshell, $command_file) = tempfile('omshell.XXXXXX', DIR => '/tmp/xcat', UNLINK => 0); + my $command = xCAT::DHCP::OmapiRunner->open_command_file(); + my $omshell = ref($command) eq 'HASH' ? $command->{handle} : undef; die "Unable to start omshell: $!" unless $omshell; print $omshell $omshell_commands; close($omshell); - my $pid = fork(); - die "Unable to start omshell: $!" unless defined $pid; - if ($pid == 0) { - open(STDIN, '<', $command_file) or exit 127; ## no critic (InputOutput::RequireCheckedOpen) - open(STDOUT, '>', '/dev/null') or exit 127; ## no critic (InputOutput::RequireCheckedOpen) - open(STDERR, '>', '/dev/null') or exit 127; ## no critic (InputOutput::RequireCheckedOpen) - exec { $settings->{omshell_path} } $settings->{omshell_path}; - exit 127; - } - - for (1 .. 100) { - if (waitpid($pid, WNOHANG) == $pid) { - sleep 1.0; - unlink $command_file; - exit 0; - } - sleep 0.1; - } - kill 'TERM', $pid; - for (1 .. 20) { - if (waitpid($pid, WNOHANG) == $pid) { - unlink $command_file; - exit 0; - } - sleep 0.1; - } - kill 'KILL', $pid; - waitpid($pid, 0); - unlink $command_file; + my $status = xCAT::DHCP::OmapiRunner->run_command_file( + $command->{path}, $settings->{omshell_path} + ); + die "Unable to start omshell: $!" if $status eq 'fork_error'; + unlink $command->{path}; }else{ &usage; exit 1;