Skip to content

Commit 8798014

Browse files
fmaximusyadvr
authored andcommitted
CLOUDSTACK-10377: Fix Network restart for Nuage (#2672)
Changes in PR #2508 have caused network restart to fail in a Nuage setup, as the new VR takes the same IP as the old one, and the old VR is still running. Nuage doesn't support multiple VM's having the same IP. We delay provisioning the interfaces in VSD until the old VR interface is released.
1 parent 9b83337 commit 8798014

9 files changed

Lines changed: 413 additions & 299 deletions

File tree

api/src/com/cloud/vm/VirtualMachineProfile.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public static class Param {
5656
public static final Param VmSshPubKey = new Param("VmSshPubKey");
5757
public static final Param ControlNic = new Param("ControlNic");
5858
public static final Param ReProgramGuestNetworks = new Param("RestartNetwork");
59+
public static final Param RollingRestart = new Param("RollingRestart");
5960
public static final Param PxeSeverType = new Param("PxeSeverType");
6061
public static final Param HaTag = new Param("HaTag");
6162
public static final Param HaOperation = new Param("HaOperation");
@@ -173,4 +174,6 @@ public boolean equals(Object obj) {
173174

174175
Float getMemoryOvercommitRatio();
175176

177+
boolean isRollingRestart();
178+
176179
}

engine/components-api/src/com/cloud/vm/VirtualMachineProfileImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@ public Float getMemoryOvercommitRatio() {
263263
return memoryOvercommitRatio;
264264
}
265265

266+
@Override
267+
public boolean isRollingRestart() {
268+
return Boolean.TRUE.equals(getParameter(VirtualMachineProfile.Param.RollingRestart));
269+
}
270+
266271
@Override
267272
public List<String[]> getVmData() {
268273
return vmData;

plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454

5555
import com.cloud.agent.AgentManager;
5656
import com.cloud.agent.api.Answer;
57+
import com.cloud.agent.api.Command;
5758
import com.cloud.agent.api.StartupCommand;
5859
import com.cloud.agent.api.StartupVspCommand;
5960
import com.cloud.agent.api.element.ApplyAclRuleVspCommand;
@@ -289,14 +290,41 @@ public boolean implement(Network network, NetworkOffering offering, DeployDestin
289290
VspDhcpDomainOption vspDhcpOptions = _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering);
290291
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
291292
ImplementVspCommand cmd = new ImplementVspCommand(vspNetwork, ingressFirewallRules, egressFirewallRules, floatingIpUuids, vspDhcpOptions);
293+
send(cmd, network);
294+
295+
return true;
296+
}
297+
298+
private void send(Command cmd, Network network)
299+
throws ResourceUnavailableException {
300+
send(cmd, network.getPhysicalNetworkId(), Network.class, network);
301+
}
302+
303+
private void send(Command cmd, Vpc vpc)
304+
throws ResourceUnavailableException {
305+
send(cmd, getPhysicalNetworkId(vpc.getZoneId()), Vpc.class, vpc);
306+
}
307+
308+
309+
private <R extends InternalIdentity> void send(Command cmd, long physicalNetworkId, Class<R> resourceClass,
310+
R resource)
311+
throws ResourceUnavailableException {
312+
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId);
292313
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
293-
if (answer == null || !answer.getResult()) {
294-
s_logger.error("ImplementVspCommand for network " + network.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
295-
if ((null != answer) && (null != answer.getDetails())) {
296-
throw new ResourceUnavailableException(answer.getDetails(), Network.class, network.getId());
314+
if (isFailure(answer)) {
315+
s_logger.error(cmd.getClass().getName() + " for " + resourceClass.getName() + " " + resource.getId() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
316+
if (hasFailureDetails(answer)) {
317+
throw new ResourceUnavailableException(answer.getDetails(), resourceClass, resource.getId());
297318
}
298319
}
299-
return true;
320+
}
321+
322+
private boolean hasFailureDetails(Answer answer) {
323+
return (null != answer) && (null != answer.getDetails());
324+
}
325+
326+
private boolean isFailure(Answer answer) {
327+
return answer == null || !answer.getResult();
300328
}
301329

302330
private boolean applyACLRulesForVpc(Network network, NetworkOffering offering) throws ResourceUnavailableException {
@@ -358,15 +386,9 @@ public boolean shutdown(Network network, ReservationContext context, boolean cle
358386
NetworkOfferingVO networkOfferingVO = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
359387
VspDhcpDomainOption vspDhcpOptions = _nuageVspEntityBuilder.buildNetworkDhcpOption(network, networkOfferingVO);
360388
VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
361-
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
389+
362390
ShutDownVspCommand cmd = new ShutDownVspCommand(vspNetwork, vspDhcpOptions);
363-
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
364-
if (answer == null || !answer.getResult()) {
365-
s_logger.error("ShutDownVspCommand for network " + network.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
366-
if ((null != answer) && (null != answer.getDetails())) {
367-
throw new ResourceUnavailableException(answer.getDetails(), Network.class, network.getId());
368-
}
369-
}
391+
send(cmd, network);
370392
}
371393
return true;
372394
}
@@ -501,14 +523,17 @@ public boolean removeDhcpSupportForSubnet(Network network) throws ResourceUnavai
501523

502524
@Override
503525
public boolean setExtraDhcpOptions(Network network, long nicId, Map<Integer, String> dhcpOptions) {
526+
if (network.isRollingRestart()) {
527+
return true;
528+
}
529+
504530
VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
505531
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
506532
NicVO nic = _nicDao.findById(nicId);
507533

508534
ExtraDhcpOptionsVspCommand extraDhcpOptionsVspCommand = new ExtraDhcpOptionsVspCommand(vspNetwork, nic.getUuid(), dhcpOptions);
509535
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), extraDhcpOptionsVspCommand);
510-
511-
if (answer == null || !answer.getResult()) {
536+
if (isFailure(answer)) {
512537
s_logger.error("[setExtraDhcpOptions] setting extra DHCP options for nic " + nic.getUuid() + " failed.");
513538
return false;
514539
}
@@ -539,15 +564,9 @@ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules)
539564
}
540565

541566
VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(config);
542-
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(config.getPhysicalNetworkId());
543567
ApplyStaticNatVspCommand cmd = new ApplyStaticNatVspCommand(vspNetwork, vspStaticNatDetails);
544-
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
545-
if (answer == null || !answer.getResult()) {
546-
s_logger.error("ApplyStaticNatNuageVspCommand for network " + config.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
547-
if ((null != answer) && (null != answer.getDetails())) {
548-
throw new ResourceUnavailableException(answer.getDetails(), Network.class, config.getId());
549-
}
550-
}
568+
send(cmd,
569+
config);
551570

552571
return true;
553572
}
@@ -611,16 +630,10 @@ public VspAclRule apply(@Nullable InternalIdentity input) {
611630
}
612631
});
613632

614-
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
615633
VspAclRule.ACLType vspAclType = isNetworkAcl ? VspAclRule.ACLType.NetworkACL : VspAclRule.ACLType.Firewall;
616634
ApplyAclRuleVspCommand cmd = new ApplyAclRuleVspCommand(vspAclType, vspNetwork, vspAclRules, networkReset);
617-
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
618-
if (answer == null || !answer.getResult()) {
619-
s_logger.error("ApplyAclRuleNuageVspCommand for network " + network.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
620-
if ((null != answer) && (null != answer.getDetails())) {
621-
throw new ResourceUnavailableException(answer.getDetails(), Network.class, network.getId());
622-
}
623-
}
635+
send(cmd,
636+
network);
624637
return true;
625638
}
626639

@@ -686,7 +699,6 @@ public String apply(@Nullable DomainRouterVO input) {
686699
});
687700

688701
Domain vpcDomain = _domainDao.findById(vpc.getDomainId());
689-
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(getPhysicalNetworkId(vpc.getZoneId()));
690702

691703
String preConfiguredDomainTemplateName;
692704
VpcDetailVO domainTemplateNameDetail = _vpcDetailsDao.findDetail(vpc.getId(), NuageVspManager.nuageDomainTemplateDetailName);
@@ -710,14 +722,7 @@ public String apply(@Nullable DomainRouterVO input) {
710722
}
711723

712724
ShutDownVpcVspCommand cmd = new ShutDownVpcVspCommand(vpcDomain.getUuid(), vpc.getUuid(), preConfiguredDomainTemplateName, domainRouterUuids, vpcDetails);
713-
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
714-
if (answer == null || !answer.getResult()) {
715-
s_logger.error("ShutDownVpcVspCommand for VPC " + vpc.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
716-
if ((null != answer) && (null != answer.getDetails())) {
717-
throw new ResourceUnavailableException(answer.getDetails(), Vpc.class, vpc.getId());
718-
}
719-
return false;
720-
}
725+
send(cmd, vpc);
721726
}
722727
return true;
723728
}

plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import com.cloud.network.dao.NetworkVO;
8383
import com.cloud.network.dao.PhysicalNetworkVO;
8484
import com.cloud.network.manager.NuageVspManager;
85+
import com.cloud.network.router.VirtualRouter;
8586
import com.cloud.offering.NetworkOffering;
8687
import com.cloud.offerings.dao.NetworkOfferingDao;
8788
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
@@ -94,13 +95,15 @@
9495
import com.cloud.utils.db.DB;
9596
import com.cloud.utils.exception.CloudRuntimeException;
9697
import com.cloud.utils.net.Ip;
98+
import com.cloud.vm.DomainRouterVO;
9799
import com.cloud.vm.Nic;
98100
import com.cloud.vm.NicProfile;
99101
import com.cloud.vm.NicVO;
100102
import com.cloud.vm.ReservationContext;
101103
import com.cloud.vm.VMInstanceVO;
102104
import com.cloud.vm.VirtualMachine;
103105
import com.cloud.vm.VirtualMachineProfile;
106+
import com.cloud.vm.dao.DomainRouterDao;
104107
import com.cloud.vm.dao.VMInstanceDao;
105108

106109
public class NuageVspGuestNetworkGuru extends GuestNetworkGuru implements NetworkGuruAdditionalFunctions {
@@ -134,6 +137,8 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru implements Networ
134137
DataCenterDetailsDao _dcDetailsDao;
135138
@Inject
136139
VlanDetailsDao _vlanDetailsDao;
140+
@Inject
141+
private DomainRouterDao _routerDao;
137142

138143
public NuageVspGuestNetworkGuru() {
139144
super();
@@ -528,29 +533,34 @@ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, D
528533
nic.setBroadcastUri(network.getBroadcastUri());
529534
nic.setIsolationUri(network.getBroadcastUri());
530535

531-
//NicProfile does not contain the NIC UUID. We need this information to set it in the VMInterface and VPort
532-
//that we create in VSP
533-
NicVO nicFromDb = _nicDao.findById(nic.getId());
534-
IPAddressVO staticNatIp = _ipAddressDao.findByVmIdAndNetworkId(network.getId(), vm.getId());
535536
VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network);
536-
VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic);
537-
VspStaticNat vspStaticNat = null;
538-
if (staticNatIp != null) {
539-
VlanVO staticNatVlan = _vlanDao.findById(staticNatIp.getVlanId());
540-
vspStaticNat = _nuageVspEntityBuilder.buildVspStaticNat(null, staticNatIp, staticNatVlan, vspNic);
541-
}
542537

