mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-05 20:47:55 +00:00
ab86139959
Add a shared OMAPI policy helper for ISC DHCP and DDNS so administrators can select the key name, signing algorithm, and omshell path from the site table while preserving the existing xcat_key hmac-md5 default. Keep local ISC updates from hanging indefinitely when omshell does not exit, and use a static host-declaration fallback for local Ubuntu ISC releases where omshell is unstable for xCAT host updates. Co-authored-by: gskouson <1507929+gskouson@users.noreply.github.com>
192 lines
5.6 KiB
Perl
Executable File
192 lines
5.6 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
#use Data::Dumper;
|
|
use strict;
|
|
use warnings;
|
|
|
|
BEGIN
|
|
{
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
|
}
|
|
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::Table;
|
|
|
|
sub usage{
|
|
print "Usage: dhcphelper -h \n";
|
|
print "\n";
|
|
print " dhcphelper -r|--rm -m|--mac <mac address> [ -a|--ip <ip address>] [ -n|--name <node name>]\n";
|
|
print " delete the dhcp lease of specified <mac>,<ip address> and <node name>\n";
|
|
print "\n";
|
|
|
|
return;
|
|
}
|
|
|
|
my $help;
|
|
my $rmop;
|
|
my $mac;
|
|
my $ip;
|
|
my $hostname;
|
|
GetOptions ("m|mac=s" => \$mac, # numeric
|
|
"a|ip=s" => \$ip, # string
|
|
"n|name=s" => \$hostname, # string
|
|
"r|rm" => \$rmop, # flag
|
|
"h|help" => \$help) # flag
|
|
or &usage;
|
|
|
|
if($help){
|
|
&usage;
|
|
exit 0;
|
|
}elsif($rmop){
|
|
require xCAT::DHCP::Backend;
|
|
my $backend = xCAT::DHCP::Backend->new_backend();
|
|
if (ref($backend) ne 'HASH' && $backend->name eq 'kea') {
|
|
if ($mac && $mac !~ /:/) {
|
|
$mac = lc($mac);
|
|
$mac =~ s/(\w{2})/$1:/g;
|
|
$mac =~ s/:$//;
|
|
}
|
|
|
|
mkdir "/tmp/xcat" unless -d "/tmp/xcat";
|
|
open(my $dhcplockfd, ">", "/tmp/xcat/dhcplock") or die "Unable to lock DHCP state: $!"; ## no critic (InputOutput::RequireBriefOpen)
|
|
flock($dhcplockfd, LOCK_EX);
|
|
|
|
my $config4 = $backend->load_dhcp4_config();
|
|
if ($config4->{error}) {
|
|
print "Error: $config4->{error}\n";
|
|
exit 1;
|
|
}
|
|
my $config6;
|
|
my $have_dhcp6 = -e $backend->dhcp6_config_file();
|
|
if ($have_dhcp6) {
|
|
$config6 = $backend->load_dhcp6_config();
|
|
if ($config6->{error}) {
|
|
print "Error: $config6->{error}\n";
|
|
exit 1;
|
|
}
|
|
}
|
|
|
|
my @matches;
|
|
push @matches, { hostname => $hostname } if $hostname;
|
|
push @matches, { 'hw-address' => lc($mac) } if $mac;
|
|
push @matches, { 'ip-address' => $ip } if $ip;
|
|
|
|
foreach my $match (@matches) {
|
|
$backend->delete_reservations($config4, $match);
|
|
$backend->delete_reservations($config6, $match) if $config6;
|
|
}
|
|
|
|
my $result = $backend->write_dhcp4_json($backend->encode_config($config4));
|
|
if ($result->{error}) {
|
|
print "Error: $result->{error}\n";
|
|
exit 1;
|
|
}
|
|
if ($config6) {
|
|
my $result6 = $backend->write_dhcp6_json($backend->encode_config($config6));
|
|
if ($result6->{error}) {
|
|
print "Error: $result6->{error}\n";
|
|
exit 1;
|
|
}
|
|
}
|
|
|
|
my $restart = $backend->restart_services(ipv6 => $config6 ? 1 : 0);
|
|
if ($restart->{error}) {
|
|
print "Error: $restart->{error}\n";
|
|
exit 1;
|
|
}
|
|
exit 0;
|
|
}
|
|
|
|
my $settings = xCAT::DHCP::OmapiPolicy->settings();
|
|
if ($settings->{error}) {
|
|
print "Error: $settings->{error}\n";
|
|
exit 1;
|
|
}
|
|
|
|
my $passtab = xCAT::Table->new('passwd');
|
|
my $pent = $passtab->getAttribs({ key => 'omapi', username => $settings->{key_name} }, qw(username password));
|
|
my $passwd = $pent ? $pent->{password} : undef;
|
|
if(!$passwd){
|
|
print "Error: no 'omapi' entry defined in passwd table!";
|
|
exit 1;
|
|
}
|
|
|
|
my $omshell_commands = xCAT::DHCP::OmapiPolicy->omshell_preamble($settings, secret => $passwd);
|
|
$omshell_commands .= "connect\n";
|
|
|
|
if($hostname){
|
|
$omshell_commands .= "new host\n";
|
|
$omshell_commands .= "set name = \"$hostname\"\n"; #Find and destroy conflict name
|
|
$omshell_commands .= "open\n";
|
|
$omshell_commands .= "remove\n";
|
|
$omshell_commands .= "close\n";
|
|
}
|
|
|
|
if ($mac)
|
|
{
|
|
$omshell_commands .= "new host\n";
|
|
$omshell_commands .= "set hardware-address = " . $mac . "\n"; #find and destroy mac conflict
|
|
$omshell_commands .= "open\n";
|
|
$omshell_commands .= "remove\n";
|
|
$omshell_commands .= "close\n";
|
|
}
|
|
|
|
if($ip){
|
|
$omshell_commands .= "new host\n";
|
|
$omshell_commands .= "set ip-address = $ip\n"; #find and destroy ip conflict
|
|
$omshell_commands .= "open\n";
|
|
$omshell_commands .= "remove\n";
|
|
$omshell_commands .= "close\n";
|
|
}
|
|
|
|
mkdir "/tmp/xcat" unless -d "/tmp/xcat";
|
|
my ($omshell, $command_file) = tempfile('omshell.XXXXXX', DIR => '/tmp/xcat', UNLINK => 0);
|
|
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;
|
|
}else{
|
|
&usage;
|
|
exit 1;
|
|
}
|
|
|
|
|
|
#print "$mac-$ip-$hostname\n"
|
|
exit 0;
|