#1551 cluster health info page
Merged 2 years ago by tkopecek. Opened 2 years ago by tkopecek.
tkopecek/koji issue1550  into  master

@@ -0,0 +1,82 @@ 

+ #from kojiweb import util

+ 

+ #def printOption(value, label=None)

+ #if not $label

+ #set $label = $value

+ #end if

+ <option value="$value"#if $value == $arch then ' selected="selected"' else ''#>$label</option>

+ #end def

+ 

+ #include "includes/header.chtml"

+ <style>

+   span {

+     display: inline-block;

+     box-sizing: border-box;

+     height: 100%;

+     float: left;

+     padding: 0px;

+     text-overflow: ellipsis;

+   }

+   .graph {

+       height: 15px;

+   }

+ 

+   .free {

+     background: #00ff00;

+                 text-align: right;

+   }

+ 

+   .busy {

+     background: #ff0000;

+   }

+ 

+   .count {

+     background: #0000ff;

+     color: #ffffff;

+   }

+ </style>

+ 

+   <h4>Cluster health</h4>

+   <table class="data-list">

+     <tr style="text-align: left">

+       <td colspan="3">

+         <form action="">

+           Architecture:

+           <select onchange="javascript: window.location = 'clusterhealth?arch=' + this.value + '$util.passthrough($self, 'order')';">

+             $printOption('__all__', 'all')

+             #for $arch in $arches

+             $printOption($arch)

+             #end for

+           </select>

+         </form>

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th>Channel</th>

+       <th>Load/Capacity</th>

+       <th>Builder readiness</th>

+     </tr>

+     #for $channel in $channels

+     <tr>

+       <th>

+           <a href="channelinfo?channelID=$channel['id']">$channel['name']</a>

+       </th>

+       <td width="$graphWidth" class="graph">

+         #if $channel['capacityPerc']

+         <span style="width: $channel['capacityPerc']%">

+           <span style="width: #echo $channel['perc_load']#%" class="busy" title="Load: #echo int($channel['load'])#"></span>

+           <span style="width: #echo 100 - $channel['perc_load']#%" class="free" title="Free capacity: #echo int($channel['capacity'] - $channel['load'])#">#echo int(100 - $channel['perc_load'])#%&nbsp;</span>

+         </span>

+         #end if

+       </td>

+       <td width="$graphWidth" class="graph">

+         <span style="width: #echo $channel['enabledPerc']#%">

+           <span style="width: #echo 100 - $channel['perc_ready']#%" class="busy" title="Busy builders: #echo $channel['enabled'] - $channel['ready']#"></span>

+           <span style="width: #echo $channel['perc_ready']#%" class="free" title="Ready builders: $channel['ready']"">#echo int($channel['ready'])#&nbsp;</span>

+         </span>

+       </td>

+     </tr>

+     #end for

+   </table>

+ 

+ #include "includes/footer.chtml"

file modified
+56
@@ -2134,6 +2134,62 @@ 

  

      return _genHTML(environ, 'buildsbytarget.chtml')

  

+ def _filter_hosts_by_arch(hosts, arch):

+     if arch == '__all__':

+         return hosts

+     else:

+         return [h for h in hosts if arch in h['arches'].split()]

+ 

+ def clusterhealth(environ, arch='__all__'):

+     values = _initValues(environ, 'Cluster health', 'reports')

+     server = _getServer(environ)

+     channels = server.listChannels()

+     server.multicall = True

+     for channel in channels:

+         server.listHosts(channelID=channel['id'])

+     max_enabled = 0

+     max_capacity = 0

+     arches = set()

+     for channel, [hosts] in zip(channels, server.multiCall()):

+         for host in hosts:

+             arches |= set(host['arches'].split())

+         hosts = _filter_hosts_by_arch(hosts, arch)

+         channel['enabled'] = len([x for x in hosts if x['enabled']])

+         channel['disabled'] = len(hosts) - channel['enabled']

+         channel['ready'] = len([x for x in hosts if x['ready']])

+         channel['capacity'] = sum([x['capacity'] for x in hosts])

+         channel['load'] = sum([x['task_load'] for x in hosts])

+         if max_enabled < channel['enabled']:

+             max_enabled = channel['enabled']

+         if max_capacity < channel['capacity']:

+             max_capacity = channel['capacity']

+ 

+     graphWidth = 400.0

+     # compute values for channels

+     for channel in channels:

+         try:

+             channel['capacityPerc'] = channel['capacity'] / max_capacity * 100

+         except ZeroDivisionError:

+             channel['capacityPerc'] = 0

+         try:

+             channel['enabledPerc'] = channel['enabled'] / max_enabled * 100

+         except ZeroDivisionError:

+             channel['enabledPerc'] = 0

+         if channel['capacity']:

+             channel['perc_load'] = min(100, channel['load'] / channel['capacity'] * 100)

+         else:

+             channel['perc_load'] = 0.0

+         if channel['enabled']:

+             channel['perc_ready'] = min(100, channel['ready'] / channel['enabled'] * 100)

+         else:

+             channel['perc_ready'] = 0.0

+ 

+     values['arch'] = arch

+     values['arches'] = sorted(arches)

+     values['graphWidth'] = graphWidth

+     values['channels'] = sorted(channels, key=lambda x: x['name'])

+     return _genHTML(environ, 'clusterhealth.chtml')

+ 

  def recentbuilds(environ, user=None, tag=None, package=None):

      values = _initValues(environ, 'Recent Build RSS')

      server = _getServer(environ)

@@ -12,6 +12,7 @@ 

      <li><a href="tasksbyhost">Tasks completed by each host</a></li>

      <li><a href="buildsbystatus">Succeeded/failed/canceled builds</a></li>

      <li><a href="buildsbytarget">Number of builds in each target</a></li>

+     <li><a href="clusterhealth">Cluster health</a></li>

    </ul>

  

  #include "includes/footer.chtml"