543-
boolean defaultHasDns = getDefaultHasDns(networkHasDnsCache, nicFromDb);
544-
VspDhcpVMOption dhcpOption = _nuageVspEntityBuilder.buildVmDhcpOption(nicFromDb, defaultHasDns, networkHasDns);
545-
ReserveVmInterfaceVspCommand cmd = new ReserveVmInterfaceVspCommand(vspNetwork, vspVm, vspNic, vspStaticNat, dhcpOption);
546-
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
538+
if (vm.isRollingRestart()) {
539+
((NetworkVO)network).setRollingRestart(true);
540+
} else {
541+
//NicProfile does not contain the NIC UUID. We need this information to set it in the VMInterface and VPort
542+
//that we create in VSP
543+
NicVO nicFromDb = _nicDao.findById(nic.getId());
544+
IPAddressVO staticNatIp = _ipAddressDao.findByVmIdAndNetworkId(network.getId(), vm.getId());
545+
VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic);
546+
VspStaticNat vspStaticNat = null;
547+
if (staticNatIp != null) {
548+
VlanVO staticNatVlan = _vlanDao.findById(staticNatIp.getVlanId());
549+
vspStaticNat = _nuageVspEntityBuilder.buildVspStaticNat(null, staticNatIp, staticNatVlan, vspNic);
550+
}
547551

