package org.ovirt.engine.core.bll.network.macpool; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.commons.lang.math.LongRange; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.errors.EngineError; import org.ovirt.engine.core.common.errors.EngineException; import org.ovirt.engine.core.common.utils.ToStringBuilder; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase; import org.ovirt.engine.core.utils.MacAddressRangeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class MacPoolUsingRanges implements MacPool { private static final Logger log = LoggerFactory.getLogger(MacPoolUsingRanges.class); private final Guid id; private final boolean allowDuplicates; private MacsStorage macsStorage; private Collection<LongRange> rangesBoundaries; public MacPoolUsingRanges(Guid id, Collection<LongRange> rangesBoundaries, boolean allowDuplicates) { this.id = id; this.allowDuplicates = allowDuplicates; this.rangesBoundaries = rangesBoundaries; initialize(); } private void initialize() { log.info("Initializing {}", this); this.macsStorage = createMacsStorage(rangesBoundaries); log.info("Finished initializing {}. Available MACs in pool: {}", this, macsStorage.getAvailableMacsCount()); } /** * create and initialize internal structures to accommodate all macs specified in {@code rangesString} up to {@code * maxMacsInPool}. * * @return initialized {@link MacsStorage} instance. */ private MacsStorage createMacsStorage(Collection<LongRange> rangesBoundaries) { MacsStorage macsStorage = new MacsStorage(allowDuplicates); for (LongRange range : rangesBoundaries) { log.debug("Adding range {} to pool {}.", range, this); macsStorage.addRange(range.getMinimumLong(), range.getMaximumLong()); } if (macsStorage.availableMacExist()) { return macsStorage; } else { throw new EngineException(EngineError.MAC_POOL_INITIALIZATION_FAILED); } } private void logWhenMacPoolIsEmpty() { if (!macsStorage.availableMacExist()) { AuditLogableBase logable = new AuditLogableBase(); new AuditLogDirector().log(logable, AuditLogType.MAC_POOL_EMPTY); } } @Override public Guid getId() { return id; } @Override public String allocateNewMac() { return allocateMacAddresses(1).get(0); } @Override public int getAvailableMacsCount() { int availableMacsSize = macsStorage.getAvailableMacsCount(); log.debug("Number of available Mac addresses = {}", availableMacsSize); return availableMacsSize; } @Override public void freeMac(String mac) { this.freeMacs(Collections.singletonList(mac)); } @Override public boolean addMac(String mac) { log.debug("Allocating custom mac address {} from {}.", mac, this); boolean added = macsStorage.useMac(MacAddressRangeUtils.macToLong(mac)); logWhenMacPoolIsEmpty(); return added; } @Override public List<String> addMacs(List<String> macs) { List<String> notAddedMacs = new ArrayList<>(macs.size()); for (String mac : macs) { if (!addMac(mac)) { notAddedMacs.add(mac); } } return notAddedMacs; } @Override public void forceAddMac(String mac) { log.debug("Forcibly allocating custom mac address {} from {}", mac, this); macsStorage.useMacNoDuplicityCheck(MacAddressRangeUtils.macToLong(mac)); logWhenMacPoolIsEmpty(); } @Override public void forceAddMacs(List<String> macs) { for (String mac : macs) { forceAddMac(mac); } } @Override public boolean isMacInUse(String mac) { boolean result = macsStorage.isMacInUse(MacAddressRangeUtils.macToLong(mac)); log.debug("Mac {} isMacInUse={}", mac, result); return result; } @Override public void freeMacs(List<String> macs) { log.debug("Releasing mac addresses {} back to {}", macs, this); for (String mac : macs) { macsStorage.freeMac(MacAddressRangeUtils.macToLong(mac)); } } @Override public List<String> allocateMacAddresses(int numberOfAddresses) { log.debug("Allocating {} mac addresses from {}.", numberOfAddresses, this); List<Long> macs = macsStorage.allocateAvailableMacs(numberOfAddresses); List<String> result = MacAddressRangeUtils.macAddressesToStrings(macs); log.debug("Allocated mac addresses: {} from {}.", result, this); Collections.sort(result); logWhenMacPoolIsEmpty(); return result; } @Override public boolean isMacInRange(String mac) { boolean result = macsStorage.isMacInRange(MacAddressRangeUtils.macToLong(mac)); log.debug("Mac {} isMacInRange={}", mac, result); return result; } @Override public boolean isDuplicateMacAddressesAllowed() { return this.allowDuplicates; } @Override public String toString() { return ToStringBuilder.forInstance(this) .append("id", id) .build(); } }