3605: Getting jobs/queue_size from API server works. Fixed server-side
authorPeter Amstutz <peter.amstutz@curoverse.com>
Tue, 16 Sep 2014 00:41:26 +0000 (20:41 -0400)
committerPeter Amstutz <peter.amstutz@curoverse.com>
Tue, 16 Sep 2014 00:41:26 +0000 (20:41 -0400)
sorting.  Date rendering improvements.

apps/workbench/app/assets/javascripts/dates.js
apps/workbench/app/assets/stylesheets/projects.css.scss
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/models/job.rb
apps/workbench/app/views/application/_pipeline_status_label.html.erb
apps/workbench/app/views/collections/_show_source_summary.html.erb
apps/workbench/app/views/projects/_compute_node_summary.html.erb [new file with mode: 0644]
apps/workbench/app/views/projects/index.html.erb
services/api/app/controllers/arvados/v1/jobs_controller.rb

index 9e484ce15d10a7a766b3092a3db988569b6e6059..eeb6edea1cd8442480fd5bd0a295c0459665c9b4 100644 (file)
@@ -1,11 +1,23 @@
+jQuery(function($){
 $(document).on('ajax:complete arv:pane:loaded ready', function() {
-    console.log("woble!");
     $('[data-utc-date]').each(function(i, elm) {
-        var re = /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d) UTC/;
-        var v = $(elm).attr('data-utc-date').match(re);
+            console.log("woble!");
+        var v = $(elm).attr('data-utc-date').match(/(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d) UTC/);
+        if (!v) {
+            v = $(elm).attr('data-utc-date').match(/(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z/);
+        }
+
         if (v) {
             var ts = new Date(Date.UTC(v[1], v[2]-1, v[3], v[4], v[5], v[6]));
-            $(elm).text(ts.toLocaleTimeString() + " " + ts.toLocaleDateString());
+            if ($(elm).attr('data-utc-date-opts') && $(elm).attr('data-utc-date-opts').match(/noseconds/)) {
+                $(elm).text((ts.getHours() > 12 ? (ts.getHours()-12) : ts.getHours())
+                            + ":" + (ts.getMinutes() < 10 ? '0' : '') + ts.getMinutes()
+                            + (ts.getHours() > 12 ? " PM " : " AM ")
+                            + ts.toLocaleDateString());
+            } else {
+                $(elm).text(ts.toLocaleTimeString() + " " + ts.toLocaleDateString());
+            }
         }
     });
 });
+});
index 600a7a39504b8fece5bd6f7c86afda368e97c55c..d9edfd89fd7aa7c1b997cc20d20acb937c57cdef 100644 (file)
@@ -54,5 +54,15 @@ div.scroll-20em {
 }
 
 .dashboard-panel-info-row {
-  margin-bottom: .5em
+  padding: .5em;
+  border-radius: .3em;
+}
+
+.x-ellip {
+  overflow-x: hide;
+  text-overflow: ellipsis;
+}
+
+.dashboard-panel-info-row:hover {
+  background-color: #D9EDF7;
 }
\ No newline at end of file
index 3c067fa4681b6c70bd000a045db93fc5fe5b422d..756339e5be3924f59032b5dc2956da4b41cd240b 100644 (file)
@@ -694,17 +694,17 @@ class ApplicationController < ActionController::Base
 
   helper_method :running_pipelines
   def running_pipelines
-    PipelineInstance.order([["started_at", "asc"]]).filter([["state", "=", "RunningOnServer"]]).all.results.reverse
+    PipelineInstance.order(["started_at asc", "created_at asc"]).filter([["state", "in", ["RunningOnServer", "RunningOnClient"]]])
   end
 
   helper_method :finished_pipelines
   def finished_pipelines lim
-    PipelineInstance.limit(lim).order([["finished_at", "asc"]]).filter([["state", "in", ["Completed", "Failed", "Cancelled"]]])
+    PipelineInstance.limit(lim).order(["finished_at desc"]).filter([["state", "in", ["Complete", "Failed", "Paused"]], ["finished_at", "!=", nil]])
   end
 
   helper_method :recent_collections
   def recent_collections lim
-    c = Collection.limit(lim).order([["modified_at", "asc"]]).filter([["owner_uuid", "is_a", "arvados#group"]])
+    c = Collection.limit(lim).order(["modified_at desc"]).filter([["owner_uuid", "is_a", "arvados#group"]])
     own = {}
     Group.filter([["uuid", "in", c.map(&:owner_uuid)]]).each do |g|
       own[g[:uuid]] = g
index 309cadeb69554e1aac0a6dbeaa10b92d7adee30f..ff2eb00e7096957b9e77a5ba08702c0239524169 100644 (file)
@@ -34,6 +34,10 @@ class Job < ArvadosBase
     arvados_api_client.api "jobs/#{self.uuid}/", "cancel", {}
   end
 
+  def self.queue_size
+    arvados_api_client.api("jobs/", "queue_size", {"_method"=> "GET"})[:queue_size] rescue 0
+  end
+
   def state
     Job::state(self)
   end
index 8abf65b4537cf01f22027e8be36586e8f414bdd0..9e5b71047b3147daf54fe9478429d26555d03e8a 100644 (file)
@@ -4,6 +4,8 @@
   <span class="label label-danger">failed</span>
 <% elsif p.state == 'RunningOnServer' || p.state == 'RunningOnClient' %>
   <span class="label label-info">running</span>
+<% elsif p.state == 'Paused'  %>
+  <span class="label label-default">paused</span>
 <% else %>
   <% if not p.components.values.any? { |c| c[:job] rescue false } %>
     <span class="label label-default">not started</span>
index ba9e9dfb9fe628b4faf8dc318c19b6f7ab78b49b..51f9348450219e2e6ead5f0eec3dbd673fe59ebd 100644 (file)
@@ -7,10 +7,12 @@
     <% pipelines = PipelineInstance.filter([["components", "like", "%#{@object.uuid}%"]]).each do |pipeline| %>
       <% pipeline.components.each do |cname, c| %>
         <% if c[:output_uuid] == @object.uuid %>
-          <b><%= cname %></b> component of pipeline <b><%= link_to_if_arvados_object(pipeline, friendly_name: true) %></b>
+          <b><%= cname %></b> component of <b><%= link_to_if_arvados_object(pipeline, friendly_name: true) %></b>
           <% if c.andand[:job].andand[:finished_at] %>
-            <b>finished at <%= c[:job][:finished_at] %></b>
+            finished at <span class="utc-date"
+                                 data-utc-date="<%= c[:job][:finished_at] %>"><%= c[:job][:finished_at] %></span>
           <% end %>
+          <br>
         <% end %>
       <% end %>
     <% end %>
diff --git a/apps/workbench/app/views/projects/_compute_node_summary.html.erb b/apps/workbench/app/views/projects/_compute_node_summary.html.erb
new file mode 100644 (file)
index 0000000..9a58d09
--- /dev/null
@@ -0,0 +1,23 @@
+<div class="compute-summary-numbers">
+    <table>
+      <colgroup>
+        <col width="25%">
+        <col width="25%">
+        <col width="25%">
+        <col width="25%">
+
+      </colgroup>
+      <tr>
+        <td><%= Job.queue_size %></td>
+        <td><%= nodes.select {|n| n.crunch_worker_state.in? ["busy", "idle"] }.size %></td>
+        <td><%= nodes.select {|n| n.crunch_worker_state == "busy" }.size %></td>
+        <td><%= nodes.select {|n| n.crunch_worker_state == "idle" }.size %></td>
+      </tr>
+      <tr>
+        <th>Queue</th>
+        <th>Nodes</th>
+        <th>Busy</th>
+        <th>Idle</th>
+      </tr>
+    </table>
+</div>
index fad72044f4ee110d830dec8b43633be311467185..e7e87368d6a837538fac9f31a4eff0783249270b 100644 (file)
@@ -2,7 +2,7 @@
   <div class="row">
     <div class="col-md-6">
       <div class="panel panel-default">
-        <div class="panel-heading"><span class="panel-title">Pipelines running</span>
+        <div class="panel-heading"><span class="panel-title">Active pipelines</span>
           <span class="pull-right">
     <%= link_to(
          choose_pipeline_templates_path(
@@ -17,7 +17,7 @@
     </span>
         </div>
 
-        <div class="panel-body" style="overflow-x: scroll;">
+        <div class="panel-body">
           <% if running_pipelines.empty? %>
             No pipelines are currently running.
           <% end %>
@@ -67,7 +67,8 @@
               </div>
 
               <div class="clearfix">
-                Started at <span class="utc-date" data-utc-date="<%= p[:started_at] || p[:created_at] %>"><%= p[:created_at] %></span>.
+                Started at <span class="utc-date" data-utc-date="<%= p[:started_at] || p[:created_at] %>"
+                                 data-utc-date-opts="noseconds"><%= p[:created_at] %></span>.
                 <% pipeline_time = Time.now - (p[:started_at] || p[:created_at]) %>
                 Active for <%= runtime(pipeline_time, false) %>.
 
 
       <div class="panel panel-default">
         <div class="panel-heading"><span class="panel-title">Recently finished pipelines</span></div>
-        <div class="panel-body" style="overflow-x: scroll;">
+        <div class="panel-body">
           <% finished_pipelines(8).each do |p| %>
             <div class="dashboard-panel-info-row">
               <div class="row">
-                <div class="col-md-4">
+                <div class="col-md-6 x-ellip">
                 <%= link_to_if_arvados_object p, friendly_name: true %>
               </div>
-              <div class="col-md-4">
+              <div class="col-md-2">
                 <%= render partial: "pipeline_status_label", locals: {p: p}%>
               </div>
               <div class="col-md-4">
-                <% outputs = [] %>
-                <% p.components.each do |k, c| %>
-                  <% outputs << c[:output_uuid] if c[:output_uuid] %>
-                <% end %>
-                <%= outputs %>
+                <span class="utc-date" data-utc-date="<%= p[:finished_at] || p[:modified_at] %>"
+                      data-utc-date-opts="noseconds"><%= p[:modified_at] %></span>
               </div>
               </div>
-
               <div class="row">
                 <div class="col-md-12">
-                  Finished at <span class="utc-date" data-utc-date="<%= p[:finished_at] || p[:modified_at] %>"><%= p[:modified_at] %></span>.
                   <% if p[:started_at] and p[:finished_at] %>
                     <% pipeline_time = p[:finished_at] - p[:started_at] %>
-                    Active for <%= runtime(pipeline_time, false) %>.
+                    Active for <%= runtime(pipeline_time, false) %>
                   <% end %>
+
+                  <span class="pull-right">
+                    <% outputs = [] %>
+                    <% p.components.each do |k, c| %>
+                      <% outputs << c[:output_uuid] if c[:output_uuid] %>
+                    <% end %>
+                    <% if outputs.size == 0 %>
+                      No output.
+                    <% elsif outputs.size == 1 %>
+                      <i class="fa fa-fw fa-archive"></i> <%= link_to_if_arvados_object outputs[0], friendly_name: true %>
+                    <% else %>
+                      <a href="#<%= p[:uuid] %>" data-toggle="collapse">Outputs <span class="caret"></span></a>
+                    <% end %>
+                  </span>
                 </div>
               </div>
+
+                <div class="row collapse" id="<%= p[:uuid] %>" >
+                  <div class="col-md-offset-3 col-md-10">
+                    <% outputs.each do |out| %>
+                      <div>
+                        <i class="fa fa-fw fa-archive"></i> <%= link_to_if_arvados_object out, friendly_name: true %>
+                      </div>
+                    <% end %>
+                  </div>
+                </div>
+
             </div>
           <% end %>
         </div>
       </div>
-        </div>
+    </div>
 
     <div class="col-md-6">
       <% nodes = Node.all %>
       <div class="panel panel-default">
-        <div class="panel-heading"><span class="panel-title"><a data-toggle="collapse" href="#compute_node_status">Compute node status</a></span></div>
+        <div class="panel-heading"><span class="panel-title"><a data-toggle="collapse" href="#compute_node_status">Compute node status <span class="caret"></span></a></span></div>
         <div class="panel-body">
           <div class="compute-node-summary" data-toggle="collapse" href="#compute_node_status">
             <%= render partial: 'compute_node_summary', locals: {nodes: nodes} %>
       </div>
       <div class="panel panel-default">
         <div class="panel-heading"><span class="panel-title">Recent collections</span></div>
-        <div class="panel-body" style="overflow-x: scroll;">
+        <div class="panel-body">
           <% r = recent_collections(8) %>
           <% r[:collections].each do |p| %>
             <div class="dashboard-panel-info-row">
             <div>
               <i class="fa fa-fw fa-folder-o"></i><%= link_to_if_arvados_object r[:owners][p[:owner_uuid]], friendly_name: true %>/
-              <span class="pull-right"><span class="utc-date" data-utc-date="<%= p[:modified_at] %>">p[:modified_at]</span></span>
+              <span class="pull-right"><span class="utc-date"
+                                             data-utc-date="<%= p[:modified_at] %>"
+                                             data-utc-date-opts="noseconds"><%= p[:modified_at]%></span></span>
             </div>
-            <div style="margin-left: 1em"><%= link_to_if_arvados_object p, friendly_name: true %>
+            <div class="x-ellip" style="margin-left: 1em"><%= link_to_if_arvados_object p, friendly_name: true %>
             </div>
             </div>
           <% end %>
index afb516bd48d89385d70f42922374359d7079b7e0..5a571d4a8b6665b98ee6a9d76d9055c99e1c5e34 100644 (file)
@@ -2,8 +2,8 @@ class Arvados::V1::JobsController < ApplicationController
   accept_attribute_as_json :script_parameters, Hash
   accept_attribute_as_json :runtime_constraints, Hash
   accept_attribute_as_json :tasks_summary, Hash
-  skip_before_filter :find_object_by_uuid, :only => :queue
-  skip_before_filter :render_404_if_no_object, :only => :queue
+  skip_before_filter :find_object_by_uuid, :only => [:queue, :queue_size]
+  skip_before_filter :render_404_if_no_object, :only => [:queue, :queue_size]
 
   def create
     [:repository, :script, :script_version, :script_parameters].each do |r|
@@ -163,7 +163,7 @@ class Arvados::V1::JobsController < ApplicationController
   end
 
   def queue_size
-    render :json => {:queue_size => Job.queue.size}
+          render :json => {:queue_size => Job.queue.size}
   end
 
   def self._create_requires_parameters