Enhance DHCP functionality by adding lease time support across various components. Updated DhcpEntryCommand to include lease time, modified VmDhcpConfig to handle lease time, and adjusted related scripts and configurations to accommodate this new parameter. This allows for configurable DHCP lease durations, improving flexibility in network management.

This commit is contained in:
Shawn Edwards 2026-01-12 11:22:13 -06:00
parent b8813c7b24
commit bb72490b72
9 changed files with 76 additions and 17 deletions

View File

@ -36,6 +36,7 @@ public class DhcpEntryCommand extends NetworkElementCommand {
private boolean isDefault;
boolean executeInSequence = false;
boolean remove;
Long leaseTime;
public boolean isRemove() {
return remove;
@ -152,4 +153,12 @@ public class DhcpEntryCommand extends NetworkElementCommand {
public void setDefault(boolean isDefault) {
this.isDefault = isDefault;
}
public Long getLeaseTime() {
return leaseTime;
}
public void setLeaseTime(Long leaseTime) {
this.leaseTime = leaseTime;
}
}

View File

@ -35,7 +35,7 @@ public class DhcpEntryConfigItem extends AbstractConfigItemFacade {
final DhcpEntryCommand command = (DhcpEntryCommand) cmd;
final VmDhcpConfig vmDhcpConfig = new VmDhcpConfig(command.getVmName(), command.getVmMac(), command.getVmIpAddress(), command.getVmIp6Address(), command.getDuid(), command.getDefaultDns(),
command.getDefaultRouter(), command.getStaticRoutes(), command.isDefault(), command.isRemove());
command.getDefaultRouter(), command.getStaticRoutes(), command.isDefault(), command.isRemove(), command.getLeaseTime());
return generateConfigItems(vmDhcpConfig);
}

View File

@ -29,6 +29,7 @@ public class VmDhcpConfig extends ConfigBase {
private String defaultGateway;
private String staticRoutes;
private boolean defaultEntry;
private Long leaseTime;
// Indicate if the entry should be removed when set to true
private boolean remove;
@ -39,6 +40,11 @@ public class VmDhcpConfig extends ConfigBase {
public VmDhcpConfig(String hostName, String macAddress, String ipv4Address, String ipv6Address, String ipv6Duid, String dnsAddresses, String defaultGateway,
String staticRoutes, boolean defaultEntry, boolean remove) {
this(hostName, macAddress, ipv4Address, ipv6Address, ipv6Duid, dnsAddresses, defaultGateway, staticRoutes, defaultEntry, remove, null);
}
public VmDhcpConfig(String hostName, String macAddress, String ipv4Address, String ipv6Address, String ipv6Duid, String dnsAddresses, String defaultGateway,
String staticRoutes, boolean defaultEntry, boolean remove, Long leaseTime) {
super(VM_DHCP);
this.hostName = hostName;
this.macAddress = macAddress;
@ -50,6 +56,7 @@ public class VmDhcpConfig extends ConfigBase {
this.staticRoutes = staticRoutes;
this.defaultEntry = defaultEntry;
this.remove = remove;
this.leaseTime = leaseTime;
}
public String getHostName() {
@ -132,4 +139,12 @@ public class VmDhcpConfig extends ConfigBase {
this.defaultEntry = defaultEntry;
}
public Long getLeaseTime() {
return leaseTime;
}
public void setLeaseTime(Long leaseTime) {
this.leaseTime = leaseTime;
}
}

View File

@ -17,18 +17,18 @@
# under the License.
# Usage: dhcpd_edithosts.py mac ip hostname dns gateway nextserver
# Usage: dhcpd_edithosts.py mac ip hostname dns gateway nextserver [leasetime]
import sys, os
from os.path import exists
from time import sleep
from os import remove
usage = '''dhcpd_edithosts.py mac ip hostname dns gateway nextserver'''
usage = '''dhcpd_edithosts.py mac ip hostname dns gateway nextserver [leasetime]'''
conf_path = "/etc/dhcpd.conf"
file_lock = "/etc/dhcpd.conf_locked"
sleep_max = 20
host_entry = 'host %s { hardware ethernet %s; fixed-address %s; option domain-name-servers %s; option domain-name "%s"; option routers %s; default-lease-time infinite; max-lease-time infinite; min-lease-time infinite; filename "pxelinux.0";}'
host_entry1 = 'host %s { hardware ethernet %s; fixed-address %s; option domain-name-servers %s; option domain-name "%s"; option routers %s; default-lease-time infinite; max-lease-time infinite; min-lease-time infinite; next-server %s; filename "pxelinux.0";}'
host_entry = 'host %s { hardware ethernet %s; fixed-address %s; option domain-name-servers %s; option domain-name "%s"; option routers %s; default-lease-time %s; max-lease-time %s; min-lease-time %s; filename "pxelinux.0";}'
host_entry1 = 'host %s { hardware ethernet %s; fixed-address %s; option domain-name-servers %s; option domain-name "%s"; option routers %s; default-lease-time %s; max-lease-time %s; min-lease-time %s; next-server %s; filename "pxelinux.0";}'
def lock():
if exists(file_lock):
count = 0
@ -59,10 +59,14 @@ def unlock():
print "Cannot remove file lock at %s" % file_lock
return False
def insert_host_entry(mac, ip, hostname, dns, gateway, next_server):
def insert_host_entry(mac, ip, hostname, dns, gateway, next_server, lease_time="infinite"):
if lock() == False:
return 1
# Convert 0 to 'infinite' for lease time
if lease_time == "0":
lease_time = "infinite"
cmd = 'sed -i /"fixed-address %s"/d %s' % (ip, conf_path)
ret = os.system(cmd)
if ret != 0:
@ -78,9 +82,9 @@ def insert_host_entry(mac, ip, hostname, dns, gateway, next_server):
return 1
if next_server != "null":
entry = host_entry1 % (hostname, mac, ip, dns, "cloudnine.internal", gateway, next_server)
entry = host_entry1 % (hostname, mac, ip, dns, "cloudnine.internal", gateway, lease_time, lease_time, lease_time, next_server)
else:
entry = host_entry % (hostname, mac, ip, dns, "cloudnine.internal", gateway)
entry = host_entry % (hostname, mac, ip, dns, "cloudnine.internal", gateway, lease_time, lease_time, lease_time)
cmd = '''echo '%s' >> %s''' % (entry, conf_path)
ret = os.system(cmd)
if ret != 0:
@ -111,6 +115,7 @@ if __name__ == "__main__":
dns = sys.argv[4]
gateway = sys.argv[5]
next_server = sys.argv[6]
lease_time = sys.argv[7] if len(sys.argv) > 7 else "infinite"
if exists(conf_path) == False:
conf_path = "/etc/dhcp/dhcpd.conf"
@ -118,5 +123,5 @@ if __name__ == "__main__":
print "Cannot find dhcpd.conf"
sys.exit(1)
ret = insert_host_entry(mac, ip, hostname, dns, gateway, next_server)
ret = insert_host_entry(mac, ip, hostname, dns, gateway, next_server, lease_time)
sys.exit(ret)

View File

@ -21,6 +21,7 @@
# $1 : the mac address
# $2 : the associated ip address
# $3 : the hostname
# $4 : the lease time (optional, defaults to 'infinite')
wait_for_dnsmasq () {
local _pid=$(pidof dnsmasq)
@ -41,11 +42,17 @@ no_dhcp_release=$?
[ ! -f /etc/dhcphosts.txt ] && touch /etc/dhcphosts.txt
[ ! -f /var/lib/misc/dnsmasq.leases ] && touch /var/lib/misc/dnsmasq.leases
# Set lease time, default to 'infinite', convert 0 to 'infinite'
lease_time=${4:-infinite}
if [ "$lease_time" = "0" ]; then
lease_time=infinite
fi
sed -i /$1/d /etc/dhcphosts.txt
sed -i /$2,/d /etc/dhcphosts.txt
sed -i /$3,/d /etc/dhcphosts.txt
echo "$1,$2,$3,infinite" >>/etc/dhcphosts.txt
echo "$1,$2,$3,$lease_time" >>/etc/dhcphosts.txt
#release previous dhcp lease if present
if [ $no_dhcp_release -eq 0 ]

View File

@ -351,6 +351,15 @@ public enum Config {
ConfigKey.Kind.CSV,
null),
DhcpLeaseTimeout(
"Network",
ManagementServer.class,
Integer.class,
"dhcp.lease.timeout",
"0",
"DHCP lease time in seconds for VMs. Use 0 for infinite lease time (default). A non-zero value sets the lease duration in seconds.",
null),
//VPN
RemoteAccessVpnPskLength(
"Network",

View File

@ -296,6 +296,11 @@ public class CommandSetupHelper {
dhcpCommand.setDefault(nic.isDefaultNic());
dhcpCommand.setRemove(remove);
// Set DHCP lease timeout from global config (0 = infinite)
String leaseTimeStr = _configDao.getValue(Config.DhcpLeaseTimeout.key());
Long leaseTime = (leaseTimeStr != null) ? Long.parseLong(leaseTimeStr) : 0L;
dhcpCommand.setLeaseTime(leaseTime);
dhcpCommand.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId()));
dhcpCommand.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
dhcpCommand.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, _routerControlHelper.getRouterIpInNetwork(nic.getNetworkId(), router.getId()));

View File

@ -199,12 +199,14 @@ class CsDhcp(CsDataBag):
def add(self, entry):
self.add_host(entry['ipv4_address'], entry['host_name'])
# Lease time set to "infinite" since we properly control all DHCP/DNS config via CloudStack.
# Lease time is configurable via CloudStack global config dhcp.lease.timeout
# 0 = infinite (default), otherwise the value represents seconds
# Infinite time helps avoid some edge cases which could cause DHCPNAK being sent to VMs since
# (RHEL) system lose routes when they receive DHCPNAK.
# When VM is expunged, its active lease and DHCP/DNS config is properly removed from related files in VR,
# so the infinite duration of lease does not cause any issues or garbage.
lease = 'infinite'
lease_time = entry.get('lease_time', 0)
lease = 'infinite' if lease_time == 0 else str(lease_time)
if entry['default_entry']:
self.dhcp_hosts.add("%s,%s,%s,%s" % (entry['mac_address'],

View File

@ -21,7 +21,7 @@
# edithosts.sh -- edit the dhcphosts file on the routing domain
usage() {
printf "Usage: %s: -m <MAC address> -4 <IPv4 address> -6 <IPv6 address> -h <hostname> -d <default router> -n <name server address> -s <Routes> -u <DUID> [-N]\n" $(basename $0) >&2
printf "Usage: %s: -m <MAC address> -4 <IPv4 address> -6 <IPv6 address> -h <hostname> -d <default router> -n <name server address> -s <Routes> -u <DUID> -l <lease time> [-N]\n" $(basename $0) >&2
}
mac=
@ -33,8 +33,9 @@ dns=
routes=
duid=
nondefault=
lease_time=infinite
while getopts 'm:4:h:d:n:s:6:u:N' OPTION
while getopts 'm:4:h:d:n:s:6:u:l:N' OPTION
do
case $OPTION in
m) mac="$OPTARG"
@ -53,6 +54,8 @@ do
;;
s) routes="$OPTARG"
;;
l) lease_time="$OPTARG"
;;
N) nondefault=1
;;
?) usage
@ -124,17 +127,21 @@ fi
sed -i /$host,/d $DHCP_HOSTS
#put in the new entry
# If lease_time is 0, use 'infinite', otherwise use the value
if [ "$lease_time" = "0" ]; then
lease_time=infinite
fi
if [ $ipv4 ]
then
echo "$mac,$ipv4,$host,infinite" >>$DHCP_HOSTS
echo "$mac,$ipv4,$host,$lease_time" >>$DHCP_HOSTS
fi
if [ $ipv6 ]
then
if [ $nondefault ]
then
echo "id:$duid,set:nondefault6,[$ipv6],$host,infinite" >>$DHCP_HOSTS
echo "id:$duid,set:nondefault6,[$ipv6],$host,$lease_time" >>$DHCP_HOSTS
else
echo "id:$duid,[$ipv6],$host,infinite" >>$DHCP_HOSTS
echo "id:$duid,[$ipv6],$host,$lease_time" >>$DHCP_HOSTS
fi
fi