Muli Salem has uploaded a new change for review. Change subject: engine: Support Duplicate Mac Addresses ......................................................................
engine: Support Duplicate Mac Addresses This patch adds support to duplicate Mac addresses. It separates the logic in MacPoolManager into two possible polices, duplicate and non-duplicate. Upon engine start, the config value is taken and the MacPoolManager is initialized accordingly. Change-Id: Ie96eda19de2d3a44e24806095fb690e4eba41165 Signed-off-by: Muli Salem <msa...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManager.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicy.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyDuplicate.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyNonDuplicate.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/UpdateVmInterfaceCommand.java 6 files changed, 197 insertions(+), 50 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/98/10698/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManager.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManager.java index 40afe72..03d711e 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManager.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManager.java @@ -1,6 +1,5 @@ package org.ovirt.engine.core.bll.network; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -27,9 +26,7 @@ private static Log log = LogFactory.getLog(MacPoolManager.class); - private final Set<String> availableMacs = new HashSet<String>(); - private final Set<String> allocatedMacs = new HashSet<String>(); - private final Set<String> allocatedCustomMacs = new HashSet<String>(); + private MacPoolManagerPolicy policy; private final ReentrantReadWriteLock lockObj = new ReentrantReadWriteLock(); private boolean initialized; @@ -42,6 +39,11 @@ } public void initialize() { + if (Config.<Boolean> GetValue(ConfigValues.AllowDuplicateMacAddresses)) { + policy = new MacPoolManagerPolicyDuplicate(); + } else { + policy = new MacPoolManagerPolicyNonDuplicate(); + } lockObj.writeLock().lock(); try { String ranges = Config.<String> GetValue(ConfigValues.MacPoolRanges); @@ -79,9 +81,13 @@ } } - if (availableMacs.isEmpty()) { + if (getAvailableMacs().isEmpty()) { throw new VdcBLLException(VdcBllErrors.MAC_POOL_INITIALIZATION_FAILED); } + } + + private Set<String> getAvailableMacs() { + return policy.getAvailableMacs(); } private String parseRangePart(String start) { @@ -123,10 +129,10 @@ } value = builder.toString(); value = value.substring(0, value.length() - 1); - if (!availableMacs.contains(value)) { - availableMacs.add(value); + if (!getAvailableMacs().contains(value)) { + getAvailableMacs().add(value); } - if (availableMacs.size() > Config.<Integer> GetValue(ConfigValues.MaxMacsCountInPool)) { + if (getAvailableMacs().size() > Config.<Integer> GetValue(ConfigValues.MaxMacsCountInPool)) { throw new MacPoolExceededMaxException(); } } @@ -142,10 +148,10 @@ logInitializationError("Failed to allocate new Mac address."); throw new VdcBLLException(VdcBllErrors.MAC_POOL_NOT_INITIALIZED); } - if (availableMacs.isEmpty()) { + if (getAvailableMacs().isEmpty()) { throw new VdcBLLException(VdcBllErrors.MAC_POOL_NO_MACS_LEFT); } - Iterator<String> my = availableMacs.iterator(); + Iterator<String> my = getAvailableMacs().iterator(); mac = my.next(); commitNewMac(mac); } finally { @@ -156,9 +162,8 @@ } private boolean commitNewMac(String mac) { - availableMacs.remove(mac); - allocatedMacs.add(mac); - if (availableMacs.isEmpty()) { + policy.commitNewMac(mac); + if (getAvailableMacs().isEmpty()) { AuditLogableBase logable = new AuditLogableBase(); AuditLogDirector.log(logable, AuditLogType.MAC_POOL_EMPTY); return false; @@ -167,7 +172,7 @@ } public int getavailableMacsCount() { - return availableMacs.size(); + return getAvailableMacs().size(); } public void freeMac(String mac) { @@ -177,7 +182,7 @@ if (!initialized) { logInitializationError("Failed to free mac address " + mac + " ."); } else { - internalFreeMac(mac); + policy.freeMac(mac); } } finally { lockObj.writeLock().unlock(); @@ -191,15 +196,6 @@ AuditLogDirector.log(logable, AuditLogType.MAC_ADDRESSES_POOL_NOT_INITIALIZED); } - private void internalFreeMac(String mac) { - if (allocatedCustomMacs.contains(mac)) { - allocatedCustomMacs.remove(mac); - } else if (allocatedMacs.contains(mac)) { - allocatedMacs.remove(mac); - availableMacs.add(mac); - } - } - /** * Add user define mac address Function return false if the mac is in use * @@ -210,17 +206,7 @@ boolean retVal = true; lockObj.writeLock().lock(); try { - if (allocatedMacs.contains(mac)) { - retVal = false; - } else { - if (availableMacs.contains(mac)) { - retVal = commitNewMac(mac); - } else if (allocatedCustomMacs.contains(mac)) { - retVal = false; - } else { - allocatedCustomMacs.add(mac); - } - } + retVal = policy.addMac(mac); } finally { lockObj.writeLock().unlock(); } @@ -230,7 +216,7 @@ public boolean isMacInUse(String mac) { lockObj.readLock().lock(); try { - return allocatedMacs.contains(mac) || allocatedCustomMacs.contains(mac); + return policy.isMacInUse(mac); } finally { lockObj.readLock().unlock(); } @@ -244,7 +230,7 @@ logInitializationError("Failed to free MAC addresses."); } for (String mac : macs) { - internalFreeMac(mac); + policy.freeMac(mac); } } finally { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicy.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicy.java new file mode 100644 index 0000000..70c37b7 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicy.java @@ -0,0 +1,39 @@ +package org.ovirt.engine.core.bll.network; + +import java.util.Set; + +public interface MacPoolManagerPolicy { + + /** + * Commits a Mac address and removes it from the available Mac addresses list + * + * @param mac + */ + void commitNewMac(String mac); + + /** + * Frees the given Mac address + */ + void freeMac(String mac); + + /** + * Adds a Mac address. + * + * @param mac + * @return + */ + public boolean addMac(String mac); + + /** + * Checks whether the given Mac address is in use. + * + * @param mac + * @return + */ + public boolean isMacInUse(String mac); + + /** + * Returns the set of available Mac addresses + */ + public Set<String> getAvailableMacs(); +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyDuplicate.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyDuplicate.java new file mode 100644 index 0000000..cff4baa --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyDuplicate.java @@ -0,0 +1,78 @@ +package org.ovirt.engine.core.bll.network; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class MacPoolManagerPolicyDuplicate implements MacPoolManagerPolicy { + + private final Set<String> availableMacs = new HashSet<String>(); + + // Maps that hold the allocated Mac addresses as keys, and counters as values + private final Map<String, Integer> allocatedMacs = new HashMap<String, Integer>(); + private final Map<String, Integer> allocatedCustomMacs = new HashMap<String, Integer>(); + + @Override + public void commitNewMac(String mac) { + availableMacs.remove(mac); + addMacToMap(allocatedMacs, mac); + } + + @Override + public void freeMac(String mac) { + if (allocatedMacs.get(mac) != null) { + if (allocatedMacs.get(mac) == 1) { + allocatedMacs.remove(mac); + availableMacs.add(mac); + } else if (allocatedMacs.get(mac) > 1) { + decrementMacInMap(allocatedMacs, mac); + } + } else if (allocatedCustomMacs.get(mac) != null) { + if (allocatedCustomMacs.get(mac) == 1) { + allocatedCustomMacs.remove(mac); + } else if (allocatedCustomMacs.get(mac) > 1) { + decrementMacInMap(allocatedCustomMacs, mac); + } + } + } + + @Override + public boolean addMac(String mac) { + if (availableMacs.contains(mac)) { + commitNewMac(mac); + } else if (allocatedMacs.containsKey(mac)) { + addMacToMap(allocatedMacs, mac); + } else { + addMacToMap(allocatedCustomMacs, mac); + } + return true; + } + + @Override + public boolean isMacInUse(String mac) { + return allocatedMacs.containsKey(mac) || allocatedCustomMacs.containsKey(mac); + } + + @Override + public Set<String> getAvailableMacs() { + return availableMacs; + } + + private void incrementMacInMap(Map<String, Integer> macMap, String mac) { + macMap.put(mac, macMap.get(mac) + 1); + } + + private void decrementMacInMap(Map<String, Integer> macMap, String mac) { + macMap.put(mac, macMap.get(mac) - 1); + } + + private void addMacToMap(Map<String, Integer> macMap, String mac) { + if (macMap.containsKey(mac)) { + incrementMacInMap(macMap, mac); + } else { + macMap.put(mac, 1); // First time this mac is used + } + } + +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyNonDuplicate.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyNonDuplicate.java new file mode 100644 index 0000000..0747c68 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/MacPoolManagerPolicyNonDuplicate.java @@ -0,0 +1,54 @@ +package org.ovirt.engine.core.bll.network; + +import java.util.HashSet; +import java.util.Set; + +public class MacPoolManagerPolicyNonDuplicate implements MacPoolManagerPolicy { + + private final Set<String> availableMacs = new HashSet<String>(); + private final Set<String> allocatedMacs = new HashSet<String>(); + private final Set<String> allocatedCustomMacs = new HashSet<String>(); + + @Override + public void commitNewMac(String mac) { + availableMacs.remove(mac); + allocatedMacs.add(mac); + } + + @Override + public void freeMac(String mac) { + if (allocatedCustomMacs.contains(mac)) { + allocatedCustomMacs.remove(mac); + } else if (allocatedMacs.contains(mac)) { + allocatedMacs.remove(mac); + availableMacs.add(mac); + } + } + + @Override + public boolean addMac(String mac) { + if (allocatedMacs.contains(mac)) { + return false; + } else { + if (availableMacs.contains(mac)) { + commitNewMac(mac); + return true; + } else if (allocatedCustomMacs.contains(mac)) { + return false; + } else { + allocatedCustomMacs.add(mac); + return true; + } + } + } + + @Override + public boolean isMacInUse(String mac) { + return allocatedMacs.contains(mac) || allocatedCustomMacs.contains(mac); + } + + @Override + public Set<String> getAvailableMacs() { + return availableMacs; + } +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java index 170ba10..c464fe9 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java @@ -23,8 +23,6 @@ import org.ovirt.engine.core.common.businessentities.network.Network; import org.ovirt.engine.core.common.businessentities.network.VmInterfaceType; import org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface; -import org.ovirt.engine.core.common.config.Config; -import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.utils.ValidationUtils; import org.ovirt.engine.core.common.validation.group.CreateEntity; import org.ovirt.engine.core.compat.Guid; @@ -182,10 +180,8 @@ return false; } - Boolean allowDupMacs = Config.<Boolean> GetValue(ConfigValues.AllowDuplicateMacAddresses); // this must be the last check because it adds the mac address to the pool - if (!MacPoolManager.getInstance().addMac(getMacAddress()) - && !allowDupMacs) { + if (!MacPoolManager.getInstance().addMac(getMacAddress())) { addCanDoActionMessage(VdcBllMessages.NETWORK_MAC_ADDRESS_IN_USE); return false; } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/UpdateVmInterfaceCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/UpdateVmInterfaceCommand.java index c6b9f69..d61f2a5 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/UpdateVmInterfaceCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/UpdateVmInterfaceCommand.java @@ -24,8 +24,6 @@ import org.ovirt.engine.core.common.businessentities.network.Network; import org.ovirt.engine.core.common.businessentities.network.VmInterfaceType; import org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface; -import org.ovirt.engine.core.common.config.Config; -import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.utils.ValidationUtils; import org.ovirt.engine.core.common.validation.group.UpdateVmNic; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; @@ -157,9 +155,7 @@ super.rollback(); if (macAddressChanged) { MacPoolManager.getInstance().addMac(oldIface.getMacAddress()); - if (!Config.<Boolean> GetValue(ConfigValues.AllowDuplicateMacAddresses)) { - MacPoolManager.getInstance().freeMac(getMacAddress()); - } + MacPoolManager.getInstance().freeMac(getMacAddress()); } } @@ -244,10 +240,8 @@ return false; } - Boolean allowDupMacs = Config.<Boolean> GetValue(ConfigValues.AllowDuplicateMacAddresses); // this must be the last check because it adds the mac address to the pool - if (!MacPoolManager.getInstance().addMac(getMacAddress()) - && !allowDupMacs) { + if (!MacPoolManager.getInstance().addMac(getMacAddress())) { addCanDoActionMessage(VdcBllMessages.NETWORK_MAC_ADDRESS_IN_USE); return false; } -- To view, visit http://gerrit.ovirt.org/10698 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie96eda19de2d3a44e24806095fb690e4eba41165 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Muli Salem <msa...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches