private void applyNetworkServices( final VmInstanceSpec spec, NetworkServiceExtensionPosition position, final Completion completion) { if (!spec.getVmInventory().getType().equals(VmInstanceConstant.USER_VM_TYPE)) { completion.success(); return; } if (nsExts.isEmpty()) { completion.success(); return; } if (spec.getL3Networks() == null || spec.getL3Networks().isEmpty()) { completion.success(); return; } // we run into this situation when VM nics are all detached and the // VM is being rebooted if (spec.getDestNics().isEmpty()) { completion.success(); return; } List<String> nsTypes = spec.getRequiredNetworkServiceTypes(); FlowChain schain = FlowChainBuilder.newSimpleFlowChain() .setName( String.format("apply-network-service-to-vm-%s", spec.getVmInventory().getUuid())); schain.allowEmptyFlow(); for (final NetworkServiceExtensionPoint ns : nsExts) { if (ns.getNetworkServiceExtensionPosition() != position) { continue; } if (!nsTypes.contains(ns.getNetworkServiceType().toString())) { continue; } Flow flow = new Flow() { String __name__ = String.format("apply-network-service-%s", ns.getNetworkServiceType()); @Override public void run(final FlowTrigger chain, Map data) { logger.debug( String.format( "NetworkServiceExtensionPoint[%s] is asking back ends to apply network service[%s] if needed", ns.getClass().getName(), ns.getNetworkServiceType())); ns.applyNetworkService( spec, data, new Completion() { @Override public void success() { chain.next(); } @Override public void fail(ErrorCode errorCode) { chain.fail(errorCode); } }); } @Override public void rollback(final FlowRollback chain, Map data) { logger.debug( String.format( "NetworkServiceExtensionPoint[%s] is asking back ends to release network service[%s] if needed", ns.getClass().getName(), ns.getNetworkServiceType())); ns.releaseNetworkService( spec, data, new NoErrorCompletion() { @Override public void done() { chain.rollback(); } }); } }; schain.then(flow); } schain .error( new FlowErrorHandler() { @Override public void handle(ErrorCode err, Map data) { completion.fail(err); } }) .done( new FlowDoneHandler() { @Override public void handle(Map data) { completion.success(); } }) .start(); }