2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-05 12:37:54 +00:00
Files
xcat-core/xCAT-server/share/xcat/tools/dhcpop
T
Vinícius Ferrão ab86139959 Support configurable ISC OMAPI TSIG policy
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>
2026-05-07 03:57:10 -03:00

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;