mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-9717: [VMware] RVRs have mismatching MAC addresses for extra public NICs. (#1878)
Fix: When RVR is enabled and Peer Router is available, get the MAC addresses of the extra public NICs from the Peer Router and set them to the router.
This commit is contained in:
parent
b947eca958
commit
0c6cf69eee
@ -77,5 +77,7 @@ public interface NicDao extends GenericDao<NicVO, Long> {
|
||||
|
||||
NicVO getControlNicForVM(long vmId);
|
||||
|
||||
Long getPeerRouterId(String publicMacAddress, long routerId);
|
||||
|
||||
List<NicVO> listByVmIdAndKeyword(long instanceId, String keyword);
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
|
||||
private SearchBuilder<NicVO> NonReleasedSearch;
|
||||
private GenericSearchBuilder<NicVO, Integer> deviceIdSearch;
|
||||
private GenericSearchBuilder<NicVO, Integer> CountByForStartingVms;
|
||||
private SearchBuilder<NicVO> PeerRouterSearch;
|
||||
|
||||
@Inject
|
||||
VMInstanceDao _vmDao;
|
||||
@ -94,6 +95,12 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
|
||||
join1.and("state", join1.entity().getState(), Op.EQ);
|
||||
CountByForStartingVms.join("vm", join1, CountByForStartingVms.entity().getInstanceId(), join1.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
CountByForStartingVms.done();
|
||||
|
||||
PeerRouterSearch = createSearchBuilder();
|
||||
PeerRouterSearch.and("instanceId", PeerRouterSearch.entity().getInstanceId(), Op.NEQ);
|
||||
PeerRouterSearch.and("macAddress", PeerRouterSearch.entity().getMacAddress(), Op.EQ);
|
||||
PeerRouterSearch.and("vmType", PeerRouterSearch.entity().getVmType(), Op.EQ);
|
||||
PeerRouterSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -312,6 +319,19 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
|
||||
return results.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getPeerRouterId(String publicMacAddress, final long routerId) {
|
||||
final SearchCriteria<NicVO> sc = PeerRouterSearch.create();
|
||||
sc.setParameters("instanceId", routerId);
|
||||
sc.setParameters("macAddress", publicMacAddress);
|
||||
sc.setParameters("vmType", VirtualMachine.Type.DomainRouter);
|
||||
NicVO nicVo = findOneBy(sc);
|
||||
if (nicVo != null) {
|
||||
return nicVo.getInstanceId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NicVO> listByVmIdAndKeyword(long instanceId, String keyword) {
|
||||
SearchCriteria<NicVO> sc = AllFieldsSearch.create();
|
||||
|
||||
@ -94,6 +94,7 @@ import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.NicVO;
|
||||
import com.cloud.vm.SecondaryStorageVmVO;
|
||||
@ -101,6 +102,7 @@ import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
@ -128,6 +130,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
||||
@Inject
|
||||
private NicDao _nicDao;
|
||||
@Inject
|
||||
private DomainRouterDao _domainRouterDao;
|
||||
@Inject
|
||||
private PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
|
||||
@Inject
|
||||
private VMInstanceDao _vmDao;
|
||||
@ -296,6 +300,19 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
||||
}
|
||||
|
||||
to.setNics(expandedNics);
|
||||
|
||||
VirtualMachine router = vm.getVirtualMachine();
|
||||
DomainRouterVO routerVO = _domainRouterDao.findById(router.getId());
|
||||
if (routerVO != null && routerVO.getIsRedundantRouter()) {
|
||||
Long peerRouterId = _nicDao.getPeerRouterId(publicNicProfile.getMacAddress(), router.getId());
|
||||
DomainRouterVO peerRouterVO = null;
|
||||
if (peerRouterId != null) {
|
||||
peerRouterVO = _domainRouterDao.findById(peerRouterId);
|
||||
if (peerRouterVO != null) {
|
||||
details.put("PeerRouterInstanceName", peerRouterVO.getInstanceName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer sbMacSequence = new StringBuffer();
|
||||
|
||||
@ -46,6 +46,7 @@ import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.NDC;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.vim25.AboutInfo;
|
||||
@ -1959,6 +1960,40 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
VirtualDevice nic;
|
||||
int nicMask = 0;
|
||||
int nicCount = 0;
|
||||
|
||||
if (vmSpec.getType() == VirtualMachine.Type.DomainRouter) {
|
||||
int extraPublicNics = mgr.getRouterExtraPublicNics();
|
||||
if (extraPublicNics > 0 && vmSpec.getDetails().containsKey("PeerRouterInstanceName")) {
|
||||
//Set identical MAC address for RvR on extra public interfaces
|
||||
String peerRouterInstanceName = vmSpec.getDetails().get("PeerRouterInstanceName");
|
||||
|
||||
VirtualMachineMO peerVmMo = hyperHost.findVmOnHyperHost(peerRouterInstanceName);
|
||||
if (peerVmMo == null) {
|
||||
peerVmMo = hyperHost.findVmOnPeerHyperHost(peerRouterInstanceName);
|
||||
}
|
||||
|
||||
if (peerVmMo != null) {
|
||||
String oldMacSequence = generateMacSequence(nics);
|
||||
|
||||
for (int nicIndex = nics.length - extraPublicNics; nicIndex < nics.length; nicIndex++) {
|
||||
VirtualDevice nicDevice = peerVmMo.getNicDeviceByIndex(nics[nicIndex].getDeviceId());
|
||||
if (nicDevice != null) {
|
||||
String mac = ((VirtualEthernetCard)nicDevice).getMacAddress();
|
||||
if (mac != null) {
|
||||
s_logger.info("Use same MAC as previous RvR, the MAC is " + mac + " for extra NIC with device id: " + nics[nicIndex].getDeviceId());
|
||||
nics[nicIndex].setMac(mac);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(vmSpec.getBootArgs())) {
|
||||
String newMacSequence = generateMacSequence(nics);
|
||||
vmSpec.setBootArgs(replaceNicsMacSequenceInBootArgs(oldMacSequence, newMacSequence, vmSpec));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.valueOf(vmSpec.getDetails().get(VmDetailConstants.NIC_ADAPTER));
|
||||
if (s_logger.isDebugEnabled())
|
||||
s_logger.debug("VM " + vmInternalCSName + " will be started with NIC device type: " + nicDeviceType);
|
||||
@ -2166,6 +2201,36 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the mac sequence from the nics.
|
||||
*/
|
||||
protected String generateMacSequence(NicTO[] nics) {
|
||||
if (nics.length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuffer sbMacSequence = new StringBuffer();
|
||||
for (NicTO nicTo : sortNicsByDeviceId(nics)) {
|
||||
sbMacSequence.append(nicTo.getMac()).append("|");
|
||||
}
|
||||
if (!sbMacSequence.toString().isEmpty()) {
|
||||
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1); //Remove extra '|' char appended at the end
|
||||
}
|
||||
|
||||
return sbMacSequence.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update boot args with the new nic mac addresses.
|
||||
*/
|
||||
protected String replaceNicsMacSequenceInBootArgs(String oldMacSequence, String newMacSequence, VirtualMachineTO vmSpec) {
|
||||
String bootArgs = vmSpec.getBootArgs();
|
||||
if (!StringUtils.isBlank(bootArgs) && !StringUtils.isBlank(oldMacSequence) && !StringUtils.isBlank(newMacSequence)) {
|
||||
return bootArgs.replace(oldMacSequence, newMacSequence);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets video card memory to the one provided in detail svga.vramSize (if provided) on {@code vmConfigSpec}.
|
||||
* 64MB was always set before.
|
||||
|
||||
@ -58,11 +58,13 @@ import com.vmware.vim25.VirtualDevice;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineVideoCard;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ScaleVmAnswer;
|
||||
import com.cloud.agent.api.ScaleVmCommand;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
@ -215,6 +217,38 @@ public class VmwareResourceTest {
|
||||
verify(_resource).execute(cmd);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateMacSequence() {
|
||||
final NicTO nicTo1 = new NicTO();
|
||||
nicTo1.setMac("01:23:45:67:89:AB");
|
||||
nicTo1.setDeviceId(1);
|
||||
|
||||
final NicTO nicTo2 = new NicTO();
|
||||
nicTo2.setMac("02:00:65:b5:00:03");
|
||||
nicTo2.setDeviceId(0);
|
||||
|
||||
//final NicTO [] nicTOs = {nicTO1, nicTO2, nicTO3};
|
||||
//final NicTO[] nics = new NicTO[]{nic};
|
||||
final NicTO[] nics = new NicTO[] {nicTo1, nicTo2};
|
||||
|
||||
String macSequence = _resource.generateMacSequence(nics);
|
||||
assertEquals(macSequence, "02:00:65:b5:00:03|01:23:45:67:89:AB");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceNicsMacSequenceInBootArgs() {
|
||||
String bootArgs = "nic_macs=02:00:65:b5:00:03|7C02:00:4f:1b:00:15|7C1e:00:54:00:00:0f|7C02:00:35:fa:00:11|7C02:00:47:40:00:12";
|
||||
doReturn(bootArgs).when(vmSpec).getBootArgs();
|
||||
|
||||
String oldMacSequence = "7C02:00:35:fa:00:11|7C02:00:47:40:00:12";
|
||||
String newMacSequence = "7C02:00:0c:1d:00:1d|7C02:00:68:0f:00:1e";
|
||||
|
||||
String updatedBootArgs = _resource.replaceNicsMacSequenceInBootArgs(oldMacSequence, newMacSequence, vmSpec);
|
||||
|
||||
String newBootArgs = "nic_macs=02:00:65:b5:00:03|7C02:00:4f:1b:00:15|7C1e:00:54:00:00:0f|7C02:00:0c:1d:00:1d|7C02:00:68:0f:00:1e";
|
||||
assertEquals(newBootArgs, updatedBootArgs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureVideoCardSvgaVramProvided() throws Exception {
|
||||
Map<String, String> specDetails = new HashMap<String, String>();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user