From 9e86fdf1b67c13bcb96b20d089726c89e4eaf16a Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Tue, 13 Jan 2026 13:36:25 +0530 Subject: [PATCH 1/4] Fix cloud-sysvmadmin hang (#12355) --- setup/bindir/cloud-sysvmadm.in | 129 +++++++++------------------------ 1 file changed, 33 insertions(+), 96 deletions(-) diff --git a/setup/bindir/cloud-sysvmadm.in b/setup/bindir/cloud-sysvmadm.in index a262f6b710e..00b24806d07 100755 --- a/setup/bindir/cloud-sysvmadm.in +++ b/setup/bindir/cloud-sysvmadm.in @@ -184,49 +184,29 @@ stop_start_system() { stop_start_router() { prepare_ids_clause router=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select uuid from vm_instance where state=\"Running\" and type=\"DomainRouter\"$zone$vmidsclause"`) - length_router=(${#router[@]}) + length_router=${#router[@]} echo -e "\nStopping and starting $length_router running routing vm(s)$inzone$withids... " echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_router running routing vm(s)$inzone$withids... " >>$LOGFILE #Spawn reboot router in parallel - run commands in chunks - number of threads is configurable + if [ $maxthreads -gt $length_router ]; then + maxthreads=$length_router + fi pids=() for d in "${router[@]}"; do reboot_router $d & pids=( "${pids[@]}" $! ) - - length_pids=(${#pids[@]}) - unfinishedPids=(${#pids[@]}) - - if [ $maxthreads -gt $length_router ]; then - maxthreads=$length_router - fi + length_pids=${#pids[@]} if [ $length_pids -ge $maxthreads ]; then - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - count=0 - for (( i = 0 ; i < $length_pids; i++ )); do - if ! ps ax | grep -v grep | grep ${pids[$i]} > /dev/null; then - count=`expr $count + 1` - fi - done - - if [ $count -eq $unfinishedPids ]; then - unfinishedPids=0 - fi - - done - - #remove all elements from pids - if [ $unfinishedPids -eq 0 ]; then - pids=() - length_pids=(${#pids[@]}) - fi - + # Wait for $maxthreads number of processes to finish + wait + # Clear the pids array for the next batch + pids=() fi done @@ -234,9 +214,8 @@ stop_start_router() { if [ "$length_router" == "0" ];then echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No running router vms found \n" >>$LOGFILE else - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - done + # Wait for the remaining background processes to finish + wait echo -e "Done restarting router(s)$inzone$withids. \n" echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting router(s)$inzone$withids. \n" >>$LOGFILE @@ -288,49 +267,29 @@ reboot_router(){ restart_networks(){ networks=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select n.id from networks n, network_offerings no where n.network_offering_id = no.id and no.system_only = 0 and n.removed is null$zone"`) - length_networks=(${#networks[@]}) + length_networks=${#networks[@]} echo -e "\nRestarting $length_networks networks$inzone... " echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Restarting $length_networks networks$inzone... " >>$LOGFILE #Spawn restart network in parallel - run commands in chunks - number of threads is configurable + if [ $maxthreads -gt $length_networks ]; then + maxthreads=$length_networks + fi pids=() for d in "${networks[@]}"; do restart_network $d & pids=( "${pids[@]}" $! ) - - length_pids=(${#pids[@]}) - unfinishedPids=(${#pids[@]}) - - if [ $maxthreads -gt $length_networks ]; then - maxthreads=$length_networks - fi + length_pids=${#pids[@]} if [ $length_pids -ge $maxthreads ]; then - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - count=0 - for (( i = 0 ; i < $length_pids; i++ )); do - if ! ps ax | grep -v grep | grep ${pids[$i]} > /dev/null; then - count=`expr $count + 1` - fi - done - - if [ $count -eq $unfinishedPids ]; then - unfinishedPids=0 - fi - - done - - #remove all elements from pids - if [ $unfinishedPids -eq 0 ]; then - pids=() - length_pids=(${#pids[@]}) - fi - + # Wait for $maxthreads number of processes to finish + wait + # Clear the pids array for the next batch + pids=() fi done @@ -339,9 +298,8 @@ restart_networks(){ if [ "$length_networks" == "0" ];then echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No networks found \n" >>$LOGFILE else - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - done + # Wait for the remaining background processes to finish + wait echo -e "Done restarting networks$inzone. \n" echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting networks$inzone. \n" >>$LOGFILE @@ -392,49 +350,29 @@ restart_vpc(){ restart_vpcs(){ vpcs=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select uuid from vpc WHERE removed is null$zone"`) - length_vpcs=(${#vpcs[@]}) + length_vpcs=${#vpcs[@]} echo -e "\nRestarting $length_vpcs vpcs... " echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Restarting $length_vpcs vpcs... " >>$LOGFILE #Spawn restart vpcs in parallel - run commands in chunks - number of threads is configurable + if [ $maxthreads -gt $length_vpcs ]; then + maxthreads=$length_vpcs + fi pids=() for d in "${vpcs[@]}"; do restart_vpc $d & pids=( "${pids[@]}" $! ) - - length_pids=(${#pids[@]}) - unfinishedPids=(${#pids[@]}) - - if [ $maxthreads -gt $length_vpcs ]; then - maxthreads=$length_vpcs - fi + length_pids=${#pids[@]} if [ $length_pids -ge $maxthreads ]; then - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - count=0 - for (( i = 0 ; i < $length_pids; i++ )); do - if ! ps ax | grep -v grep | grep ${pids[$i]} > /dev/null; then - count=`expr $count + 1` - fi - done - - if [ $count -eq $unfinishedPids ]; then - unfinishedPids=0 - fi - - done - - #remove all elements from pids - if [ $unfinishedPids -eq 0 ]; then - pids=() - length_pids=(${#pids[@]}) - fi - + # Wait for $maxthreads number of processes to finish + wait + # Clear the pids array for the next batch + pids=() fi done @@ -443,9 +381,8 @@ restart_vpcs(){ if [ "$length_vpcs" == "0" ];then echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No vpcs found \n" >>$LOGFILE else - while [ $unfinishedPids -gt 0 ]; do - sleep 10 - done + # Wait for the remaining background processes to finish + wait echo -e "Done restarting vpcs$inzone. \n" echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting vpcs$inzone. \n" >>$LOGFILE From b8ed34e2a88ed528a52d12824ad32c19586b5c9e Mon Sep 17 00:00:00 2001 From: Vishesh <8760112+vishesh92@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:18:55 +0530 Subject: [PATCH 2/4] Reset modifier button's state (#12187) --- systemvm/agent/noVNC/app/ui.js | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/systemvm/agent/noVNC/app/ui.js b/systemvm/agent/noVNC/app/ui.js index 75f2eb03f71..85530549e60 100644 --- a/systemvm/agent/noVNC/app/ui.js +++ b/systemvm/agent/noVNC/app/ui.js @@ -29,6 +29,14 @@ const UI = { connected: false, desktopName: "", + // Modifier key configuration + _modifierKeys: { + shift: { keysym: KeyTable.XK_Shift_L, code: "ShiftLeft", buttonId: 'noVNC_toggle_shift_button' }, + ctrl: { keysym: KeyTable.XK_Control_L, code: "ControlLeft", buttonId: 'noVNC_toggle_ctrl_button' }, + alt: { keysym: KeyTable.XK_Alt_L, code: "AltLeft", buttonId: 'noVNC_toggle_alt_button' }, + windows: { keysym: KeyTable.XK_Super_L, code: "MetaLeft", buttonId: 'noVNC_toggle_windows_button' } + }, + statusTimeout: null, hideKeyboardTimeout: null, idleControlbarTimeout: null, @@ -125,6 +133,11 @@ const UI = { document.getElementById("noVNC_status") .addEventListener('click', UI.hideStatus); + // Handle tab/window close to release modifier keys + // This is critical for VMware VMs using websocket reverse proxy + window.addEventListener('beforeunload', UI.handleBeforeUnload); + window.addEventListener('pagehide', UI.handlePageHide); + // Bootstrap fallback input handler UI.keyboardinputReset(); @@ -1740,6 +1753,39 @@ const UI = { UI.idleControlbar(); }, + _sendKeyUp(keysym, code) { + if (!UI.rfb) return; + UI.rfb.sendKey(keysym, code, false); + }, + + // Release a single modifier key if it's pressed + _releaseModifierKey(keyName) { + const keyConfig = UI._modifierKeys[keyName]; + if (!keyConfig) return false; + + const btn = document.getElementById(keyConfig.buttonId); + if (!btn || !btn.classList.contains("noVNC_selected")) { + return false; + } + + UI._sendKeyUp(keyConfig.keysym, keyConfig.code); + btn.classList.remove("noVNC_selected"); + return true; + }, + + // Release all currently pressed modifier keys + _releaseAllModifierKeys() { + let keysReleased = false; + + // Release all modifier keys + for (const keyName in UI._modifierKeys) { + if (UI._releaseModifierKey(keyName)) { + keysReleased = true; + } + } + return keysReleased; + }, + // Move focus to the screen in order to be able to use the // keyboard right after these extra keys. // The exception is when a virtual keyboard is used, because @@ -1836,6 +1882,20 @@ const UI = { selectbox.options.add(optn); }, + // Handle tab/window close events + // These fire when the user closes the tab, which doesn't call disconnect() + handleBeforeUnload(event) { + // Release modifier keys before tab closes + // This is critical for VMware VMs using websocket reverse proxy + UI._releaseAllModifierKeys(); + }, + + handlePageHide(event) { + // Also handle pagehide as a fallback (fires in more browsers) + // Release modifier keys before page is hidden + UI._releaseAllModifierKeys(); + }, + /* ------^------- * /MISC * ============== From 6a324da27a6005959932d2ddf108ed76f6878aae Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Tue, 13 Jan 2026 18:26:39 +0530 Subject: [PATCH 3/4] MAC address assignment improvements (#12349) --- .../java/com/cloud/network/NetworkModel.java | 8 ++++ .../java/com/cloud/network/addr/PublicIp.java | 8 ++-- .../orchestration/NetworkOrchestrator.java | 2 +- .../NetworkOrchestratorTest.java | 1 + .../com/cloud/network/dao/NetworkDaoImpl.java | 4 +- .../main/java/com/cloud/vm/dao/NicDao.java | 2 +- .../java/com/cloud/vm/dao/NicDaoImpl.java | 3 +- .../cloud/network/IpAddressManagerImpl.java | 4 +- .../cloud/network/Ipv6AddressManagerImpl.java | 2 +- .../com/cloud/network/NetworkModelImpl.java | 40 +++++++++++++++---- .../cloud/network/guru/DirectNetworkGuru.java | 2 +- .../network/guru/PodBasedNetworkGuru.java | 5 ++- .../network/guru/PrivateNetworkGuru.java | 6 ++- .../network/guru/StorageNetworkGuru.java | 6 ++- .../network/router/NicProfileHelper.java | 3 +- .../network/router/NicProfileHelperImpl.java | 11 ++--- .../cloud/network/Ipv6AddressManagerTest.java | 2 + .../cloud/network/MockNetworkModelImpl.java | 18 +++++++++ .../com/cloud/vpc/MockNetworkModelImpl.java | 18 +++++++++ .../java/com/cloud/utils/net/NetUtils.java | 6 +-- 20 files changed, 119 insertions(+), 32 deletions(-) diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java index a4cd87af008..309595d746f 100644 --- a/api/src/main/java/com/cloud/network/NetworkModel.java +++ b/api/src/main/java/com/cloud/network/NetworkModel.java @@ -125,6 +125,10 @@ public interface NetworkModel { */ String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException; + String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException; + + boolean isMACUnique(String mac, long networkId); + PublicIpAddress getPublicIpAddress(long ipAddressId); List listPodVlans(long podId); @@ -362,4 +366,8 @@ public interface NetworkModel { boolean checkSecurityGroupSupportForNetwork(Account account, DataCenter zone, List networkIds, List securityGroupsIds); + + default long getMacIdentifier(Long dataCenterId) { + return 0; + } } diff --git a/engine/components-api/src/main/java/com/cloud/network/addr/PublicIp.java b/engine/components-api/src/main/java/com/cloud/network/addr/PublicIp.java index d69a72a02c5..2f9cd45d632 100644 --- a/engine/components-api/src/main/java/com/cloud/network/addr/PublicIp.java +++ b/engine/components-api/src/main/java/com/cloud/network/addr/PublicIp.java @@ -40,7 +40,11 @@ public class PublicIp implements PublicIpAddress { } public static PublicIp createFromAddrAndVlan(IPAddressVO addr, VlanVO vlan) { - return new PublicIp(addr, vlan, NetUtils.createSequenceBasedMacAddress(addr.getMacAddress(), NetworkModel.MACIdentifier.value())); + long macIdentifier = NetworkModel.MACIdentifier.valueIn(addr.getDataCenterId()); + if (macIdentifier == 0) { + macIdentifier = addr.getDataCenterId(); + } + return new PublicIp(addr, vlan, NetUtils.createSequenceBasedMacAddress(addr.getMacAddress(), macIdentifier)); } @Override @@ -274,6 +278,4 @@ public class PublicIp implements PublicIpAddress { public boolean isForSystemVms() { return false; } - - } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 8a97735bab5..d19a4f1d4a0 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -1270,7 +1270,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra nicProfile.setIPv4Gateway(ipv4Gateway); nicProfile.setIPv4Netmask(ipv4Netmask); - if (nicProfile.getMacAddress() == null) { + if (nicProfile.getMacAddress() == null || !_networkModel.isMACUnique(nicProfile.getMacAddress(), network.getId())) { try { String macAddress = _networkModel.getNextAvailableMacAddressInNetwork(network.getId()); nicProfile.setMacAddress(macAddress); diff --git a/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java b/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java index a95f0e36475..e3989737112 100644 --- a/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java +++ b/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java @@ -396,6 +396,7 @@ public class NetworkOrchestratorTest extends TestCase { when(testOrchestrator._ipAddressDao.acquireInLockTable(Mockito.anyLong())).thenReturn(ipVoSpy); when(testOrchestrator._ipAddressDao.update(Mockito.anyLong(), Mockito.any(IPAddressVO.class))).thenReturn(true); when(testOrchestrator._ipAddressDao.releaseFromLockTable(Mockito.anyLong())).thenReturn(true); + when(testOrchestrator._networkModel.isMACUnique(Mockito.anyString(), Mockito.anyLong())).thenReturn(true); try { when(testOrchestrator._networkModel.getNextAvailableMacAddressInNetwork(Mockito.anyLong())).thenReturn(macAddress); } catch (InsufficientAddressCapacityException e) { diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java index 0aae532eac5..058ffa0030d 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java @@ -432,8 +432,8 @@ public class NetworkDaoImpl extends GenericDaoBaseimplements Ne public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) { final SequenceFetcher fetch = SequenceFetcher.getInstance(); long seq = fetch.getNextSequence(Long.class, _tgMacAddress, networkConfigId); - if(zoneMacIdentifier != null && zoneMacIdentifier.intValue() != 0 ){ - seq = seq | _prefix << 40 | (long)zoneMacIdentifier << 32 | networkConfigId << 16 & 0x00000000ffff0000l; + if (zoneMacIdentifier != null && zoneMacIdentifier != 0) { + seq = seq | _prefix << 40 | (long)zoneMacIdentifier << 32 | networkConfigId << 16 & 0x00000000ffff0000L; } return NetUtils.long2Mac(seq); } diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java index d34b03c4cb0..d2798eae8f7 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java @@ -91,7 +91,7 @@ public interface NicDao extends GenericDao { List listByVmIdAndKeyword(long instanceId, String keyword); - NicVO findByMacAddress(String macAddress); + NicVO findByMacAddress(String macAddress, long networkId); NicVO findByNetworkIdAndMacAddressIncludingRemoved(long networkId, String mac); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java index 7d1af1982ae..ee8f4293e06 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java @@ -400,9 +400,10 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { } @Override - public NicVO findByMacAddress(String macAddress) { + public NicVO findByMacAddress(String macAddress, long networkId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("macAddress", macAddress); + sc.setParameters("network", networkId); return findOneBy(sc); } diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java index 1c8bf7ae03f..fe555af9d50 100644 --- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java @@ -2321,7 +2321,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag())); nic.setFormat(AddressFormat.Ip4); nic.setReservationId(String.valueOf(ip.getVlanTag())); - if(nic.getMacAddress() == null) { + if (nic.getMacAddress() == null) { nic.setMacAddress(ip.getMacAddress()); } } @@ -2372,7 +2372,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage nic.setBroadcastUri(network.getBroadcastUri()); nic.setFormat(AddressFormat.Ip4); - if(nic.getMacAddress() == null) { + if (nic.getMacAddress() == null || !_networkModel.isMACUnique(nic.getMacAddress(), network.getId())) { nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId())); } } diff --git a/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java b/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java index d4c293ecf88..d096b09ec0d 100644 --- a/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java @@ -241,7 +241,7 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa if (nic.getBroadCastUri() == null) { nic.setBroadcastUri(network.getBroadcastUri()); } - if (nic.getMacAddress() == null) { + if (nic.getMacAddress() == null || !_networkModel.isMACUnique(nic.getMacAddress(), network.getId())) { nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId())); } } diff --git a/server/src/main/java/com/cloud/network/NetworkModelImpl.java b/server/src/main/java/com/cloud/network/NetworkModelImpl.java index 26464273490..4a5b7199430 100644 --- a/server/src/main/java/com/cloud/network/NetworkModelImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkModelImpl.java @@ -593,22 +593,34 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi @Override public String getNextAvailableMacAddressInNetwork(long networkId) throws InsufficientAddressCapacityException { NetworkVO network = _networksDao.findById(networkId); - Integer zoneIdentifier = MACIdentifier.value(); - if (zoneIdentifier.intValue() == 0) { - zoneIdentifier = Long.valueOf(network.getDataCenterId()).intValue(); + if (network == null) { + throw new CloudRuntimeException("Could not find network with id " + networkId); } + + Integer zoneMacIdentifier = Long.valueOf(getMacIdentifier(network.getDataCenterId())).intValue(); String mac; do { - mac = _networksDao.getNextAvailableMacAddress(networkId, zoneIdentifier); + mac = _networksDao.getNextAvailableMacAddress(networkId, zoneMacIdentifier); if (mac == null) { throw new InsufficientAddressCapacityException("Unable to create another mac address", Network.class, networkId); } - } while(! isMACUnique(mac)); + } while (!isMACUnique(mac, networkId)); return mac; } - private boolean isMACUnique(String mac) { - return (_nicDao.findByMacAddress(mac) == null); + @Override + public String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException { + String macAddressStr = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(macAddress, getMacIdentifier(datacenterId))); + if (!isMACUnique(macAddressStr, networkId)) { + macAddressStr = getNextAvailableMacAddressInNetwork(networkId); + } + return macAddressStr; + } + + @Override + public boolean isMACUnique(String mac, long networkId) { + return (_nicDao.findByMacAddress(mac, networkId) == null); + } @Override @@ -2815,4 +2827,18 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi } return false; } + + @Override + public long getMacIdentifier(Long dataCenterId) { + long macAddress = 0; + if (dataCenterId == null) { + macAddress = NetworkModel.MACIdentifier.value(); + } else { + macAddress = NetworkModel.MACIdentifier.valueIn(dataCenterId); + if (macAddress == 0) { + macAddress = dataCenterId; + } + } + return macAddress; + } } diff --git a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java index 0cb698e9682..5c0c4eed7fc 100644 --- a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java +++ b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java @@ -293,7 +293,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { allocateDirectIp(nic, network, vm, dc, nic.getRequestedIPv4(), nic.getRequestedIPv6()); nic.setReservationStrategy(ReservationStrategy.Create); - if (nic.getMacAddress() == null) { + if (nic.getMacAddress() == null || !_networkModel.isMACUnique(nic.getMacAddress(), network.getId())) { nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId())); if (nic.getMacAddress() == null) { throw new InsufficientAddressCapacityException("Unable to allocate more mac addresses", Network.class, network.getId()); diff --git a/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java index 5dafa60f1c7..15faec46589 100644 --- a/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java +++ b/server/src/main/java/com/cloud/network/guru/PodBasedNetworkGuru.java @@ -53,6 +53,8 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { DataCenterDao _dcDao; @Inject StorageNetworkManager _sNwMgr; + @Inject + NetworkModel _networkModel; Random _rand = new Random(System.currentTimeMillis()); @@ -131,7 +133,8 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { Integer vlan = result.getVlan(); nic.setIPv4Address(result.getIpAddress()); - nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(result.getMacAddress(), NetworkModel.MACIdentifier.value()))); + String macAddress = _networkModel.getUniqueMacAddress(result.getMacAddress(), config.getId(), dest.getDataCenter().getId()); + nic.setMacAddress(macAddress); nic.setIPv4Gateway(pod.getGateway()); nic.setFormat(AddressFormat.Ip4); String netmask = NetUtils.getCidrNetmask(pod.getCidrSize()); diff --git a/server/src/main/java/com/cloud/network/guru/PrivateNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/PrivateNetworkGuru.java index 9fa8e2f26de..4c22dc16f82 100644 --- a/server/src/main/java/com/cloud/network/guru/PrivateNetworkGuru.java +++ b/server/src/main/java/com/cloud/network/guru/PrivateNetworkGuru.java @@ -189,8 +189,12 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { PrivateIpVO ipVO = _privateIpDao.allocateIpAddress(network.getDataCenterId(), network.getId(), null); String vlanTag = BroadcastDomainType.getValue(network.getBroadcastUri()); String netmask = NetUtils.getCidrNetmask(network.getCidr()); + String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), networkModel.getMacIdentifier(network.getDataCenterId()))); + if (!networkModel.isMACUnique(macAddress, network.getId())) { + macAddress = networkModel.getNextAvailableMacAddressInNetwork(network.getId()); + } PrivateIpAddress ip = - new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value()))); + new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, macAddress); nic.setIPv4Address(ip.getIpAddress()); nic.setIPv4Gateway(ip.getGateway()); diff --git a/server/src/main/java/com/cloud/network/guru/StorageNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/StorageNetworkGuru.java index 221661fea12..4d2d582c9ff 100644 --- a/server/src/main/java/com/cloud/network/guru/StorageNetworkGuru.java +++ b/server/src/main/java/com/cloud/network/guru/StorageNetworkGuru.java @@ -37,7 +37,6 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.offering.NetworkOffering; import com.cloud.user.Account; -import com.cloud.utils.net.NetUtils; import com.cloud.vm.Nic.ReservationStrategy; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; @@ -47,6 +46,8 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu @Inject StorageNetworkManager _sNwMgr; @Inject + NetworkModel _networkModel; + @Inject NetworkDao _nwDao; protected StorageNetworkGuru() { @@ -130,7 +131,8 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu vlan = ip.getVlan(); nic.setIPv4Address(ip.getIpAddress()); - nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.getMac(), NetworkModel.MACIdentifier.value()))); + String macAddress = _networkModel.getUniqueMacAddress(ip.getMac(), network.getId(), dest.getDataCenter().getId()); + nic.setMacAddress(macAddress); nic.setFormat(AddressFormat.Ip4); nic.setIPv4Netmask(ip.getNetmask()); nic.setBroadcastType(BroadcastDomainType.Storage); diff --git a/server/src/main/java/com/cloud/network/router/NicProfileHelper.java b/server/src/main/java/com/cloud/network/router/NicProfileHelper.java index 832d77f9e40..b1ad2ef950b 100644 --- a/server/src/main/java/com/cloud/network/router/NicProfileHelper.java +++ b/server/src/main/java/com/cloud/network/router/NicProfileHelper.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.router; +import com.cloud.exception.InsufficientAddressCapacityException; import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition; import com.cloud.network.Network; @@ -24,7 +25,7 @@ import com.cloud.vm.NicProfile; public interface NicProfileHelper { - public abstract NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router); + public abstract NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router) throws InsufficientAddressCapacityException; public abstract NicProfile createGuestNicProfileForVpcRouter(final RouterDeploymentDefinition vpcRouterDeploymentDefinition, Network guestNetwork); diff --git a/server/src/main/java/com/cloud/network/router/NicProfileHelperImpl.java b/server/src/main/java/com/cloud/network/router/NicProfileHelperImpl.java index 399019db3e2..b0320dbfab9 100644 --- a/server/src/main/java/com/cloud/network/router/NicProfileHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NicProfileHelperImpl.java @@ -21,6 +21,7 @@ import java.net.URI; import javax.inject.Inject; +import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.vm.NicVO; import com.cloud.vm.VirtualMachine; import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition; @@ -61,7 +62,7 @@ public class NicProfileHelperImpl implements NicProfileHelper { @Override @DB - public NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router) { + public NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router) throws InsufficientAddressCapacityException { final Network privateNetwork = _networkModel.getNetwork(privateGateway.getNetworkId()); PrivateIpVO ipVO = _privateIpDao.allocateIpAddress(privateNetwork.getDataCenterId(), privateNetwork.getId(), privateGateway.getIp4Address()); @@ -90,14 +91,14 @@ public class NicProfileHelperImpl implements NicProfileHelper { privateNicProfile.setDeviceId(null); if (router.getIsRedundantRouter()) { - String newMacAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value())); - privateNicProfile.setMacAddress(newMacAddress); + String newMacAddress = _networkModel.getUniqueMacAddress(ipVO.getMacAddress(), privateNetwork.getId(), privateNetwork.getDataCenterId()); + privateNicProfile.setMacAddress(newMacAddress); } } else { final String netmask = NetUtils.getCidrNetmask(privateNetwork.getCidr()); + String newMacAddress = _networkModel.getUniqueMacAddress(ipVO.getMacAddress(), privateNetwork.getId(), privateNetwork.getDataCenterId()); final PrivateIpAddress ip = - new PrivateIpAddress(ipVO, privateNetwork.getBroadcastUri().toString(), privateNetwork.getGateway(), netmask, - NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value()))); + new PrivateIpAddress(ipVO, privateNetwork.getBroadcastUri().toString(), privateNetwork.getGateway(), netmask, newMacAddress); final URI netUri = BroadcastDomainType.fromString(ip.getBroadcastUri()); privateNicProfile.setIPv4Address(ip.getIpAddress()); diff --git a/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java b/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java index 0b8e7f43137..68a0fa8052d 100644 --- a/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java +++ b/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java @@ -246,8 +246,10 @@ public class Ipv6AddressManagerTest { Mockito.when(network.getIp6Cidr()).thenReturn("2001:db8:100::/64"); Mockito.when(network.getIp6Gateway()).thenReturn("2001:db8:100::1"); + Mockito.when(network.getId()).thenReturn(1L); Mockito.when(networkModel.getNetworkIp6Dns(network, dc)).thenReturn(new Pair<>("2001:db8::53:1", "2001:db8::53:2")); + Mockito.when(networkModel.isMACUnique("1e:00:b1:00:0a:f6", 1L)).thenReturn(true); String expected = "2001:db8:100:0:1c00:b1ff:fe00:af6"; diff --git a/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java b/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java index ea9a0340eaa..88df58da645 100644 --- a/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java +++ b/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java @@ -129,6 +129,24 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { return null; } + /* (non-Javadoc) + * @see com.cloud.network.NetworkModel#getUniqueMacAddress(long, long, long) + */ + @Override + public String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see com.cloud.network.NetworkModel#isMACUnique(String, long) + */ + @Override + public boolean isMACUnique(String mac, long networkId) { + // TODO Auto-generated method stub + return true; + } + /* (non-Javadoc) * @see com.cloud.network.NetworkModel#getPublicIpAddress(long) */ diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java index 3b41a56dc0f..5efcd972022 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java @@ -141,6 +141,24 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { return null; } + /* (non-Javadoc) + * @see com.cloud.network.NetworkModel#getUniqueMacAddress(long, long, long) + */ + @Override + public String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see com.cloud.network.NetworkModel#isMACUnique(String, long) + */ + @Override + public boolean isMACUnique(String mac, long networkId) { + // TODO Auto-generated method stub + return true; + } + /* (non-Javadoc) * @see com.cloud.network.NetworkModel#getPublicIpAddress(long) */ diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java b/utils/src/main/java/com/cloud/utils/net/NetUtils.java index 0b7d2350281..1a0382f249b 100644 --- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java +++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java @@ -131,17 +131,17 @@ public class NetUtils { } } - public static long createSequenceBasedMacAddress(final long macAddress, long globalConfig) { + public static long createSequenceBasedMacAddress(final long macAddress, long macIdentifier) { /* Logic for generating MAC address: Mac = B1:B2:B3:B4:B5:B6 (Bx is a byte). B1 -> Presently controlled by prefix variable. The value should be such that the MAC is local and unicast. - B2 -> This will be configurable for each deployment/installation. Controlled by the global config MACIdentifier + B2 -> This will be configurable for each deployment/installation. Controlled by the 'mac.identifier' zone-level config B3 -> A randomly generated number between 0 - 255 B4,5,6 -> These bytes are based on the unique DB identifier associated with the IP address for which MAC is generated (refer to mac_address field in user_ip_address table). */ - return macAddress | prefix<<40 | globalConfig << 32 & 0x00ff00000000l | (long)s_rand.nextInt(255) << 24; + return macAddress | prefix << 40 | macIdentifier << 32 & 0x00ff00000000L | (long)s_rand.nextInt(255) << 24; } public static String getHostName() { From 5c1f9315ceda5d354e9666c91bffd9a378bbd0fa Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:42:42 +0530 Subject: [PATCH 4/4] Remove transaction from updateCapacityForHost cal (#12421) --- .../src/main/java/com/cloud/alert/AlertManagerImpl.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java index 377b2134d78..7bf00037ee4 100644 --- a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java @@ -294,13 +294,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi Math.min(CapacityManager.CapacityCalculateWorkers.value(), hostIds.size()))); for (Long hostId : hostIds) { futures.put(hostId, executorService.submit(() -> { - Transaction.execute(new TransactionCallbackNoReturn() { - @Override - public void doInTransactionWithoutResult(TransactionStatus status) { - final HostVO host = hostDao.findById(hostId); - _capacityMgr.updateCapacityForHost(host); - } - }); + final HostVO host = hostDao.findById(hostId); + _capacityMgr.updateCapacityForHost(host); return null; })); }