Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/01/15 14:59:47 (9 years ago)
Author:
ascheibe
Message:

#2394 merged r12428, r12429, r12430, r12435, r12442, r12443, r12445, r12514, r12517, r12519, r12520, r12521, r12523, r12532, r12542, r12546, r12552, r12553, r12556, r12557, r12559, r12561, r12146, r12457 into stable

Location:
stable
Files:
13 edited
1 copied

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Services.WebApp.Status/3.3/HeuristicLab.Services.WebApp.Status-3.3.csproj

    r12428 r12563  
    7373  </PropertyGroup>
    7474  <ItemGroup>
    75     <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
    76       <HintPath>..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
    77       <Private>False</Private>
     75    <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
     76      <SpecificVersion>False</SpecificVersion>
     77      <HintPath>..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
    7878    </Reference>
    7979    <Reference Include="System" />
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataController.cs

    r12428 r12563  
    1 using System;
     1#region License Information
     2/* HeuristicLab
     3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     4 *
     5 * This file is part of HeuristicLab.
     6 *
     7 * HeuristicLab is free software: you can redistribute it and/or modify
     8 * it under the terms of the GNU General Public License as published by
     9 * the Free Software Foundation, either version 3 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * HeuristicLab is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     19 */
     20#endregion
     21
     22using System;
    223using System.Collections.Generic;
     24using System.Data.Linq;
    325using System.Linq;
    426using System.Web.Http;
     
    2547        FROM UserTasks ut;";
    2648
    27 
    2849    private class UserTaskStatus {
    2950      public Guid UserId { get; set; }
     
    4162        CalculatingTasks = uts.CalculatingTasks,
    4263        WaitingTasks = uts.WaitingTasks
    43       });
     64      }).OrderBy(x => x.User.Name);
    4465    }
    4566    // end temporary quickfix
     
    5071                            where slave.SlaveState == SlaveState.Calculating || slave.SlaveState == SlaveState.Idle
    5172                            select slave).ToList();
     73        var activeSlaves = onlineSlaves.Where(s => s.IsAllowedToCalculate).ToList();
     74        var calculatingSlaves = activeSlaves.Where(s => s.SlaveState == SlaveState.Calculating).ToList();
     75        int calculatingMemory = calculatingSlaves.Any() ? (int)calculatingSlaves.Sum(s => s.Memory) : 0;
     76        int freeCalculatingMemory = calculatingSlaves.Any() ? (int)calculatingSlaves.Sum(s => s.FreeMemory) : 0;
     77
    5278        return new DTO.Status {
    5379          CoreStatus = new DTO.CoreStatus {
    5480            TotalCores = onlineSlaves.Sum(s => s.Cores ?? 0),
    55             AvailableCores = onlineSlaves.Where(s => s.IsAllowedToCalculate).Sum(s => s.Cores ?? 0),
    56             FreeCores = onlineSlaves.Sum(s => s.FreeCores ?? 0)
     81            FreeCores = onlineSlaves.Sum(s => s.FreeCores ?? 0), // temporary for old chart data
     82            ActiveCores = activeSlaves.Sum(s => s.Cores ?? 0),
     83            CalculatingCores = calculatingSlaves.Sum(s => s.Cores ?? 0) - calculatingSlaves.Sum(s => s.FreeCores ?? 0)
    5784          },
    5885          CpuUtilizationStatus = new DTO.CpuUtilizationStatus {
     
    6087                                  ? Math.Round(onlineSlaves.Average(s => s.CpuUtilization), 2)
    6188                                  : 0.0,
    62             UsedCpuUtilization = onlineSlaves.Any(x => x.IsAllowedToCalculate)
    63                                  ? Math.Round(onlineSlaves.Where(x => x.IsAllowedToCalculate).Average(s => s.CpuUtilization), 2)
    64                                  : 0.0
     89            ActiveCpuUtilization = activeSlaves.Any()
     90                                   ? Math.Round(activeSlaves.Average(s => s.CpuUtilization), 2)
     91                                   : 0.0,
     92            CalculatingCpuUtilization = calculatingSlaves.Any()
     93                                        ? Math.Round(calculatingSlaves.Average(s => s.CpuUtilization), 2)
     94                                        : 0.0
    6595          },
    6696          MemoryStatus = new DTO.MemoryStatus {
    67             TotalMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.Memory) / 1024 : 0,
    68             FreeMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.FreeMemory) / 1024 : 0
     97            TotalMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.Memory) : 0,
     98            FreeMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.FreeMemory) : 0,
     99            ActiveMemory = activeSlaves.Any() ? (int)activeSlaves.Sum(s => s.Memory) : 0,
     100            UsedMemory = calculatingMemory - freeCalculatingMemory
    69101          },
    70102          TasksStatus = GetTaskStatus(db),
    71           SlavesCpuStatus = onlineSlaves.Select(x => new DTO.SlaveCpuStatus {
    72             CpuUtilization = Math.Round(x.CpuUtilization, 2),
     103          SlavesStatus = onlineSlaves.Select(x => new DTO.SlaveStatus {
    73104            Slave = new DTO.Slave {
    74105              Id = x.ResourceId.ToString(),
    75106              Name = x.Name
    76             }
    77           }),
     107            },
     108            CpuUtilization = x.CpuUtilization,
     109            Cores = x.Cores ?? 0,
     110            FreeCores = x.FreeCores ?? 0,
     111            Memory = x.Memory ?? 0,
     112            FreeMemory = x.FreeMemory ?? 0,
     113            IsAllowedToCalculate = x.IsAllowedToCalculate,
     114            State = x.SlaveState.ToString()
     115          }).OrderBy(x => x.Slave.Name),
    78116          Timestamp = JavascriptUtils.ToTimestamp(DateTime.Now)
    79117        };
     
    82120
    83121    public IEnumerable<DTO.Status> GetStatusHistory(DateTime start, DateTime end) {
     122      TimeSpan ts = end - start;
     123      int increment = 1;
     124      double totalMinutes = ts.TotalMinutes;
     125      while (totalMinutes > 5761) {
     126        totalMinutes -= 5761;
     127        increment += 5;
     128      }
    84129      using (var db = new HiveDataContext()) {
     130        DataLoadOptions loadOptions = new DataLoadOptions();
     131        loadOptions.LoadWith<Statistics>(o => o.SlaveStatistics);
     132        db.LoadOptions = loadOptions;
     133        db.DeferredLoadingEnabled = false;
    85134        var statistics = db.Statistics.Where(s => s.Timestamp >= start && s.Timestamp <= end)
    86                                       .OrderBy(x => x.Timestamp)
     135                                      .OrderBy(s => s.Timestamp)
    87136                                      .ToList();
     137        var status = new DTO.Status {
     138          CoreStatus = new DTO.CoreStatus(),
     139          CpuUtilizationStatus = new DTO.CpuUtilizationStatus(),
     140          MemoryStatus = new DTO.MemoryStatus()
     141        };
     142        int freeCores = 0;
     143        int freeMemory = 0;
     144        int i = 1;
    88145        foreach (var statistic in statistics) {
    89           yield return new DTO.Status {
    90             CoreStatus = new DTO.CoreStatus {
    91               TotalCores = statistic.SlaveStatistics.Sum(x => x.Cores),
    92               AvailableCores = 0,
    93               FreeCores = statistic.SlaveStatistics.Sum(x => x.FreeCores)
    94             },
    95             CpuUtilizationStatus = new DTO.CpuUtilizationStatus {
    96               TotalCpuUtilization = 0.0,
    97               UsedCpuUtilization = statistic.SlaveStatistics.Any() ? statistic.SlaveStatistics.Average(x => x.CpuUtilization) : 0.0
    98             },
    99             MemoryStatus = new DTO.MemoryStatus {
    100               TotalMemory = statistic.SlaveStatistics.Sum(x => x.Memory) / 1024,
    101               FreeMemory = statistic.SlaveStatistics.Sum(x => x.FreeMemory) / 1024
    102             },
    103             Timestamp = JavascriptUtils.ToTimestamp(statistic.Timestamp)
    104           };
     146          status.CoreStatus.TotalCores += statistic.SlaveStatistics.Sum(x => x.Cores);
     147          freeCores += statistic.SlaveStatistics.Sum(x => x.FreeCores);
     148          status.CpuUtilizationStatus.TotalCpuUtilization += statistic.SlaveStatistics.Any()
     149                                                             ? statistic.SlaveStatistics.Average(x => x.CpuUtilization)
     150                                                             : 0.0;
     151          status.MemoryStatus.TotalMemory += statistic.SlaveStatistics.Sum(x => x.Memory);
     152          freeMemory += statistic.SlaveStatistics.Sum(x => x.FreeMemory);
     153          if (i >= increment) {
     154            status.Timestamp = JavascriptUtils.ToTimestamp(statistic.Timestamp);
     155            status.CoreStatus.TotalCores /= i;
     156            freeCores /= i;
     157            status.CpuUtilizationStatus.TotalCpuUtilization /= i;
     158            status.MemoryStatus.TotalMemory /= i;
     159            freeMemory /= i;
     160            status.CoreStatus.ActiveCores = status.CoreStatus.TotalCores;
     161            status.MemoryStatus.ActiveMemory = status.MemoryStatus.TotalMemory;
     162            status.CpuUtilizationStatus.ActiveCpuUtilization = status.CpuUtilizationStatus.TotalCpuUtilization;
     163            status.CpuUtilizationStatus.CalculatingCpuUtilization = status.CpuUtilizationStatus.CalculatingCpuUtilization;
     164            status.CoreStatus.CalculatingCores = status.CoreStatus.TotalCores - freeCores;
     165            status.MemoryStatus.UsedMemory = status.MemoryStatus.TotalMemory - freeMemory;
     166            yield return status;
     167            status = new DTO.Status {
     168              CoreStatus = new DTO.CoreStatus(),
     169              CpuUtilizationStatus = new DTO.CpuUtilizationStatus(),
     170              MemoryStatus = new DTO.MemoryStatus()
     171            };
     172            freeCores = 0;
     173            freeMemory = 0;
     174            i = 1;
     175          } else {
     176            i++;
     177          }
    105178        }
    106179      }
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataTransfer/Slave.cs

    r12428 r12563  
    1 namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer {
     1#region License Information
     2/* HeuristicLab
     3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     4 *
     5 * This file is part of HeuristicLab.
     6 *
     7 * HeuristicLab is free software: you can redistribute it and/or modify
     8 * it under the terms of the GNU General Public License as published by
     9 * the Free Software Foundation, either version 3 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * HeuristicLab is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     19 */
     20#endregion
     21
     22namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer {
    223  public class Slave {
    324    public string Id { get; set; } // currently unused
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataTransfer/Status.cs

    r12428 r12563  
    1 using System.Collections.Generic;
     1#region License Information
     2/* HeuristicLab
     3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     4 *
     5 * This file is part of HeuristicLab.
     6 *
     7 * HeuristicLab is free software: you can redistribute it and/or modify
     8 * it under the terms of the GNU General Public License as published by
     9 * the Free Software Foundation, either version 3 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * HeuristicLab is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     19 */
     20#endregion
     21
     22using System.Collections.Generic;
    223
    324namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer {
     
    526  public class CoreStatus {
    627    public int TotalCores { get; set; }
    7     public int AvailableCores { get; set; }
    8     public int FreeCores { get; set; }
     28    public int FreeCores { get; set; } // temporary quickfix for old chart data
     29    public int ActiveCores { get; set; }
     30    public int CalculatingCores { get; set; }
    931  }
    1032
    1133  public class CpuUtilizationStatus {
    1234    public double TotalCpuUtilization { get; set; }
    13     public double UsedCpuUtilization { get; set; }
     35    public double ActiveCpuUtilization { get; set; }
     36    public double CalculatingCpuUtilization { get; set; }
    1437  }
    1538
    1639  public class MemoryStatus {
    1740    public int TotalMemory { get; set; }
    18     public int FreeMemory { get; set; }
     41    public int FreeMemory { get; set; } // temporary quickfix for old chart data
     42    public int ActiveMemory { get; set; }
     43    public int UsedMemory { get; set; }
    1944  }
    2045
     
    2550  }
    2651
    27   public class SlaveCpuStatus {
     52  public class SlaveStatus {
    2853    public Slave Slave { get; set; }
    2954    public double CpuUtilization { get; set; }
     55    public int Cores { get; set; }
     56    public int FreeCores { get; set; }
     57    public int Memory { get; set; }
     58    public int FreeMemory { get; set; }
     59    public bool IsAllowedToCalculate { get; set; }
     60    public string State { get; set; }
    3061  }
    3162
     
    3566    public MemoryStatus MemoryStatus { get; set; }
    3667    public IEnumerable<TaskStatus> TasksStatus { get; set; }
    37     public IEnumerable<SlaveCpuStatus> SlavesCpuStatus { get; set; }
     68    public IEnumerable<SlaveStatus> SlavesStatus { get; set; }
    3869    public long Timestamp { get; set; }
    3970  }
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataTransfer/User.cs

    r12428 r12563  
    1 
     1#region License Information
     2/* HeuristicLab
     3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     4 *
     5 * This file is part of HeuristicLab.
     6 *
     7 * HeuristicLab is free software: you can redistribute it and/or modify
     8 * it under the terms of the GNU General Public License as published by
     9 * the Free Software Foundation, either version 3 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * HeuristicLab is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     19 */
     20#endregion
     21
    222namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer {
    323  public class User {
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApi/JavascriptUtils.cs

    r12428 r12563  
    1 using System;
     1#region License Information
     2/* HeuristicLab
     3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     4 *
     5 * This file is part of HeuristicLab.
     6 *
     7 * HeuristicLab is free software: you can redistribute it and/or modify
     8 * it under the terms of the GNU General Public License as published by
     9 * the Free Software Foundation, either version 3 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * HeuristicLab is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     19 */
     20#endregion
     21
     22using System;
    223
    324namespace HeuristicLab.Services.WebApp.Status.WebApi {
     
    627      var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    728      var time = input.Subtract(new TimeSpan(epoch.Ticks));
    8       return (long)(time.Ticks / 10000);
     29      return time.Ticks / 10000;
    930    }
    1031  }
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/history.cshtml

    r12428 r12563  
    1212<div id="history-header">
    1313    <form class="form-inline">
    14         <div class="form-group">
     14        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
    1515            <label for="fromDate">From:&nbsp;</label>
    1616            <div class="input-group">
     
    2121            </div>
    2222        </div>
    23         <div class="form-group">
    24             <label for="fromDate">&nbsp;&nbsp;To:&nbsp;</label>
     23        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
     24            <label for="fromDate">To:&nbsp;</label>
    2525            <div class="input-group">
    2626                <input id="fromDate" type="text" class="form-control" datepicker-popup="dd.MM.yyyy" ng-model="toDate" is-open="toIsOpen" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
     
    2929                </span>
    3030            </div>
     31        </div>
     32        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
     33            <button type="button" class="btn btn-default" ng-click="updateCharts()">
     34                Apply
     35            </button>
    3136        </div>
    3237    </form>
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/historyCtrl.js

    r12428 r12563  
    44        ['$scope', '$interval', 'app.status.data.service',
    55        function ($scope, $interval, dataService) {
    6 
    76            $scope.chartOptions = {
    87                grid: {
     
    1514                yaxis: {
    1615                    min: 0,
    17                     max: 100,
    18                     zoomRange: false,
    19                     panRange: false
     16                    max: 100
    2017                },
    2118                xaxis: {
    2219                    mode: "time",
    2320                    twelveHourClock: false
    24                 },
    25                 zoom: {
    26                     interactive: true
    27                 },
    28                 pan: {
    29                     interactive: true
    3021                }
    3122            };
     
    4334                    }
    4435                },
    45                 yaxis: {
    46                     zoomRange: false,
    47                     panRange: false
    48                 },
    4936                xaxis: {
    5037                    mode: "time",
    5138                    twelveHourClock: false
    52                 },
    53                 zoom: {
    54                     interactive: true
    55                 },
    56                 pan: {
    57                     interactive: true
    5839                }
    5940            };
     41
    6042
    6143            $scope.fromDate = new Date();
     
    8870            $scope.memorySeries = [[]];
    8971
    90             var updateCharts = function () {
    91                 dataService.getStatusHistory({start: ConvertFromDate($scope.fromDate), end: ConvertToDate($scope.toDate)}, function (status) {
     72            $scope.updateCharts = function () {
     73                dataService.getStatusHistory({ start: ConvertFromDate($scope.fromDate), end: ConvertToDate($scope.toDate) }, function (status) {
    9274                    var noOfStatus = status.length;
    9375                    var cpuSeries = [];
     
    9678                    for (var i = 0; i < noOfStatus; ++i) {
    9779                        var curStatus = status[i];
    98                         var cpuData = Math.round(curStatus.CpuUtilizationStatus.UsedCpuUtilization);
    99                         var usedCores = curStatus.CoreStatus.TotalCores - curStatus.CoreStatus.FreeCores;
    100                         var usedMemory = curStatus.MemoryStatus.TotalMemory - curStatus.MemoryStatus.FreeMemory;
     80                        var cpuData = Math.round(curStatus.CpuUtilizationStatus.ActiveCpuUtilization);
    10181                        cpuSeries.push([curStatus.Timestamp, cpuData]);
    102                         coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus.TotalCores]);
    103                         coreSeries[1].push([curStatus.Timestamp, usedCores]);
    104                         memorySeries[0].push([curStatus.Timestamp, curStatus.MemoryStatus.TotalMemory]);
    105                         memorySeries[1].push([curStatus.Timestamp, usedMemory]);
     82                        coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus.ActiveCores]);
     83                        coreSeries[1].push([curStatus.Timestamp, curStatus.CoreStatus.CalculatingCores]);
     84                        memorySeries[0].push([curStatus.Timestamp, Math.round(curStatus.MemoryStatus.ActiveMemory / 1024)]);
     85                        memorySeries[1].push([curStatus.Timestamp, Math.round(curStatus.MemoryStatus.UsedMemory / 1024)]);
    10686                    }
    10787                    $scope.cpuSeries = [{ data: cpuSeries, label: "&nbsp;CPU Utilization", color: "#f7921d" }];
     
    11797                });
    11898            };
    119 
    120             $scope.$watch('fromDate', function (newValue, oldValue) {
    121                 updateCharts();
    122             });
    123             $scope.$watch('toDate', function (newValue, oldValue) {
    124                 updateCharts();
    125             });
     99            $scope.updateCharts();
    126100        }]
    127101    );
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/status.cshtml

    r12428 r12563  
    1111
    1212<div class="default-view-container">
    13     <div class="row">
    14         <div class="col-lg-3 col-md-6">
    15             <div class="panel panel-default">
    16                 <div class="panel-heading">
    17                     <h3 class="panel-title">Cores</h3>
    18                 </div>
     13<div class="row">
     14    <div class="col-lg-3 col-md-6">
     15        <div class="panel panel-default">
     16            <div class="panel-heading">
     17                <h3 class="panel-title">Cores</h3>
     18            </div>
     19            <div class="panel-body">
     20                <div class="text-center">
     21                    <knob knob-data="core.knobData" knob-options="knobOptions"></knob>
     22                </div>
     23                <table class="table table-no-border table-condensed table-auto-width table-content">
     24                    <tr data-toggle="tooltip" data-placement="bottom" title="All online slaves">
     25                        <td class="text-left">
     26                            Total:
     27                        </td>
     28                        <td class="text-right">{{status.CoreStatus.TotalCores | number}}</td>
     29                    </tr>
     30                    <tr data-toggle="tooltip" data-placement="bottom" title="All calculating and idle slaves that are allowed to calculate">
     31                        <td class="text-left">Active:</td>
     32                        <td class="text-right">{{status.CoreStatus.ActiveCores | number}}</td>
     33                    </tr>
     34                    <tr data-toggle="tooltip" data-placement="bottom" title="All calculating slaves that are allowed to calculate">
     35                        <td class="text-left">Calculating:</td>
     36                        <td class="text-right">{{status.CoreStatus.CalculatingCores | number}}</td>
     37                    </tr>
     38                </table>
     39            </div>
     40        </div>
     41    </div>
     42
     43    <div class="col-lg-3 col-md-6">
     44        <div class="panel panel-default">
     45            <div class="panel-heading">
     46                <h3 class="panel-title">CPU Utilization</h3>
     47            </div>
     48            <div class="panel-body">
     49                <div class="text-center">
     50                    <knob knob-data="cpu.knobData" knob-options="knobOptions"></knob>
     51                </div>
     52                <table class="table table-no-border table-condensed table-auto-width table-content">
     53                    <tr data-toggle="tooltip" data-placement="bottom" title="All online slaves">
     54                        <td class="text-left">Total:</td>
     55                        <td class="text-right">{{status.CpuUtilizationStatus.TotalCpuUtilization | number: 2}} %</td>
     56                    </tr>
     57                    <tr data-toggle="tooltip" data-placement="bottom" title="All calculating and idle slaves that are allowed to calculate">
     58                        <td class="text-left">Active:</td>
     59                        <td class="text-right">{{status.CpuUtilizationStatus.ActiveCpuUtilization | number: 2}} %</td>
     60                    </tr>
     61                    <tr data-toggle="tooltip" data-placement="bottom" title="All calculating slaves that are allowed to calculate">
     62                        <td class="text-left">Calculating:</td>
     63                        <td class="text-right">{{status.CpuUtilizationStatus.CalculatingCpuUtilization | number: 2}} %</td>
     64                    </tr>
     65                </table>
     66            </div>
     67        </div>
     68    </div>
     69
     70    <div class="col-lg-3 col-md-6">
     71        <div class="panel panel-default">
     72            <div class="panel-heading">
     73                <h3 class="panel-title">Memory</h3>
     74            </div>
     75            <div class="panel-body">
     76                <div class="text-center">
     77                    <knob knob-data="memory.knobData" knob-options="knobOptions"></knob>
     78                </div>
     79                <table class="table table-no-border table-condensed table-auto-width table-content">
     80                    <tr data-toggle="tooltip" data-placement="bottom" title="All online slaves">
     81                        <td class="text-left">Total:</td>
     82                        <td class="text-right">{{status.MemoryStatus.TotalMemory | kbToGB}} GB</td>
     83                    </tr>
     84                    <tr data-toggle="tooltip" data-placement="bottom" title="All calculating and idle slaves that are allowed to calculate">
     85                        <td class="text-left">Active:</td>
     86                        <td class="text-right">{{status.MemoryStatus.ActiveMemory | kbToGB}} GB</td>
     87                    </tr>
     88                    <tr data-toggle="tooltip" data-placement="bottom" title="All calculating slaves that are allowed to calculate">
     89                        <td class="text-left">Calculating:</td>
     90                        <td class="text-right">{{status.MemoryStatus.UsedMemory | kbToGB}} GB</td>
     91                    </tr>
     92                </table>
     93            </div>
     94        </div>
     95    </div>
     96
     97    <div class="col-lg-3 col-md-6">
     98        <div class="panel panel-default">
     99            <div class="panel-heading">
     100                <h3 class="panel-title">Tasks</h3>
     101            </div>
     102            <div class="panel-body">
     103                <table class="table table-no-border table-condensed table-auto-width table-content">
     104                    <tr>
     105                        <td class="text-left">Total:</td>
     106                        <td class="text-right">{{tasks.WaitingTasks + tasks.CalculatingTasks | number}}</td>
     107                    </tr>
     108                    <tr>
     109                        <td class="text-left">Waiting:</td>
     110                        <td class="text-right">{{tasks.WaitingTasks | number}}</td>
     111                    </tr>
     112                    <tr>
     113                        <td class="text-left">Calculating:</td>
     114                        <td class="text-right">{{tasks.CalculatingTasks | number}}</td>
     115                    </tr>
     116                </table>
     117            </div>
     118        </div>
     119    </div>
     120</div>
     121
     122<div class="row">
     123    <div class="col-lg-12">
     124        <div class="panel panel-default">
     125            <div class="panel-heading">
     126                <h3 class="panel-title">CPU Utilization Chart</h3>
     127            </div>
     128            <div class="panel-body">
     129                <flot dataset="cpu.series" options="chartOptions"></flot>
     130            </div>
     131        </div>
     132    </div>
     133</div>
     134
     135<div class="row">
     136    <div class="col-lg-12">
     137        <div class="panel panel-default">
     138            <div class="panel-heading">
     139                <h3 class="panel-title">Core Chart</h3>
     140            </div>
     141            <div class="panel-body">
     142                <flot dataset="core.series" options="fillChartOptions"></flot>
     143            </div>
     144        </div>
     145    </div>
     146</div>
     147
     148<div class="row">
     149    <div class="col-lg-12">
     150        <div class="panel panel-default">
     151            <div class="panel-heading">
     152                <h3 class="panel-title">Memory Chart</h3>
     153            </div>
     154            <div class="panel-body">
     155                <flot dataset="memory.series" options="fillChartOptions"></flot>
     156            </div>
     157        </div>
     158    </div>
     159</div>
     160
     161<div class="row">
     162    <div class="col-lg-12">
     163        <div class="panel panel-default">
     164            <div class="panel-heading">
     165                <h3 class="panel-title">Tasks by User</h3>
     166            </div>
     167            <div class="panel-body">
     168                <table class="table table-hover" ts-wrapper>
     169                    <thead>
     170                        <tr>
     171                            <th ts-criteria="User.Name">Username</th>
     172                            <th ts-criteria="CalculatingTasks|parseInt">Calculating Tasks</th>
     173                            <th ts-criteria="WaitingTasks|parseInt">Waiting Tasks</th>
     174                        </tr>
     175                    </thead>
     176                    <tbody>
     177                        <tr ng-repeat="task in status.TasksStatus" ts-repeat>
     178                            <td>{{task.User.Name}}</td>
     179                            <td>{{task.CalculatingTasks | number}}</td>
     180                            <td>{{task.WaitingTasks | number}}</td>
     181                        </tr>
     182                        <tr ng-hide="status.TasksStatus.length">
     183                            <td colspan="3" class="text-center">
     184                                There are no waiting or calculating tasks available!
     185                            </td>
     186                        </tr>
     187                    </tbody>
     188                </table>
     189            </div>
     190        </div>
     191    </div>
     192</div>
     193
     194<div class="row">
     195    <div class="col-lg-12">
     196        <div class="panel panel-default">
     197            <div class="panel-heading">
     198                <h3 class="panel-title">
     199                    <a data-toggle="collapse" data-target="#collapseActiveCalculatingSlaves"
     200                       ng-href="#/status">
     201                        Active Calculating Slaves
     202                    </a>
     203                </h3>
     204            </div>
     205            <div id="collapseActiveCalculatingSlaves"
     206                 class="panel-collapse collapse in">
    19207                <div class="panel-body">
    20                     <center>
    21                         <knob knob-data="core.knobData" knob-options="knobOptions"></knob>
    22                     </center>
    23                     <p>Total Cores: {{status.CoreStatus.TotalCores}}</p>
    24                     <p>Used Cores: {{status.CoreStatus.TotalCores - status.CoreStatus.FreeCores}}</p>
    25                 </div>
    26             </div>
    27         </div>
    28 
    29         <div class="col-lg-3 col-md-6">
    30             <div class="panel panel-default">
    31                 <div class="panel-heading">
    32                     <h3 class="panel-title">CPU Utilization</h3>
    33                 </div>
    34                 <div class="panel-body">
    35                     <center>
    36                         <knob knob-data="cpu.knobData" knob-options="knobOptions"></knob>
    37                     </center>
    38                     <p>Total Utilization: {{status.CpuUtilizationStatus.TotalCpuUtilization}} %</p>
    39                     <p>Used Utilization: {{status.CpuUtilizationStatus.UsedCpuUtilization}} %</p>
    40                 </div>
    41             </div>
    42         </div>
    43 
    44         <div class="col-lg-3 col-md-6">
    45             <div class="panel panel-default">
    46                 <div class="panel-heading">
    47                     <h3 class="panel-title">Memory</h3>
    48                 </div>
    49                 <div class="panel-body">
    50                     <center>
    51                         <knob knob-data="memory.knobData" knob-options="knobOptions"></knob>
    52                     </center>
    53                     <p>TotalMemory: {{status.MemoryStatus.TotalMemory}} GB</p>
    54                     <p>UsedMemory: {{status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory}} GB</p>
    55                 </div>
    56             </div>
    57         </div>
    58 
    59         <div class="col-lg-3 col-md-6">
    60             <div class="panel panel-default">
    61                 <div class="panel-heading">
    62                     <h3 class="panel-title">Tasks</h3>
    63                 </div>
    64                 <div class="panel-body">
    65                     <p>Total: {{tasks.WaitingTasks + tasks.CalculatingTasks}}</p>
    66                     <p>Waiting: {{tasks.WaitingTasks}}</p>
    67                     <p>Calculating: {{tasks.CalculatingTasks}}</p>
    68                 </div>
    69             </div>
    70         </div>
    71     </div>
    72 
    73     <div class="row">
    74         <div class="col-lg-12">
    75             <div class="panel panel-default">
    76                 <div class="panel-heading">
    77                     <h3 class="panel-title">CPU Utilization Chart</h3>
    78                 </div>
    79                 <div class="panel-body">
    80                     <flot dataset="cpu.series" options="chartOptions"></flot>
    81                 </div>
    82             </div>
    83         </div>
    84     </div>
    85 
    86     <div class="row">
    87         <div class="col-lg-12">
    88             <div class="panel panel-default">
    89                 <div class="panel-heading">
    90                     <h3 class="panel-title">Core Chart</h3>
    91                 </div>
    92                 <div class="panel-body">
    93                     <flot dataset="core.series" options="fillChartOptions"></flot>
    94                 </div>
    95             </div>
    96         </div>
    97     </div>
    98 
    99     <div class="row">
    100         <div class="col-lg-12">
    101             <div class="panel panel-default">
    102                 <div class="panel-heading">
    103                     <h3 class="panel-title">Memory Chart</h3>
    104                 </div>
    105                 <div class="panel-body">
    106                     <flot dataset="memory.series" options="fillChartOptions"></flot>
    107                 </div>
    108             </div>
    109         </div>
    110     </div>
    111 
    112     <div class="row">
    113         <div class="col-lg-12">
    114             <div class="panel panel-default">
    115                 <div class="panel-heading">
    116                     <h3 class="panel-title">Tasks by User</h3>
    117                 </div>
    118                 <div class="panel-body">
    119                     <table class="table table-hover">
     208                    <table class="table table-hover" ts-wrapper>
    120209                        <thead>
    121210                            <tr>
    122                                 <th>Username</th>
    123                                 <th>Calculating Tasks</th>
    124                                 <th>Waiting Tasks</th>
     211                                <th ts-criteria="Slave.Name">Slave</th>
     212                                <th ts-criteria="CpuUtilization|parseFloat">CPU Utilization</th>
     213                                <th ts-criteria="Cores|parseInt">Cores</th>
     214                                <th ts-criteria="Memory|parseInt">Memory</th>
    125215                            </tr>
    126216                        </thead>
    127                         <tr ng-repeat="task in status.TasksStatus">
    128                             <td>{{task.User.Name}}</td>
    129                             <td>{{task.CalculatingTasks}}</td>
    130                             <td>{{task.WaitingTasks}}</td>
     217                        <tbody>
     218                            <tr ng-repeat="slave in activeCalculatingSlaves = (status.SlavesStatus
     219                                | filter: {
     220                                    IsAllowedToCalculate: true,
     221                                    State: 'Calculating'
     222                                  })" ts-repeat>
     223                                <td>{{slave.Slave.Name}}</td>
     224                                <td>{{slave.CpuUtilization | number: 2}} %</td>
     225                                <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
     226                                <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
     227                            </tr>
     228                            <tr ng-hide="activeCalculatingSlaves.length">
     229                                <td colspan="4" class="text-center">
     230                                    There are no active calculating slaves available!
     231                                </td>
     232                            </tr>
     233                        </tbody>
     234                    </table>
     235                </div>
     236            </div>
     237        </div>
     238    </div>
     239</div>
     240
     241<div class="row">
     242    <div class="col-lg-12">
     243        <div class="panel panel-default">
     244            <div class="panel-heading">
     245                <h3 class="panel-title">
     246                    <a data-toggle="collapse" data-target="#collapseActiveIdleSlaves"
     247                       ng-href="#/status" class="collapsed">
     248                        Active Idle Slaves
     249                    </a>
     250                </h3>
     251            </div>
     252            <div id="collapseActiveIdleSlaves"
     253                 class="panel-collapse collapse">
     254                <div class="panel-body">
     255                    <table class="table table-hover" ts-wrapper>
     256                        <thead>
     257                        <tr>
     258                            <th ts-criteria="Slave.Name">Slave</th>
     259                            <th ts-criteria="CpuUtilization|parseFloat">CPU Utilization</th>
     260                            <th ts-criteria="Cores|parseInt">Cores</th>
     261                            <th ts-criteria="Memory|parseInt">Memory</th>
    131262                        </tr>
     263                        </thead>
     264                        <tbody>
     265                            <tr ng-repeat="slave in activeIdleSlaves = (status.SlavesStatus
     266                                | filter: {
     267                                    IsAllowedToCalculate: true,
     268                                    State: 'Idle'
     269                                  })" ts-repeat>
     270                                <td>{{slave.Slave.Name}}</td>
     271                                <td>{{slave.CpuUtilization | number: 2}} %</td>
     272                                <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
     273                                <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
     274                            </tr>
     275                            <tr ng-hide="activeIdleSlaves.length">
     276                                <td colspan="4" class="text-center">
     277                                    There are no active idle slaves available!
     278                                <td>
     279                            </tr>
     280                        </tbody>
    132281                    </table>
    133282                </div>
     
    135284        </div>
    136285    </div>
    137 
    138     <div class="row">
    139         <div class="col-lg-12">
    140             <div class="panel panel-default">
    141                 <div class="panel-heading">
    142                     <h3 class="panel-title">CPU Utilization by Slave</h3>
    143                 </div>
     286</div>
     287
     288<div class="row">
     289    <div class="col-lg-12">
     290        <div class="panel panel-default">
     291            <div class="panel-heading">
     292                <h3 class="panel-title">
     293                    <a data-toggle="collapse" data-target="#collapseInactiveSlaves"
     294                       ng-href="#/status" class="collapsed">
     295                        Inactive Slaves
     296                    </a>
     297                </h3>
     298            </div>
     299            <div id="collapseInactiveSlaves"
     300                 class="panel-collapse collapse">
    144301                <div class="panel-body">
    145                     <table class="table table-hover">
     302                    <table class="table table-hover" ts-wrapper>
    146303                        <thead>
    147304                            <tr>
    148                                 <th>Slave</th>
    149                                 <th>CPU Utilization</th>
     305                                <th ts-criteria="Slave.Name">Slave</th>
     306                                <th ts-criteria="CpuUtilization|parseFloat">CPU Utilization</th>
     307                                <th ts-criteria="Cores|parseInt">Cores</th>
     308                                <th ts-criteria="Memory|parseInt">Memory</th>
    150309                            </tr>
    151310                        </thead>
    152                         <tr ng-repeat="slave in status.SlavesCpuStatus">
    153                             <td>{{slave.Slave.Name}}</td>
    154                             <td>{{slave.CpuUtilization}} %</td>
    155                         </tr>
     311                        <tbody>
     312                            <tr ng-repeat="slave in inactiveSlaves = (status.SlavesStatus
     313                                | filter: {
     314                                    IsAllowedToCalculate: false
     315                                  })" ts-repeat>
     316                                <td>{{slave.Slave.Name}}</td>
     317                                <td>{{slave.CpuUtilization | number: 2}} %</td>
     318                                <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
     319                                <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
     320                            </tr>
     321                            <tr ng-hide="inactiveSlaves.length">
     322                                <td colspan="4" class="text-center">No inactive slaves available!</td>
     323                            </tr>
     324                        </tbody>
    156325                    </table>
    157326                </div>
     
    160329    </div>
    161330</div>
     331</div>
     332
     333<script>
     334    $(document).ready(function () {
     335        $('[data-toggle="tooltip"]').tooltip();
     336    });
     337</script>
  • stable/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/statusCtrl.js

    r12428 r12563  
    5353                    mode: "time",
    5454                    twelveHourClock: false
     55                },
     56                yaxis: {
     57                    min: 0
    5558                }
    5659            };
     
    8588                // update status data
    8689                dataService.getStatus({}, function (status) {
     90                    var oneDayInMs = 24 * 60 * 60 * 1000;
     91                    var today = new Date().getTime() - oneDayInMs;
    8792                    // raw status data
    8893                    $scope.status = status;
     
    96101                    }
    97102                    // knobs
    98                     $scope.cpu.knobData = Math.round(status.CpuUtilizationStatus.UsedCpuUtilization);
    99                     var usedCores = status.CoreStatus.TotalCores - status.CoreStatus.FreeCores;
    100                     $scope.core.knobData = Math.round(usedCores / status.CoreStatus.TotalCores * 100);
    101                     var usedMemory = status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory;
    102                     $scope.memory.knobData = Math.round(usedMemory / status.MemoryStatus.TotalMemory * 100);
     103                    $scope.cpu.knobData = Math.round(status.CpuUtilizationStatus.ActiveCpuUtilization);
     104                    $scope.core.knobData = Math.round(status.CoreStatus.CalculatingCores / status.CoreStatus.ActiveCores * 100);
     105                    $scope.memory.knobData = Math.round(status.MemoryStatus.UsedMemory / status.MemoryStatus.ActiveMemory * 100);
    103106                    // chart series
    104107                    var cpuSeries = $scope.cpu.series[0].data.splice(0);
    105                     if (cpuSeries.length > 2) {
    106                         cpuSeries.splice(0, 1);
     108                    var coreSeries = [$scope.core.series[0].data, $scope.core.series[1].data];
     109                    var memorySeries = [$scope.memory.series[0].data, $scope.memory.series[1].data];
     110                    if ($scope.status.Timestamp < today) {
     111                        if (cpuSeries.length > 2) {
     112                            cpuSeries.splice(0, 1);
     113                        }
     114                        if (coreSeries[0].length > 2) {
     115                            coreSeries[0].splice(0, 1);
     116                        }
     117                        if (coreSeries[1].length > 2) {
     118                            coreSeries[1].splice(0, 1);
     119                        }
     120                        if (memorySeries[0].length > 2) {
     121                            memorySeries[0].splice(0, 1);
     122                        }
     123                        if (memorySeries[1].length > 2) {
     124                            memorySeries[1].splice(0, 1);
     125                        }
    107126                    }
    108                     var coreSeries = [$scope.core.series[0].data, $scope.core.series[1].data];
    109                     if (coreSeries[0].length > 2) {
    110                         coreSeries[0].splice(0, 1);
    111                     }
    112                     if (coreSeries[1].length > 2) {
    113                         coreSeries[1].splice(0, 1);
    114                     }
    115                     var memorySeries = [$scope.memory.series[0].data, $scope.memory.series[1].data];
    116                     if (memorySeries[0].length > 2) {
    117                         memorySeries[0].splice(0, 1);
    118                     }
    119                     if (memorySeries[1].length > 2) {
    120                         memorySeries[1].splice(0, 1);
    121                     }
    122                     cpuSeries.push([$scope.status.Timestamp, $scope.cpu.knobData]);
     127                   
     128                    cpuSeries.push([$scope.status.Timestamp, Math.round(status.CpuUtilizationStatus.TotalCpuUtilization)]);
     129                    // charts are currently filled with old total/used data
     130                    // start temporary
     131                    var usedCores = status.CoreStatus.TotalCores - status.CoreStatus.FreeCores;
     132                    var usedMemory = status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory;
     133                    // end temporary
    123134                    coreSeries[0].push([$scope.status.Timestamp, status.CoreStatus.TotalCores]);
    124135                    coreSeries[1].push([$scope.status.Timestamp, usedCores]);
    125                     memorySeries[0].push([$scope.status.Timestamp, status.MemoryStatus.TotalMemory]);
    126                     memorySeries[1].push([$scope.status.Timestamp, usedMemory]);
     136                    memorySeries[0].push([$scope.status.Timestamp, Math.round(status.MemoryStatus.TotalMemory / 1024)]);
     137                    memorySeries[1].push([$scope.status.Timestamp, Math.round(usedMemory / 1024)]);
    127138                    $scope.cpu.series = [{ data: cpuSeries, label: "&nbsp;CPU Utilization", color: "#f7921d" }];
    128139                    $scope.core.series = [
     
    145156                    var noOfStatus = status.length;
    146157                    var cpuSeries = [];
    147                     var coreSeries = [[],[]];
    148                     var memorySeries = [[],[]];
     158                    var coreSeries = [[], []];
     159                    var memorySeries = [[], []];
    149160                    for (var i = 0; i < noOfStatus; ++i) {
    150161                        var curStatus = status[i];
    151                         var cpuData = Math.round(curStatus.CpuUtilizationStatus.UsedCpuUtilization);
    152                         var usedCores = curStatus.CoreStatus.TotalCores - curStatus.CoreStatus.FreeCores;
    153                         var usedMemory = curStatus.MemoryStatus.TotalMemory - curStatus.MemoryStatus.FreeMemory;
     162                        var cpuData = Math.round(curStatus.CpuUtilizationStatus.ActiveCpuUtilization);
    154163                        cpuSeries.push([curStatus.Timestamp, cpuData]);
    155                         coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus.TotalCores]);
    156                         coreSeries[1].push([curStatus.Timestamp, usedCores]);
    157                         memorySeries[0].push([curStatus.Timestamp, curStatus.MemoryStatus.TotalMemory]);
    158                         memorySeries[1].push([curStatus.Timestamp, usedMemory]);
     164                        coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus.ActiveCores]);
     165                        coreSeries[1].push([curStatus.Timestamp, curStatus.CoreStatus.CalculatingCores]);
     166                        memorySeries[0].push([curStatus.Timestamp, Math.round(curStatus.MemoryStatus.ActiveMemory / 1024)]);
     167                        memorySeries[1].push([curStatus.Timestamp, Math.round(curStatus.MemoryStatus.UsedMemory / 1024)]);
    159168                    }
    160169                    $scope.cpu.series = [{ data: cpuSeries, label: "&nbsp;CPU Utilization", color: "#f7921d" }];
  • stable/HeuristicLab.Services.WebApp.Status/3.3/packages.config

    r12429 r12563  
    55  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
    66  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
    7   <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
     7  <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
    88</packages>
  • stable/HeuristicLab.Services.WebApp.Status/3.3/status.js

    r12428 r12563  
    22(function () {
    33    var plugin = appStatusPlugin;
    4     plugin.dependencies = ['ngResource', 'ui.knob', 'ui.bootstrap'];
     4    plugin.dependencies = ['ngResource', 'ui.knob', 'ui.bootstrap', 'tableSort'];
    55    plugin.files = [
    66        'WebApp/status.css',
     
    1515    ];
    1616    var menu = app.getMenu();
    17     var section = menu.getSection('Menü', 1);
     17    var section = menu.getSection('Menu', 1);
    1818    section.addEntry({
    1919        name: 'Status',
Note: See TracChangeset for help on using the changeset viewer.