548-
if (answer == null || !answer.getResult()) {
549-
s_logger.error("ReserveVmInterfaceNuageVspCommand failed for NIC " + nic.getId() + " attached to VM " + vm.getId() + " in network " + network.getId());
550-
if ((null != answer) && (null != answer.getDetails())) {
551-
s_logger.error(answer.getDetails());
552+
boolean defaultHasDns = getDefaultHasDns(networkHasDnsCache, nicFromDb);
553+
VspDhcpVMOption dhcpOption = _nuageVspEntityBuilder.buildVmDhcpOption(nicFromDb, defaultHasDns, networkHasDns);
554+
ReserveVmInterfaceVspCommand cmd = new ReserveVmInterfaceVspCommand(vspNetwork, vspVm, vspNic, vspStaticNat, dhcpOption);
555+
Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
556+
557+
if (answer == null || !answer.getResult()) {
558+
s_logger.error("ReserveVmInterfaceNuageVspCommand failed for NIC " + nic.getId() + " attached to VM " + vm.getId() + " in network " + network.getId());
559+
if ((null != answer) && (null != answer.getDetails())) {
560+
s_logger.error(answer.getDetails());
561+
}
562+
throw new InsufficientVirtualNetworkCapacityException("Failed to reserve VM in Nuage VSP.", Network.class, network.getId());
552563
}
553-
throw new InsufficientVirtualNetworkCapacityException("Failed to reserve VM in Nuage VSP.", Network.class, network.getId());
554564
}
555565

556566
if (vspVm.getDomainRouter() == Boolean.TRUE) {
@@ -695,15 +705,18 @@ public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm
695705
}
696706

697707
try {
708+
final VirtualMachine virtualMachine = vm.getVirtualMachine();
698709
if (s_logger.isDebugEnabled()) {
699710
s_logger.debug("Handling deallocate() call back, which is called when a VM is destroyed or interface is removed, " + "to delete VM Interface with IP "
700-
+ nic.getIPv4Address() + " from a VM " + vm.getInstanceName() + " with state " + vm.getVirtualMachine().getState());
711+
+ nic.getIPv4Address() + " from a VM " + vm.getInstanceName() + " with state " + virtualMachine
712+
.getState());
701713
}
702714

703715
NicVO nicFromDb = _nicDao.findById(nic.getId());
704716

705-
VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network);
706-
VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network);
717+
VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(virtualMachine
718+
.getDomainId(), network);
719+
VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(virtualMachine, network);
707720
VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic);
708721
HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
709722

@@ -723,6 +736,32 @@ public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm
723736
} else {
724737
super.deallocate(network, nic, vm);
725738
}
739+
740+
if (virtualMachine.getType() == VirtualMachine.Type.DomainRouter) {
741+
final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER);
742+
final DomainRouterVO otherRouter = routers.stream()
743+
.filter(r -> r.getId() != vm.getId())
744+
.findFirst()
745+
.orElse(null);
746+
747+
if (otherRouter != null) {
748+
nicFromDb = _nicDao.findByNtwkIdAndInstanceId(network.getId(), otherRouter.getId());
749+
vspVm = _nuageVspEntityBuilder.buildVspVm(otherRouter, network);
750+
vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb);
751+
752+
VspDhcpVMOption dhcpOption = _nuageVspEntityBuilder.buildVmDhcpOption(nicFromDb, false, false);
753+
ReserveVmInterfaceVspCommand reserveCmd = new ReserveVmInterfaceVspCommand(vspNetwork, vspVm, vspNic, null, dhcpOption);
754+
755+
answer = _agentMgr.easySend(nuageVspHost.getId(), reserveCmd);
756+
if (answer == null || !answer.getResult()) {
757+
s_logger.error("DeallocateVmNuageVspCommand for VM " + vm.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
758+
if ((null != answer) && (null != answer.getDetails())) {
759+
s_logger.error(answer.getDetails());
760+
}
761+
}
762+
}
763+
764+
}
726765
} finally {
727766
if (network != null && lockedNetwork) {
728767
_networkDao.releaseFromLockTable(network.getId());

0 commit comments

Comments
 (0)