2929import com .cloud .agent .api .Command ;
3030import com .cloud .agent .api .NetworkUsageCommand ;
3131import com .cloud .agent .manager .Commands ;
32+ import com .cloud .dc .DataCenterVO ;
33+ import com .cloud .dc .dao .DataCenterDao ;
3234import com .cloud .exception .ConcurrentOperationException ;
3335import com .cloud .exception .InsufficientCapacityException ;
3436import com .cloud .exception .ResourceUnavailableException ;
3840import com .cloud .network .Networks .BroadcastDomainType ;
3941import com .cloud .network .Networks .IsolationType ;
4042import com .cloud .network .PublicIpAddress ;
43+ import com .cloud .network .dao .FirewallRulesDao ;
44+ import com .cloud .network .dao .IPAddressDao ;
45+ import com .cloud .network .dao .IPAddressVO ;
4146import com .cloud .network .router .VirtualRouter ;
4247import com .cloud .network .vpc .VpcManager ;
4348import com .cloud .network .vpc .VpcVO ;
5156import com .cloud .vm .VirtualMachineManager ;
5257import com .cloud .vm .dao .NicDao ;
5358
59+ import org .apache .cloudstack .network .topology .NetworkTopology ;
60+ import org .apache .cloudstack .network .topology .NetworkTopologyContext ;
61+
5462public class NicPlugInOutRules extends RuleApplier {
5563
5664 private static final Logger s_logger = Logger .getLogger (NicPlugInOutRules .class );
@@ -75,6 +83,28 @@ public boolean accept(final NetworkTopologyVisitor visitor, final VirtualRouter
7583
7684 NetworkModel networkModel = visitor .getVirtualNetworkApplianceFactory ().getNetworkModel ();
7785 VirtualMachineManager itMgr = visitor .getVirtualNetworkApplianceFactory ().getItMgr ();
86+ NicDao nicDao = visitor .getVirtualNetworkApplianceFactory ().getNicDao ();
87+
88+ // de-associate IPs before unplugging nics
89+ if (!nicsToUnplug .isEmpty ()) {
90+ NetworkTopologyContext networkTopologyContext = visitor .getVirtualNetworkApplianceFactory ().getNetworkTopologyContext ();
91+ final DataCenterDao dcDao = visitor .getVirtualNetworkApplianceFactory ().getDcDao ();
92+ final DataCenterVO dcVO = dcDao .findById (router .getDataCenterId ());
93+ final NetworkTopology networkTopology = networkTopologyContext .retrieveNetworkTopology (dcVO );
94+
95+ final String typeString = "vpc ip association before unplugging nics" ;
96+ final boolean isPodLevelException = false ;
97+ final boolean failWhenDisconnect = false ;
98+ final Long podId = null ;
99+ final VpcIpAssociationRules ipAssociationRules = new VpcIpAssociationRules (_network , _ipAddresses );
100+ final boolean result = networkTopology .applyRules (_network , router , typeString , isPodLevelException , podId , failWhenDisconnect ,
101+ new RuleApplierWrapper <RuleApplier >(ipAssociationRules ));
102+ if (!result ) {
103+ s_logger .warn ("Failed to de-associate IPs before unplugging nics" );
104+ return false ;
105+ }
106+ }
107+
78108 // 1) Unplug the nics
79109 for (Entry <String , PublicIpAddress > entry : nicsToUnplug .entrySet ()) {
80110 Network publicNtwk = null ;
@@ -159,6 +189,9 @@ private Pair<Map<String, PublicIpAddress>, Map<String, PublicIpAddress>> getNics
159189
160190 VpcManager vpcMgr = visitor .getVirtualNetworkApplianceFactory ().getVpcMgr ();
161191 NicDao nicDao = visitor .getVirtualNetworkApplianceFactory ().getNicDao ();
192+ IPAddressDao ipAddressDao = visitor .getVirtualNetworkApplianceFactory ().getIpAddressDao ();
193+ FirewallRulesDao rulesDao = visitor .getVirtualNetworkApplianceFactory ().getFirewallRulesDao ();
194+
162195 // find out nics to unplug
163196 for (PublicIpAddress ip : _ipAddresses ) {
164197 long publicNtwkId = ip .getNetworkId ();
@@ -170,10 +203,26 @@ private Pair<Map<String, PublicIpAddress>, Map<String, PublicIpAddress>> getNics
170203 }
171204
172205 if (ip .getState () == IpAddress .State .Releasing ) {
173- Nic nic = nicDao .findByIp4AddressAndNetworkIdAndInstanceId (publicNtwkId , _router .getId (), ip .getAddress ().addr ());
206+ NicVO nic = nicDao .findByIp4AddressAndNetworkIdAndInstanceId (publicNtwkId , _router .getId (), ip .getAddress ().addr ());
174207 if (nic != null ) {
175- nicsToUnplug .put (ip .getVlanTag (), ip );
176- s_logger .debug ("Need to unplug the nic for ip=" + ip + "; vlan=" + ip .getVlanTag () + " in public network id =" + publicNtwkId );
208+ final List <IPAddressVO > allIps = ipAddressDao .listByAssociatedVpc (ip .getVpcId (), null );
209+ boolean ipUpdated = false ;
210+ for (IPAddressVO allIp : allIps ) {
211+ if (allIp .getId () != ip .getId () && allIp .getVlanId () == ip .getVlanId ()
212+ && (allIp .isSourceNat ()
213+ || rulesDao .countRulesByIpIdAndState (allIp .getId (), FirewallRule .State .Active ) > 0
214+ || (allIp .isOneToOneNat () && allIp .getRuleState () == null ))) {
215+ s_logger .debug ("Updating the nic " + nic + " with new ip address " + allIp .getAddress ().addr ());
216+ nic .setIPv4Address (allIp .getAddress ().addr ());
217+ nicDao .update (nic .getId (), nic );
218+ ipUpdated = true ;
219+ break ;
220+ }
221+ }
222+ if (!ipUpdated ) {
223+ nicsToUnplug .put (ip .getVlanTag (), ip );
224+ s_logger .debug ("Need to unplug the nic for ip=" + ip + "; vlan=" + ip .getVlanTag () + " in public network id =" + publicNtwkId );
225+ }
177226 }
178227 }
179228 }
@@ -215,4 +264,4 @@ private Pair<Map<String, PublicIpAddress>, Map<String, PublicIpAddress>> getNics
215264
216265 return nicsToChange ;
217266 }
218- }
267+ }
0 commit comments