1717
1818package org .apache .cloudstack .network .topology ;
1919
20+ import java .util .ArrayList ;
2021import java .util .List ;
2122
2223import org .apache .log4j .Logger ;
2324import org .springframework .beans .factory .annotation .Autowired ;
2425import org .springframework .beans .factory .annotation .Qualifier ;
2526import org .springframework .stereotype .Component ;
2627
28+ import com .cloud .dc .DataCenter ;
29+ import com .cloud .dc .DataCenter .NetworkType ;
30+ import com .cloud .dc .Pod ;
2731import com .cloud .deploy .DeployDestination ;
32+ import com .cloud .exception .AgentUnavailableException ;
2833import com .cloud .exception .ResourceUnavailableException ;
34+ import com .cloud .host .Status ;
2935import com .cloud .network .Network ;
3036import com .cloud .network .PublicIpAddress ;
3137import com .cloud .network .router .VirtualRouter ;
3945import com .cloud .network .vpc .NetworkACLItem ;
4046import com .cloud .vm .DomainRouterVO ;
4147import com .cloud .vm .NicProfile ;
48+ import com .cloud .vm .VirtualMachine .State ;
4249import com .cloud .vm .VirtualMachineProfile ;
4350
4451@ Component
@@ -105,14 +112,25 @@ public boolean associatePublicIP(final Network network, final List<? extends Pub
105112 final Long podId = null ;
106113
107114 NicPlugInOutRules nicPlugInOutRules = _virtualNetworkApplianceFactory .createNicPluInOutRules (network , ipAddresses );
108- VpcIpAssociationRules ipAssociationRules = _virtualNetworkApplianceFactory . createVpcIpAssociationRules ( network , ipAddresses , nicPlugInOutRules );
115+ nicPlugInOutRules . accept ( _advancedVisitor , router );
109116
110- return applyRules (network , routers , typeString , isPodLevelException , podId , failWhenDisconnect , new RuleApplierWrapper <RuleApplier >(ipAssociationRules ));
117+ VpcIpAssociationRules ipAssociationRules = _virtualNetworkApplianceFactory .createVpcIpAssociationRules (network , ipAddresses );
118+ boolean result = applyRules (network , routers , typeString , isPodLevelException , podId , failWhenDisconnect , new RuleApplierWrapper <RuleApplier >(ipAssociationRules ));
119+
120+ if (result ) {
121+ _advancedVisitor .visit (nicPlugInOutRules );
122+ }
123+
124+ return result ;
111125 }
112126
113127 @ Override
114128 public boolean applyNetworkACLs (final Network network , final List <? extends NetworkACLItem > rules , final List <? extends VirtualRouter > routers , final boolean isPrivateGateway )
115129 throws ResourceUnavailableException {
130+ if (rules == null || rules .isEmpty ()) {
131+ s_logger .debug ("No network ACLs to be applied for network " + network .getId ());
132+ return true ;
133+ }
116134
117135 s_logger .debug ("APPLYING NETWORK ACLs RULES" );
118136
@@ -125,4 +143,92 @@ public boolean applyNetworkACLs(final Network network, final List<? extends Netw
125143
126144 return applyRules (network , routers , typeString , isPodLevelException , podId , failWhenDisconnect , new RuleApplierWrapper <RuleApplier >(aclsRules ));
127145 }
146+
147+ @ Override
148+ public boolean applyRules (final Network network , final List <? extends VirtualRouter > routers , final String typeString , final boolean isPodLevelException , final Long podId , final boolean failWhenDisconnect ,
149+ final RuleApplierWrapper <RuleApplier > ruleApplierWrapper )
150+ throws ResourceUnavailableException {
151+
152+ if (routers == null || routers .isEmpty ()) {
153+ s_logger .warn ("Unable to apply " + typeString + ", virtual router doesn't exist in the network " + network .getId ());
154+ throw new ResourceUnavailableException ("Unable to apply " + typeString , DataCenter .class , network .getDataCenterId ());
155+ }
156+
157+ RuleApplier ruleApplier = ruleApplierWrapper .getRuleType ();
158+
159+ final DataCenter dc = _dcDao .findById (network .getDataCenterId ());
160+ final boolean isZoneBasic = (dc .getNetworkType () == NetworkType .Basic );
161+
162+ // isPodLevelException and podId is only used for basic zone
163+ assert !((!isZoneBasic && isPodLevelException ) || (isZoneBasic && isPodLevelException && podId == null ));
164+
165+ final List <VirtualRouter > connectedRouters = new ArrayList <VirtualRouter >();
166+ final List <VirtualRouter > disconnectedRouters = new ArrayList <VirtualRouter >();
167+ boolean result = true ;
168+ final String msg = "Unable to apply " + typeString + " on disconnected router " ;
169+ for (final VirtualRouter router : routers ) {
170+ if (router .getState () == State .Running ) {
171+ s_logger .debug ("Applying " + typeString + " in network " + network );
172+
173+ if (router .isStopPending ()) {
174+ if (_hostDao .findById (router .getHostId ()).getState () == Status .Up ) {
175+ throw new ResourceUnavailableException ("Unable to process due to the stop pending router " + router .getInstanceName () +
176+ " haven't been stopped after it's host coming back!" , DataCenter .class , router .getDataCenterId ());
177+ }
178+ s_logger .debug ("Router " + router .getInstanceName () + " is stop pending, so not sending apply " + typeString + " commands to the backend" );
179+ continue ;
180+ }
181+
182+ try {
183+ ruleApplier .accept (_advancedVisitor , router );
184+
185+ connectedRouters .add (router );
186+ } catch (final AgentUnavailableException e ) {
187+ s_logger .warn (msg + router .getInstanceName (), e );
188+ disconnectedRouters .add (router );
189+ }
190+
191+ //If rules fail to apply on one domR and not due to disconnection, no need to proceed with the rest
192+ if (!result ) {
193+ if (isZoneBasic && isPodLevelException ) {
194+ throw new ResourceUnavailableException ("Unable to apply " + typeString + " on router " , Pod .class , podId );
195+ }
196+ throw new ResourceUnavailableException ("Unable to apply " + typeString + " on router " , DataCenter .class , router .getDataCenterId ());
197+ }
198+
199+ } else if (router .getState () == State .Stopped || router .getState () == State .Stopping ) {
200+ s_logger .debug ("Router " + router .getInstanceName () + " is in " + router .getState () + ", so not sending apply " + typeString + " commands to the backend" );
201+ } else {
202+ s_logger .warn ("Unable to apply " + typeString + ", virtual router is not in the right state " + router .getState ());
203+ if (isZoneBasic && isPodLevelException ) {
204+ throw new ResourceUnavailableException ("Unable to apply " + typeString + ", virtual router is not in the right state" , Pod .class , podId );
205+ }
206+ throw new ResourceUnavailableException ("Unable to apply " + typeString + ", virtual router is not in the right state" , DataCenter .class ,
207+ router .getDataCenterId ());
208+ }
209+ }
210+
211+ if (!connectedRouters .isEmpty ()) {
212+ if (!isZoneBasic && !disconnectedRouters .isEmpty () && disconnectedRouters .get (0 ).getIsRedundantRouter ()) {
213+ // These disconnected redundant virtual routers are out of sync now, stop them for synchronization
214+ //[FIXME] handleSingleWorkingRedundantRouter(connectedRouters, disconnectedRouters, msg);
215+ }
216+ } else if (!disconnectedRouters .isEmpty ()) {
217+ for (final VirtualRouter router : disconnectedRouters ) {
218+ if (s_logger .isDebugEnabled ()) {
219+ s_logger .debug (msg + router .getInstanceName () + "(" + router .getId () + ")" );
220+ }
221+ }
222+ if (isZoneBasic && isPodLevelException ) {
223+ throw new ResourceUnavailableException (msg , Pod .class , podId );
224+ }
225+ throw new ResourceUnavailableException (msg , DataCenter .class , disconnectedRouters .get (0 ).getDataCenterId ());
226+ }
227+
228+ result = true ;
229+ if (failWhenDisconnect ) {
230+ result = !connectedRouters .isEmpty ();
231+ }
232+ return result ;
233+ }
128234}
0 commit comments