mirror of https://github.com/apache/cloudstack.git
Merge 7f8b90f52f into 420bf6dff8
This commit is contained in:
commit
47d46a640b
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ public interface NetworkOrchestrationService {
|
|||
ConfigKey<Integer> NetworkThrottlingRate = new ConfigKey<>("Network", Integer.class, NetworkThrottlingRateCK, "200",
|
||||
"Default data transfer rate in megabits per second allowed in network.", true, ConfigKey.Scope.Zone);
|
||||
|
||||
ConfigKey<Integer> DhcpLeaseTimeout = new ConfigKey<>("Network", 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.",
|
||||
true, ConfigKey.Scope.Zone, "0-");
|
||||
|
||||
ConfigKey<Boolean> PromiscuousMode = new ConfigKey<>("Advanced", Boolean.class, "network.promiscuous.mode", "false",
|
||||
"Whether to allow or deny promiscuous mode on NICs for applicable network elements such as for vswitch/dvswitch portgroups.", true);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 ]
|
||||
|
|
|
|||
|
|
@ -296,6 +296,10 @@ public class CommandSetupHelper {
|
|||
dhcpCommand.setDefault(nic.isDefaultNic());
|
||||
dhcpCommand.setRemove(remove);
|
||||
|
||||
// Set DHCP lease timeout from zone-scoped config (0 = infinite)
|
||||
Long leaseTime = (long) NetworkOrchestrationService.DhcpLeaseTimeout.valueIn(router.getDataCenterId());
|
||||
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()));
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ import com.cloud.utils.net.Ip;
|
|||
import com.cloud.vm.NicVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.network.BgpPeerVO;
|
||||
import org.apache.cloudstack.network.dao.BgpPeerDetailsDao;
|
||||
import org.junit.Assert;
|
||||
|
|
@ -271,4 +273,42 @@ public class CommandSetupHelperTest {
|
|||
Assert.assertTrue(cmd instanceof SetBgpPeersCommand);
|
||||
Assert.assertEquals(4, ((SetBgpPeersCommand) cmd).getBpgPeers().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpLeaseTimeoutDefaultValue() {
|
||||
// Test that the default value is 0 (infinite)
|
||||
Integer defaultValue = NetworkOrchestrationService.DhcpLeaseTimeout.value();
|
||||
Assert.assertEquals("Default DHCP lease timeout should be 0 (infinite)", 0, defaultValue.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpLeaseTimeoutAcceptsZero() {
|
||||
// Test that 0 value is accepted (infinite lease)
|
||||
ConfigKey<Integer> configKey = NetworkOrchestrationService.DhcpLeaseTimeout;
|
||||
Assert.assertNotNull("ConfigKey should not be null", configKey);
|
||||
Assert.assertEquals("ConfigKey default should be 0", "0", configKey.defaultValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpLeaseTimeoutAcceptsPositiveValues() {
|
||||
// Test that positive values are accepted
|
||||
ConfigKey<Integer> configKey = NetworkOrchestrationService.DhcpLeaseTimeout;
|
||||
Assert.assertNotNull("ConfigKey should not be null", configKey);
|
||||
// Verify the config key exists and has expected default
|
||||
Assert.assertEquals("ConfigKey default should be 0", "0", configKey.defaultValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpLeaseTimeoutHasZoneScope() {
|
||||
// Test that the ConfigKey has Zone scope
|
||||
ConfigKey<Integer> configKey = NetworkOrchestrationService.DhcpLeaseTimeout;
|
||||
Assert.assertTrue("ConfigKey should have Zone scope", configKey.getScopes().contains(ConfigKey.Scope.Zone));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpLeaseTimeoutIsDynamic() {
|
||||
// Test that the ConfigKey is dynamic (can be updated at runtime)
|
||||
ConfigKey<Integer> configKey = NetworkOrchestrationService.DhcpLeaseTimeout;
|
||||
Assert.assertTrue("ConfigKey should be dynamic", configKey.isDynamic());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,184 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.network.router;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.routing.DhcpEntryCommand;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.NicVO;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Integration tests for DHCP lease timeout functionality.
|
||||
* Tests the end-to-end flow from ConfigKey through DhcpEntryCommand creation.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DhcpLeaseTimeoutIntegrationTest {
|
||||
|
||||
@InjectMocks
|
||||
protected CommandSetupHelper commandSetupHelper = new CommandSetupHelper();
|
||||
|
||||
@Mock
|
||||
NicDao nicDao;
|
||||
@Mock
|
||||
NetworkDao networkDao;
|
||||
@Mock
|
||||
NetworkModel networkModel;
|
||||
@Mock
|
||||
NetworkOfferingDao networkOfferingDao;
|
||||
@Mock
|
||||
NetworkOfferingDetailsDao networkOfferingDetailsDao;
|
||||
@Mock
|
||||
NetworkDetailsDao networkDetailsDao;
|
||||
@Mock
|
||||
RouterControlHelper routerControlHelper;
|
||||
@Mock
|
||||
DataCenterDao dcDao;
|
||||
|
||||
private VirtualRouter mockRouter;
|
||||
private UserVmVO mockVm;
|
||||
private NicVO mockNic;
|
||||
private DataCenterVO mockDc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "_nicDao", nicDao);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "_networkDao", networkDao);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "_networkModel", networkModel);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "_networkOfferingDao", networkOfferingDao);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "networkOfferingDetailsDao", networkOfferingDetailsDao);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "networkDetailsDao", networkDetailsDao);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "_routerControlHelper", routerControlHelper);
|
||||
ReflectionTestUtils.setField(commandSetupHelper, "_dcDao", dcDao);
|
||||
|
||||
// Create common mocks
|
||||
mockRouter = Mockito.mock(VirtualRouter.class);
|
||||
mockVm = Mockito.mock(UserVmVO.class);
|
||||
mockNic = Mockito.mock(NicVO.class);
|
||||
mockDc = Mockito.mock(DataCenterVO.class);
|
||||
|
||||
// Setup default mock behaviors
|
||||
when(mockRouter.getId()).thenReturn(100L);
|
||||
when(mockRouter.getInstanceName()).thenReturn("r-100-VM");
|
||||
when(mockRouter.getDataCenterId()).thenReturn(1L);
|
||||
|
||||
when(mockVm.getHostName()).thenReturn("test-vm");
|
||||
|
||||
when(mockNic.getMacAddress()).thenReturn("02:00:0a:0b:0c:0d");
|
||||
when(mockNic.getIPv4Address()).thenReturn("10.1.1.10");
|
||||
when(mockNic.getIPv6Address()).thenReturn(null);
|
||||
when(mockNic.getNetworkId()).thenReturn(400L);
|
||||
when(mockNic.isDefaultNic()).thenReturn(true);
|
||||
|
||||
when(dcDao.findById(anyLong())).thenReturn(mockDc);
|
||||
when(mockDc.getNetworkType()).thenReturn(com.cloud.dc.DataCenter.NetworkType.Advanced);
|
||||
when(routerControlHelper.getRouterControlIp(anyLong())).thenReturn("10.1.1.1");
|
||||
when(routerControlHelper.getRouterIpInNetwork(anyLong(), anyLong())).thenReturn("10.1.1.1");
|
||||
when(networkModel.getExecuteInSeqNtwkElmtCmd()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpEntryCommandContainsLeaseTime() {
|
||||
// Test that DhcpEntryCommand includes the lease time from ConfigKey
|
||||
Commands cmds = new Commands(Command.OnError.Continue);
|
||||
commandSetupHelper.createDhcpEntryCommand(mockRouter, mockVm, mockNic, false, cmds);
|
||||
|
||||
Assert.assertEquals("Should have one DHCP command", 1, cmds.size());
|
||||
DhcpEntryCommand dhcpCmd = (DhcpEntryCommand) cmds.toCommands()[0];
|
||||
Assert.assertNotNull("DHCP command should not be null", dhcpCmd);
|
||||
Assert.assertNotNull("Lease time should not be null", dhcpCmd.getLeaseTime());
|
||||
|
||||
// Default value should be 0 (infinite)
|
||||
Assert.assertEquals("Default lease time should be 0", Long.valueOf(0L), dhcpCmd.getLeaseTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpEntryCommandUsesZoneScopedValue() {
|
||||
// Test that the command uses zone-scoped configuration
|
||||
Long zoneId = mockRouter.getDataCenterId();
|
||||
Integer expectedLeaseTime = NetworkOrchestrationService.DhcpLeaseTimeout.valueIn(zoneId);
|
||||
|
||||
Commands cmds = new Commands(Command.OnError.Continue);
|
||||
commandSetupHelper.createDhcpEntryCommand(mockRouter, mockVm, mockNic, false, cmds);
|
||||
|
||||
DhcpEntryCommand dhcpCmd = (DhcpEntryCommand) cmds.toCommands()[0];
|
||||
Assert.assertEquals("Lease time should match zone-scoped config",
|
||||
expectedLeaseTime.longValue(), dhcpCmd.getLeaseTime().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfiniteLeaseWithZeroValue() {
|
||||
// Test that 0 value represents infinite lease
|
||||
ConfigKey<Integer> configKey = NetworkOrchestrationService.DhcpLeaseTimeout;
|
||||
Assert.assertEquals("Default value should be 0 for infinite lease", "0", configKey.defaultValue());
|
||||
|
||||
Commands cmds = new Commands(Command.OnError.Continue);
|
||||
commandSetupHelper.createDhcpEntryCommand(mockRouter, mockVm, mockNic, false, cmds);
|
||||
|
||||
DhcpEntryCommand dhcpCmd = (DhcpEntryCommand) cmds.toCommands()[0];
|
||||
Assert.assertEquals("Lease time 0 represents infinite lease", Long.valueOf(0L), dhcpCmd.getLeaseTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpCommandForNonDefaultNic() {
|
||||
// Test DHCP command creation for non-default NIC
|
||||
when(mockNic.isDefaultNic()).thenReturn(false);
|
||||
|
||||
Commands cmds = new Commands(Command.OnError.Continue);
|
||||
commandSetupHelper.createDhcpEntryCommand(mockRouter, mockVm, mockNic, false, cmds);
|
||||
|
||||
DhcpEntryCommand dhcpCmd = (DhcpEntryCommand) cmds.toCommands()[0];
|
||||
Assert.assertNotNull("DHCP command should be created for non-default NIC", dhcpCmd);
|
||||
Assert.assertNotNull("Lease time should be set even for non-default NIC", dhcpCmd.getLeaseTime());
|
||||
Assert.assertFalse("Command should reflect non-default NIC", dhcpCmd.isDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDhcpCommandWithRemoveFlag() {
|
||||
// Test DHCP command with remove flag set
|
||||
Commands cmds = new Commands(Command.OnError.Continue);
|
||||
commandSetupHelper.createDhcpEntryCommand(mockRouter, mockVm, mockNic, true, cmds);
|
||||
|
||||
DhcpEntryCommand dhcpCmd = (DhcpEntryCommand) cmds.toCommands()[0];
|
||||
Assert.assertNotNull("DHCP command should be created even with remove flag", dhcpCmd);
|
||||
Assert.assertTrue("Remove flag should be set", dhcpCmd.isRemove());
|
||||
// Lease time should still be included even for removal
|
||||
Assert.assertNotNull("Lease time should be present even for removal", dhcpCmd.getLeaseTime());
|
||||
}
|
||||
}
|
||||
|
|
@ -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'],
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue