[STORM-3484] Add Cluster Blacklist to UI to show what supervisors are blacklisted
diff --git a/storm-client/src/jvm/org/apache/storm/generated/SupervisorSummary.java b/storm-client/src/jvm/org/apache/storm/generated/SupervisorSummary.java
index 8cb28ec..3e39bad 100644
--- a/storm-client/src/jvm/org/apache/storm/generated/SupervisorSummary.java
+++ b/storm-client/src/jvm/org/apache/storm/generated/SupervisorSummary.java
@@ -39,6 +39,7 @@
   private static final org.apache.storm.thrift.protocol.TField USED_CPU_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("used_cpu", org.apache.storm.thrift.protocol.TType.DOUBLE, (short)9);
   private static final org.apache.storm.thrift.protocol.TField FRAGMENTED_MEM_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("fragmented_mem", org.apache.storm.thrift.protocol.TType.DOUBLE, (short)10);
   private static final org.apache.storm.thrift.protocol.TField FRAGMENTED_CPU_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("fragmented_cpu", org.apache.storm.thrift.protocol.TType.DOUBLE, (short)11);
+  private static final org.apache.storm.thrift.protocol.TField BLACKLISTED_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("blacklisted", org.apache.storm.thrift.protocol.TType.BOOL, (short)12);
 
   private static final org.apache.storm.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new SupervisorSummaryStandardSchemeFactory();
   private static final org.apache.storm.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new SupervisorSummaryTupleSchemeFactory();
@@ -54,6 +55,7 @@
   private double used_cpu; // optional
   private double fragmented_mem; // optional
   private double fragmented_cpu; // optional
+  private boolean blacklisted; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.storm.thrift.TFieldIdEnum {
@@ -67,7 +69,8 @@
     USED_MEM((short)8, "used_mem"),
     USED_CPU((short)9, "used_cpu"),
     FRAGMENTED_MEM((short)10, "fragmented_mem"),
-    FRAGMENTED_CPU((short)11, "fragmented_cpu");
+    FRAGMENTED_CPU((short)11, "fragmented_cpu"),
+    BLACKLISTED((short)12, "blacklisted");
 
     private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();
 
@@ -105,6 +108,8 @@
           return FRAGMENTED_MEM;
         case 11: // FRAGMENTED_CPU
           return FRAGMENTED_CPU;
+        case 12: // BLACKLISTED
+          return BLACKLISTED;
         default:
           return null;
       }
@@ -153,8 +158,9 @@
   private static final int __USED_CPU_ISSET_ID = 4;
   private static final int __FRAGMENTED_MEM_ISSET_ID = 5;
   private static final int __FRAGMENTED_CPU_ISSET_ID = 6;
+  private static final int __BLACKLISTED_ISSET_ID = 7;
   private byte __isset_bitfield = 0;
-  private static final _Fields optionals[] = {_Fields.VERSION,_Fields.TOTAL_RESOURCES,_Fields.USED_MEM,_Fields.USED_CPU,_Fields.FRAGMENTED_MEM,_Fields.FRAGMENTED_CPU};
+  private static final _Fields optionals[] = {_Fields.VERSION,_Fields.TOTAL_RESOURCES,_Fields.USED_MEM,_Fields.USED_CPU,_Fields.FRAGMENTED_MEM,_Fields.FRAGMENTED_CPU,_Fields.BLACKLISTED};
   public static final java.util.Map<_Fields, org.apache.storm.thrift.meta_data.FieldMetaData> metaDataMap;
   static {
     java.util.Map<_Fields, org.apache.storm.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.storm.thrift.meta_data.FieldMetaData>(_Fields.class);
@@ -182,6 +188,8 @@
         new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.DOUBLE)));
     tmpMap.put(_Fields.FRAGMENTED_CPU, new org.apache.storm.thrift.meta_data.FieldMetaData("fragmented_cpu", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.DOUBLE)));
+    tmpMap.put(_Fields.BLACKLISTED, new org.apache.storm.thrift.meta_data.FieldMetaData("blacklisted", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.BOOL)));
     metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
     org.apache.storm.thrift.meta_data.FieldMetaData.addStructMetaDataMap(SupervisorSummary.class, metaDataMap);
   }
@@ -234,6 +242,7 @@
     this.used_cpu = other.used_cpu;
     this.fragmented_mem = other.fragmented_mem;
     this.fragmented_cpu = other.fragmented_cpu;
+    this.blacklisted = other.blacklisted;
   }
 
   public SupervisorSummary deepCopy() {
@@ -261,6 +270,8 @@
     this.fragmented_mem = 0.0;
     set_fragmented_cpu_isSet(false);
     this.fragmented_cpu = 0.0;
+    set_blacklisted_isSet(false);
+    this.blacklisted = false;
   }
 
   @org.apache.storm.thrift.annotation.Nullable
@@ -524,6 +535,28 @@
     __isset_bitfield = org.apache.storm.thrift.EncodingUtils.setBit(__isset_bitfield, __FRAGMENTED_CPU_ISSET_ID, value);
   }
 
+  public boolean is_blacklisted() {
+    return this.blacklisted;
+  }
+
+  public void set_blacklisted(boolean blacklisted) {
+    this.blacklisted = blacklisted;
+    set_blacklisted_isSet(true);
+  }
+
+  public void unset_blacklisted() {
+    __isset_bitfield = org.apache.storm.thrift.EncodingUtils.clearBit(__isset_bitfield, __BLACKLISTED_ISSET_ID);
+  }
+
+  /** Returns true if field blacklisted is set (has been assigned a value) and false otherwise */
+  public boolean is_set_blacklisted() {
+    return org.apache.storm.thrift.EncodingUtils.testBit(__isset_bitfield, __BLACKLISTED_ISSET_ID);
+  }
+
+  public void set_blacklisted_isSet(boolean value) {
+    __isset_bitfield = org.apache.storm.thrift.EncodingUtils.setBit(__isset_bitfield, __BLACKLISTED_ISSET_ID, value);
+  }
+
   public void setFieldValue(_Fields field, @org.apache.storm.thrift.annotation.Nullable java.lang.Object value) {
     switch (field) {
     case HOST:
@@ -614,6 +647,14 @@
       }
       break;
 
+    case BLACKLISTED:
+      if (value == null) {
+        unset_blacklisted();
+      } else {
+        set_blacklisted((java.lang.Boolean)value);
+      }
+      break;
+
     }
   }
 
@@ -653,6 +694,9 @@
     case FRAGMENTED_CPU:
       return get_fragmented_cpu();
 
+    case BLACKLISTED:
+      return is_blacklisted();
+
     }
     throw new java.lang.IllegalStateException();
   }
@@ -686,6 +730,8 @@
       return is_set_fragmented_mem();
     case FRAGMENTED_CPU:
       return is_set_fragmented_cpu();
+    case BLACKLISTED:
+      return is_set_blacklisted();
     }
     throw new java.lang.IllegalStateException();
   }
@@ -804,6 +850,15 @@
         return false;
     }
 
+    boolean this_present_blacklisted = true && this.is_set_blacklisted();
+    boolean that_present_blacklisted = true && that.is_set_blacklisted();
+    if (this_present_blacklisted || that_present_blacklisted) {
+      if (!(this_present_blacklisted && that_present_blacklisted))
+        return false;
+      if (this.blacklisted != that.blacklisted)
+        return false;
+    }
+
     return true;
   }
 
@@ -849,6 +904,10 @@
     if (is_set_fragmented_cpu())
       hashCode = hashCode * 8191 + org.apache.storm.thrift.TBaseHelper.hashCode(fragmented_cpu);
 
+    hashCode = hashCode * 8191 + ((is_set_blacklisted()) ? 131071 : 524287);
+    if (is_set_blacklisted())
+      hashCode = hashCode * 8191 + ((blacklisted) ? 131071 : 524287);
+
     return hashCode;
   }
 
@@ -970,6 +1029,16 @@
         return lastComparison;
       }
     }
+    lastComparison = java.lang.Boolean.valueOf(is_set_blacklisted()).compareTo(other.is_set_blacklisted());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (is_set_blacklisted()) {
+      lastComparison = org.apache.storm.thrift.TBaseHelper.compareTo(this.blacklisted, other.blacklisted);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     return 0;
   }
 
@@ -1062,6 +1131,12 @@
       sb.append(this.fragmented_cpu);
       first = false;
     }
+    if (is_set_blacklisted()) {
+      if (!first) sb.append(", ");
+      sb.append("blacklisted:");
+      sb.append(this.blacklisted);
+      first = false;
+    }
     sb.append(")");
     return sb.toString();
   }
@@ -1227,6 +1302,14 @@
               org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
+          case 12: // BLACKLISTED
+            if (schemeField.type == org.apache.storm.thrift.protocol.TType.BOOL) {
+              struct.blacklisted = iprot.readBool();
+              struct.set_blacklisted_isSet(true);
+            } else { 
+              org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
           default:
             org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
         }
@@ -1301,6 +1384,11 @@
         oprot.writeDouble(struct.fragmented_cpu);
         oprot.writeFieldEnd();
       }
+      if (struct.is_set_blacklisted()) {
+        oprot.writeFieldBegin(BLACKLISTED_FIELD_DESC);
+        oprot.writeBool(struct.blacklisted);
+        oprot.writeFieldEnd();
+      }
       oprot.writeFieldStop();
       oprot.writeStructEnd();
     }
@@ -1342,7 +1430,10 @@
       if (struct.is_set_fragmented_cpu()) {
         optionals.set(5);
       }
-      oprot.writeBitSet(optionals, 6);
+      if (struct.is_set_blacklisted()) {
+        optionals.set(6);
+      }
+      oprot.writeBitSet(optionals, 7);
       if (struct.is_set_version()) {
         oprot.writeString(struct.version);
       }
@@ -1368,6 +1459,9 @@
       if (struct.is_set_fragmented_cpu()) {
         oprot.writeDouble(struct.fragmented_cpu);
       }
+      if (struct.is_set_blacklisted()) {
+        oprot.writeBool(struct.blacklisted);
+      }
     }
 
     @Override
@@ -1383,7 +1477,7 @@
       struct.set_num_used_workers_isSet(true);
       struct.supervisor_id = iprot.readString();
       struct.set_supervisor_id_isSet(true);
-      java.util.BitSet incoming = iprot.readBitSet(6);
+      java.util.BitSet incoming = iprot.readBitSet(7);
       if (incoming.get(0)) {
         struct.version = iprot.readString();
         struct.set_version_isSet(true);
@@ -1419,6 +1513,10 @@
         struct.fragmented_cpu = iprot.readDouble();
         struct.set_fragmented_cpu_isSet(true);
       }
+      if (incoming.get(6)) {
+        struct.blacklisted = iprot.readBool();
+        struct.set_blacklisted_isSet(true);
+      }
     }
   }
 
diff --git a/storm-client/src/py/storm/ttypes.py b/storm-client/src/py/storm/ttypes.py
index 4fae416..166e604 100644
--- a/storm-client/src/py/storm/ttypes.py
+++ b/storm-client/src/py/storm/ttypes.py
@@ -2335,11 +2335,12 @@
      - used_cpu
      - fragmented_mem
      - fragmented_cpu
+     - blacklisted
 
     """
 
 
-    def __init__(self, host=None, uptime_secs=None, num_workers=None, num_used_workers=None, supervisor_id=None, version="VERSION_NOT_PROVIDED", total_resources=None, used_mem=None, used_cpu=None, fragmented_mem=None, fragmented_cpu=None,):
+    def __init__(self, host=None, uptime_secs=None, num_workers=None, num_used_workers=None, supervisor_id=None, version="VERSION_NOT_PROVIDED", total_resources=None, used_mem=None, used_cpu=None, fragmented_mem=None, fragmented_cpu=None, blacklisted=None,):
         self.host = host
         self.uptime_secs = uptime_secs
         self.num_workers = num_workers
@@ -2351,6 +2352,7 @@
         self.used_cpu = used_cpu
         self.fragmented_mem = fragmented_mem
         self.fragmented_cpu = fragmented_cpu
+        self.blacklisted = blacklisted
 
     def read(self, iprot):
         if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
@@ -2422,6 +2424,11 @@
                     self.fragmented_cpu = iprot.readDouble()
                 else:
                     iprot.skip(ftype)
+            elif fid == 12:
+                if ftype == TType.BOOL:
+                    self.blacklisted = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
             else:
                 iprot.skip(ftype)
             iprot.readFieldEnd()
@@ -2480,6 +2487,10 @@
             oprot.writeFieldBegin('fragmented_cpu', TType.DOUBLE, 11)
             oprot.writeDouble(self.fragmented_cpu)
             oprot.writeFieldEnd()
+        if self.blacklisted is not None:
+            oprot.writeFieldBegin('blacklisted', TType.BOOL, 12)
+            oprot.writeBool(self.blacklisted)
+            oprot.writeFieldEnd()
         oprot.writeFieldStop()
         oprot.writeStructEnd()
 
@@ -10920,6 +10931,7 @@
     (9, TType.DOUBLE, 'used_cpu', None, None, ),  # 9
     (10, TType.DOUBLE, 'fragmented_mem', None, None, ),  # 10
     (11, TType.DOUBLE, 'fragmented_cpu', None, None, ),  # 11
+    (12, TType.BOOL, 'blacklisted', None, None, ),  # 12
 )
 all_structs.append(NimbusSummary)
 NimbusSummary.thrift_spec = (
diff --git a/storm-client/src/storm.thrift b/storm-client/src/storm.thrift
index e148500..401a69b 100644
--- a/storm-client/src/storm.thrift
+++ b/storm-client/src/storm.thrift
@@ -194,6 +194,7 @@
   9: optional double used_cpu;
   10: optional double fragmented_mem;
   11: optional double fragmented_cpu;
+  12: optional bool blacklisted;
 }
 
 struct NimbusSummary {
diff --git a/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java b/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
index 96d6c21..c030c64 100644
--- a/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
+++ b/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
@@ -2668,6 +2668,12 @@
     }
 
     private SupervisorSummary makeSupervisorSummary(String supervisorId, SupervisorInfo info) {
+        Set<String> blacklistedSupervisorIds = Collections.emptySet();
+        if (scheduler instanceof BlacklistScheduler) {
+            BlacklistScheduler bs = (BlacklistScheduler) scheduler;
+            blacklistedSupervisorIds = bs.getBlacklistSupervisorIds();
+        }
+
         LOG.debug("INFO: {} ID: {}", info, supervisorId);
         int numPorts = 0;
         if (info.is_set_meta()) {
@@ -2701,6 +2707,13 @@
         if (info.is_set_version()) {
             ret.set_version(info.get_version());
         }
+
+        if (blacklistedSupervisorIds.contains(supervisorId)) {
+            ret.set_blacklisted(true);
+        } else {
+            ret.set_blacklisted(false);
+        }
+
         return ret;
     }
 
diff --git a/storm-server/src/main/java/org/apache/storm/scheduler/blacklist/BlacklistScheduler.java b/storm-server/src/main/java/org/apache/storm/scheduler/blacklist/BlacklistScheduler.java
index 54c10f9..a2bedcb 100644
--- a/storm-server/src/main/java/org/apache/storm/scheduler/blacklist/BlacklistScheduler.java
+++ b/storm-server/src/main/java/org/apache/storm/scheduler/blacklist/BlacklistScheduler.java
@@ -13,6 +13,7 @@
 package org.apache.storm.scheduler.blacklist;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -53,7 +54,7 @@
     //key is supervisor key ,value is supervisor ports
     protected EvictingQueue<HashMap<String, Set<Integer>>> badSupervisorsToleranceSlidingWindow;
     protected int windowSize;
-    protected Set<String> blacklistHost;
+    protected volatile Set<String> blacklistedSupervisorIds;     // supervisor ids
     private Map<String, Object> conf;
 
     public BlacklistScheduler(IScheduler underlyingScheduler, StormMetricsRegistry metricsRegistry) {
@@ -88,10 +89,10 @@
         windowSize = toleranceTime / nimbusMonitorFreqSecs;
         badSupervisorsToleranceSlidingWindow = EvictingQueue.create(windowSize);
         cachedSupervisors = new HashMap<>();
-        blacklistHost = new HashSet<>();
+        blacklistedSupervisorIds = new HashSet<>();
 
         //nimbus:num-blacklisted-supervisor + non-blacklisted supervisor = nimbus:num-supervisors
-        metricsRegistry.registerGauge("nimbus:num-blacklisted-supervisor", () -> blacklistHost.size());
+        metricsRegistry.registerGauge("nimbus:num-blacklisted-supervisor", () -> blacklistedSupervisorIds.size());
     }
 
     @Override
@@ -110,8 +111,8 @@
         Map<String, SupervisorDetails> supervisors = cluster.getSupervisors();
         blacklistStrategy.resumeFromBlacklist();
         badSupervisors(supervisors);
-        Set<String> blacklistHosts = getBlacklistHosts(cluster, topologies);
-        this.blacklistHost = blacklistHosts;
+        blacklistedSupervisorIds = refreshBlacklistedSupervisorIds(cluster, topologies);
+        Set<String> blacklistHosts = getBlacklistHosts(cluster, blacklistedSupervisorIds);
         cluster.setBlacklistedHosts(blacklistHosts);
         removeLongTimeDisappearFromCache();
 
@@ -132,7 +133,6 @@
         for (String key : badSupervisorKeys) {
             badSupervisors.put(key, cachedSupervisors.get(key));
         }
-
         for (Map.Entry<String, SupervisorDetails> entry : supervisors.entrySet()) {
             String key = entry.getKey();
             SupervisorDetails supervisorDetails = entry.getValue();
@@ -165,11 +165,16 @@
         return badSlots;
     }
 
-    private Set<String> getBlacklistHosts(Cluster cluster, Topologies topologies) {
-        Set<String> blacklistSet = blacklistStrategy.getBlacklist(new ArrayList<>(badSupervisorsToleranceSlidingWindow),
-                                                                  cluster, topologies);
+    private Set<String> refreshBlacklistedSupervisorIds(Cluster cluster, Topologies topologies) {
+        Set<String> blacklistedSupervisors = blacklistStrategy.getBlacklist(new ArrayList<>(badSupervisorsToleranceSlidingWindow),
+                cluster, topologies);
+        LOG.info("Supervisors {} are blacklisted.", blacklistedSupervisors);
+        return blacklistedSupervisors;
+    }
+
+    private Set<String> getBlacklistHosts(Cluster cluster, Set<String> blacklistIds) {
         Set<String> blacklistHostSet = new HashSet<>();
-        for (String supervisor : blacklistSet) {
+        for (String supervisor : blacklistIds) {
             String host = cluster.getHost(supervisor);
             if (host != null) {
                 blacklistHostSet.add(host);
@@ -251,4 +256,8 @@
             throw e;
         }
     }
+
+    public Set<String> getBlacklistSupervisorIds() {
+        return Collections.unmodifiableSet(blacklistedSupervisorIds);
+    }
 }
\ No newline at end of file
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/UIHelpers.java b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/UIHelpers.java
index 3f4595c..c4113f7 100644
--- a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/UIHelpers.java
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/UIHelpers.java
@@ -880,6 +880,7 @@
         result.put("id", supervisorSummary.get_supervisor_id());
         result.put("host", supervisorSummary.get_host());
         result.put("uptime", UIHelpers.prettyUptimeSec(supervisorSummary.get_uptime_secs()));
+        result.put("blacklisted", supervisorSummary.is_blacklisted());
         result.put("uptimeSeconds", supervisorSummary.get_uptime_secs());
         result.put("slotsTotal", supervisorSummary.get_num_workers());
         result.put("slotsUsed", supervisorSummary.get_num_used_workers());
@@ -1022,7 +1023,7 @@
      */
     private static List<Map> getSupervisorsMap(List<SupervisorSummary> supervisors,
                                                Map<String, Object> config) {
-        List<Map> supervisorMaps = new ArrayList();
+        List<Map> supervisorMaps = new ArrayList<>();
         for (SupervisorSummary supervisorSummary : supervisors) {
             supervisorMaps.add(getPrettifiedSupervisorMap(supervisorSummary, config));
         }
@@ -1051,7 +1052,7 @@
      */
     public static Map<String, Object> getSupervisorPageInfo(
             SupervisorPageInfo supervisorPageInfo, Map<String,Object> config) {
-        Map<String, Object> result = new HashMap();
+        Map<String, Object> result = new HashMap<>();
         result.put("workers", getWorkerSummaries(supervisorPageInfo, config));
         result.put("schedulerDisplayResource", config.get(DaemonConfig.SCHEDULER_DISPLAY_RESOURCE));
         List<Map> supervisorMaps = getSupervisorsMap(supervisorPageInfo.get_supervisor_summaries(), config);
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html
index 027333b..a60e578 100644
--- a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/index-page-template.html
@@ -419,6 +419,11 @@
           Version
         </span>
       </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="top" title="Whether this supervisor is blacklisted or not">
+          Blacklisted
+        </span>
+      </th>
     </tr>
   </thead>
   <tbody>
@@ -441,6 +446,7 @@
       <td>{{availCpu}}</td>
       {{/schedulerDisplayResource}}
       <td>{{version}}</td>
+      <td>{{blacklisted}}</td>
     </tr>
     {{/supervisors}}
   </tbody>
diff --git a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html
index 43866c6..3475f12 100644
--- a/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html
+++ b/storm-webapp/src/main/java/org/apache/storm/daemon/ui/WEB-INF/templates/supervisor-page-template.html
@@ -82,13 +82,18 @@
               Version
             </span>
           </th>
+          <th>
+            <span data-toggle="tooltip" data-placement="top" title="Whether this supervisor is blacklisted or not">
+              Blacklisted
+            </span>
+          </th>
         </tr>
       </thead>
       <tbody>
       {{#supervisors}}
           <tr>
-            <td><a href="/supervisor.html?host={{host}}">{{host}} (<a href="{{logLink}}" title="View log">log</a>)</a></td>
-            <td><a href="/supervisor.html?id={{id}}">{{id}}</td>
+            <td><a href="/supervisor.html?host={{host}}">{{host}}</a> (<a href="{{logLink}}" title="View log">log</a>)</td>
+            <td><a href="/supervisor.html?id={{id}}">{{id}}</a></td>
             <td>{{uptime}}</td>
             <td>{{slotsTotal}}</td>
             <td>{{slotsUsed}}</td>
@@ -103,6 +108,7 @@
             <td>{{availCpu}}</td>
             {{/schedulerDisplayResource}}
             <td>{{version}}</td>
+            <td>{{blacklisted}}</td>
           </tr>
       {{/supervisors}}
       </tbody>