mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Merge pull request #1883 from Accelerite/uniqueMac
CLOUDSTACK-9723: Enable unique mac address across the zones
This commit is contained in:
commit
339fe4c7bd
@ -38,6 +38,7 @@ import com.cloud.user.Account;
|
||||
import com.cloud.vm.Nic;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
/**
|
||||
* The NetworkModel presents a read-only view into the Network data such as L2 networks,
|
||||
@ -47,6 +48,9 @@ import com.cloud.vm.VirtualMachine;
|
||||
*/
|
||||
public interface NetworkModel {
|
||||
|
||||
static final ConfigKey<Integer> MACIdentifier = new ConfigKey<Integer>("Advanced",Integer.class, "mac.identifier", "0",
|
||||
"This value will be used while generating the mac addresses for isolated and shared networks. The hexadecimal equivalent value will be present at the 2nd octet of the mac address. Default value is null which means this feature is disabled.Its scope is global.", true, ConfigKey.Scope.Global);
|
||||
|
||||
/**
|
||||
* Lists IP addresses that belong to VirtualNetwork VLANs
|
||||
*
|
||||
|
||||
@ -20,7 +20,6 @@ import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
|
||||
/**
|
||||
* A VirtualMachineGuru knows how to process a certain type of virtual machine.
|
||||
*
|
||||
|
||||
@ -20,6 +20,7 @@ import java.util.Date;
|
||||
|
||||
import com.cloud.dc.VlanVO;
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.PublicIpAddress;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.utils.net.Ip;
|
||||
@ -39,7 +40,7 @@ public class PublicIp implements PublicIpAddress {
|
||||
}
|
||||
|
||||
public static PublicIp createFromAddrAndVlan(IPAddressVO addr, VlanVO vlan) {
|
||||
return new PublicIp(addr, vlan, NetUtils.createSequenceBasedMacAddress(addr.getMacAddress()));
|
||||
return new PublicIp(addr, vlan, NetUtils.createSequenceBasedMacAddress(addr.getMacAddress(), NetworkModel.MACIdentifier.value()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -249,7 +250,9 @@ public class PublicIp implements PublicIpAddress {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
public Class<?> getEntityType()
|
||||
{
|
||||
return IpAddress.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -54,9 +54,10 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long>, StateDao<State,
|
||||
*
|
||||
* @param networkConfigId
|
||||
* id
|
||||
* @param zoneMacIdentifier
|
||||
* @return mac address if there is one. null if not.
|
||||
*/
|
||||
String getNextAvailableMacAddress(long networkConfigId);
|
||||
String getNextAvailableMacAddress(long networkConfigId, Integer zoneMacIdentifier);
|
||||
|
||||
List<NetworkVO> listBy(long accountId, long networkId);
|
||||
|
||||
|
||||
@ -377,11 +377,15 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNextAvailableMacAddress(final long networkConfigId) {
|
||||
public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) {
|
||||
final SequenceFetcher fetch = SequenceFetcher.getInstance();
|
||||
|
||||
long seq = fetch.getNextSequence(Long.class, _tgMacAddress, networkConfigId);
|
||||
seq = seq | _prefix << 40 | _rand.nextInt(Short.MAX_VALUE) << 16 & 0x00000000ffff0000l;
|
||||
if(zoneMacIdentifier != null && zoneMacIdentifier.intValue() != 0 ){
|
||||
seq = seq | _prefix << 40 | (long)zoneMacIdentifier << 32 | networkConfigId << 16 & 0x00000000ffff0000l;
|
||||
}
|
||||
else {
|
||||
seq = seq | _prefix << 40 | _rand.nextInt(Short.MAX_VALUE) << 16 & 0x00000000ffff0000l;
|
||||
}
|
||||
return NetUtils.long2Mac(seq);
|
||||
}
|
||||
|
||||
|
||||
@ -742,7 +742,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
} else {
|
||||
type = c.getType();
|
||||
}
|
||||
|
||||
//no need to validate further if a
|
||||
//config can have null value.
|
||||
String errMsg = null;
|
||||
try {
|
||||
if (type.equals(Integer.class)) {
|
||||
@ -791,6 +792,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type.equals(Integer.class) && NetworkModel.MACIdentifier.key().equalsIgnoreCase(name)) {
|
||||
try {
|
||||
final int val = Integer.parseInt(value);
|
||||
//The value need to be between 0 to 255 because the mac generation needs a value of 8 bit
|
||||
//0 value is considered as disable.
|
||||
if(val < 0 || val > 255){
|
||||
throw new InvalidParameterValueException(name+" value should be between 0 and 255. 0 value will disable this feature");
|
||||
}
|
||||
} catch (final NumberFormatException e) {
|
||||
s_logger.error("There was an error trying to parse the integer value for:" + name);
|
||||
throw new InvalidParameterValueException("There was an error trying to parse the integer value for:" + name);
|
||||
}
|
||||
}
|
||||
|
||||
if (type.equals(Integer.class) && configValuesForValidation.contains(name)) {
|
||||
try {
|
||||
final int val = Integer.parseInt(value);
|
||||
|
||||
@ -22,6 +22,7 @@ import com.cloud.user.Account;
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
public interface Ipv6AddressManager extends Manager {
|
||||
|
||||
public UserIpv6Address assignDirectIp6Address(long dcId, Account owner, Long networkId, String requestedIp6) throws InsufficientAddressCapacityException;
|
||||
|
||||
public void revokeDirectIpv6Address(long networkId, String ip6Address);
|
||||
|
||||
@ -132,7 +132,7 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa
|
||||
dc.setMacAddress(nextMac);
|
||||
_dcDao.update(dc.getId(), dc);
|
||||
|
||||
String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(mac));
|
||||
String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(mac,NetworkModel.MACIdentifier.value()));
|
||||
UserIpv6AddressVO ipVO = new UserIpv6AddressVO(ip, dcId, macAddress, ipVlan.getId());
|
||||
ipVO.setPhysicalNetworkId(network.getPhysicalNetworkId());
|
||||
ipVO.setSourceNetworkId(networkId);
|
||||
|
||||
@ -34,6 +34,8 @@ import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
@ -124,7 +126,7 @@ import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.NicSecondaryIpDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
public class NetworkModelImpl extends ManagerBase implements NetworkModel {
|
||||
public class NetworkModelImpl extends ManagerBase implements NetworkModel, Configurable {
|
||||
static final Logger s_logger = Logger.getLogger(NetworkModelImpl.class);
|
||||
@Inject
|
||||
EntityManager _entityMgr;
|
||||
@ -561,7 +563,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
|
||||
|
||||
@Override
|
||||
public String getNextAvailableMacAddressInNetwork(long networkId) throws InsufficientAddressCapacityException {
|
||||
String mac = _networksDao.getNextAvailableMacAddress(networkId);
|
||||
NetworkVO network = _networksDao.findById(networkId);
|
||||
String mac = _networksDao.getNextAvailableMacAddress(networkId, MACIdentifier.value());
|
||||
if (mac == null) {
|
||||
throw new InsufficientAddressCapacityException("Unable to create another mac address", Network.class, networkId);
|
||||
}
|
||||
@ -2364,4 +2367,14 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
|
||||
|
||||
return vmData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return NetworkModel.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {MACIdentifier};
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import java.util.Random;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.NetworkModel;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.dc.Pod;
|
||||
@ -53,6 +54,7 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru {
|
||||
DataCenterDao _dcDao;
|
||||
@Inject
|
||||
StorageNetworkManager _sNwMgr;
|
||||
|
||||
Random _rand = new Random(System.currentTimeMillis());
|
||||
|
||||
private static final TrafficType[] TrafficTypes = {TrafficType.Management};
|
||||
@ -123,7 +125,7 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru {
|
||||
}
|
||||
|
||||
nic.setIPv4Address(ip.first());
|
||||
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.second())));
|
||||
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.second(), NetworkModel.MACIdentifier.value())));
|
||||
nic.setIPv4Gateway(pod.getGateway());
|
||||
nic.setFormat(AddressFormat.Ip4);
|
||||
String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
|
||||
|
||||
@ -186,7 +186,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
|
||||
String vlanTag = BroadcastDomainType.getValue(network.getBroadcastUri());
|
||||
String netmask = NetUtils.getCidrNetmask(network.getCidr());
|
||||
PrivateIpAddress ip =
|
||||
new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress())));
|
||||
new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value())));
|
||||
|
||||
nic.setIPv4Address(ip.getIpAddress());
|
||||
nic.setIPv4Gateway(ip.getGateway());
|
||||
|
||||
@ -18,6 +18,7 @@ package com.cloud.network.guru;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.NetworkModel;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.dc.Pod;
|
||||
@ -131,7 +132,7 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu
|
||||
|
||||
vlan = ip.getVlan();
|
||||
nic.setIPv4Address(ip.getIpAddress());
|
||||
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.getMac())));
|
||||
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.getMac(), NetworkModel.MACIdentifier.value())));
|
||||
nic.setFormat(AddressFormat.Ip4);
|
||||
nic.setIPv4Netmask(ip.getNetmask());
|
||||
nic.setBroadcastType(BroadcastDomainType.Storage);
|
||||
|
||||
@ -87,14 +87,14 @@ public class NicProfileHelperImpl implements NicProfileHelper {
|
||||
router.getHypervisorType(), privateNetwork));
|
||||
|
||||
if (router.getIsRedundantRouter()) {
|
||||
String newMacAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress()));
|
||||
String newMacAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value()));
|
||||
privateNicProfile.setMacAddress(newMacAddress);
|
||||
}
|
||||
} else {
|
||||
final String netmask = NetUtils.getCidrNetmask(privateNetwork.getCidr());
|
||||
final PrivateIpAddress ip =
|
||||
new PrivateIpAddress(ipVO, privateNetwork.getBroadcastUri().toString(), privateNetwork.getGateway(), netmask,
|
||||
NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress())));
|
||||
NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value())));
|
||||
|
||||
final URI netUri = BroadcastDomainType.fromString(ip.getBroadcastUri());
|
||||
privateNicProfile.setIPv4Address(ip.getIpAddress());
|
||||
|
||||
@ -106,7 +106,7 @@ public class MockNetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implemen
|
||||
* @see com.cloud.network.dao.NetworkDao#getNextAvailableMacAddress(long)
|
||||
*/
|
||||
@Override
|
||||
public String getNextAvailableMacAddress(final long networkConfigId) {
|
||||
public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -83,9 +83,19 @@ public class NetUtils {
|
||||
public final static int DEFAULT_AUTOSCALE_POLICY_INTERVAL_TIME = 30;
|
||||
public final static int DEFAULT_AUTOSCALE_POLICY_QUIET_TIME = 5 * 60;
|
||||
private final static Random s_rand = new Random(System.currentTimeMillis());
|
||||
private final static long prefix = 0x1e;
|
||||
|
||||
public static long createSequenceBasedMacAddress(final long macAddress) {
|
||||
return macAddress | 0x060000000000l | (long)s_rand.nextInt(32768) << 25 & 0x00fffe000000l;
|
||||
public static long createSequenceBasedMacAddress(final long macAddress, long globalConfig) {
|
||||
/*
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
public static String getHostName() {
|
||||
|
||||
@ -560,6 +560,19 @@ public class NetUtilsTest {
|
||||
NetUtils.EUI64Address("2001:980:7936::/64", "c0:3f:d5:68:28:08"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testcreateSequenceBasedMacAddress(){
|
||||
long mac1 = NetUtils.createSequenceBasedMacAddress(10l,10l);
|
||||
assertEquals(10l,(mac1 & (0x0al<<32)) >> 32);
|
||||
assertEquals(10l,mac1 & 0x0al);
|
||||
assertEquals(30l, mac1>>40);
|
||||
|
||||
long mac2 = NetUtils.createSequenceBasedMacAddress(20l,15l);
|
||||
assertEquals(15l, (mac2 & (0x0fl << 32)) >> 32);
|
||||
assertEquals(20l, mac2 & 0x14l);
|
||||
assertEquals(30l, mac1>>40);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv6LinkLocal() {
|
||||
assertEquals(IPv6Address.fromString("fe80::fc54:ff:fe00:3e05"), NetUtils.ipv6LinkLocal("fe:54:00:00:3e:05"));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user