ONOS-2513 Fix entire MP2SP intent failing on partial connectivity loss

 * Added PartialFailureContraint to MP2SP intent to allow partial connectivity.
   This means the intent remains installed as long as at least one ingress point
   can reach the egress point.
 * Intents with this constraint are recompiled on ObjectiveTracker triggers
   even if not in FAILED state
 * MP2SP intent compiler can compute a partial tree if constraint is set
 * ObjectiveTracker recompiles intents on any link event
 * SDN-IP MP2SP intents now use PartialFailureConstraint

Ported from onos-1.2 branch.

Change-Id: I32eaa198fae1dfba021d9251c8f855573f0e1d7d
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index ded3924..d974009 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -63,6 +63,7 @@
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.intent.IntentState.*;
+import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
 import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
 import static org.onosproject.security.AppGuard.checkPermission;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -85,6 +86,8 @@
 
     private static final EnumSet<IntentState> RECOMPILE
             = EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
+    private static final EnumSet<IntentState> WITHDRAW
+            = EnumSet.of(WITHDRAW_REQ, WITHDRAWING, WITHDRAWN);
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected CoreService coreService;
@@ -252,16 +255,15 @@
             submit(intent);
         }
 
-        if (compileAllFailed) {
-            // If required, compile all currently failed intents.
-            for (Intent intent : getIntents()) {
-                IntentState state = getIntentState(intent.key());
-                if (RECOMPILE.contains(state)) {
-                    if (state == WITHDRAW_REQ) {
-                        withdraw(intent);
-                    } else {
-                        submit(intent);
-                    }
+        // If required, compile all currently failed intents.
+        for (Intent intent : getIntents()) {
+            IntentState state = getIntentState(intent.key());
+            if ((compileAllFailed && RECOMPILE.contains(state))
+                    || intentAllowsPartialFailure(intent)) {
+                if (WITHDRAW.contains(state)) {
+                    withdraw(intent);
+                } else {
+                    submit(intent);
                 }
             }
         }