+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
module ProvenanceHelper
class GenerateGraph
gr
end
- def cr_input_pdhs cr
- pdhs = []
- input_obj = cr[:mounts].andand[:"/var/lib/cwl/cwl.input.json"].andand[:content] || cr[:mounts]
- if input_obj
- ProvenanceHelper::find_collections input_obj do |col_hash, col_uuid, key|
- if col_hash
- pdhs << col_hash
- end
- end
- end
- pdhs
- end
-
def job_edges job, edge_opts={}
uuid = job_uuid(job)
gr = ""
gr
end
+ def cr_edges cont, edge_opts={}
+ uuid = cont[:uuid]
+ gr = ""
+
+ gr += describe_node(cont[:uuid], {href: {controller: 'container_requests',
+ id: cont[:uuid]},
+ shape: 'oval',
+ label: cont[:name]})
+
+ ProvenanceHelper::find_collections cont[:mounts] do |collection_hash, collection_uuid, key|
+ if @opts[:pdh_to_uuid] and @opts[:pdh_to_uuid][collection_hash]
+ collection_uuid = @opts[:pdh_to_uuid][collection_hash].uuid
+ collection_hash = nil
+ end
+ if collection_uuid and @pdata[collection_uuid]
+ gr += describe_node(collection_uuid)
+ gr += edge(collection_uuid, uuid, {:label => key})
+ elsif collection_hash and @pdata[collection_hash]
+ gr += describe_node(collection_hash)
+ gr += edge(collection_hash, uuid, {:label => key})
+ end
+ end
+
+ if cont[:container_image] and !@opts[:no_docker] and @pdata[cont[:container_image]]
+ gr += describe_node(cont[:container_image], {label: cont[:container_image]})
+ gr += edge(cont[:container_image], uuid, {label: "docker_image"})
+ end
+
+ if cont[:output_uuid] and !edge_opts[:no_output] and @pdata[cont[:output_uuid]]
+ gr += describe_node(cont[:output_uuid])
+ gr += edge(uuid, cont[:output_uuid], {label: "output" })
+ end
+
+ if cont[:log_uuid] and !edge_opts[:no_log] and @pdata[cont[:log_uuid]]
+ gr += describe_node(cont[:log_uuid])
+ gr += edge(uuid, cont[:log_uuid], {label: "log"})
+ end
+
+ gr
+ end
+
+ def container_edges cont, edge_opts={}
+ uuid = cont[:uuid]
+ gr = ""
+
+ gr += describe_node(cont[:uuid], {href: {controller: 'containers',
+ id: cont[:uuid]},
+ shape: 'oval'})
+
+ ProvenanceHelper::find_collections cont[:mounts] do |collection_hash, collection_uuid, key|
+ if collection_uuid and @pdata[collection_uuid]
+ gr += describe_node(collection_uuid)
+ gr += edge(collection_uuid, uuid, {:label => key})
+ elsif collection_hash and @pdata[collection_hash]
+ gr += describe_node(collection_hash)
+ gr += edge(collection_hash, uuid, {:label => key})
+ end
+ end
+
+ if cont[:container_image] and !@opts[:no_docker] and @pdata[cont[:container_image]]
+ gr += describe_node(cont[:container_image], {label: cont[:container_image]})
+ gr += edge(cont[:container_image], uuid, {label: "docker_image"})
+ end
+
+ if cont[:output] and !edge_opts[:no_output] and @pdata[cont[:output]]
+ gr += describe_node(cont[:output])
+ gr += edge(uuid, cont[:output], {label: "output" })
+ end
+
+ if cont[:log] and !edge_opts[:no_log] and @pdata[cont[:log]]
+ gr += describe_node(cont[:log])
+ gr += edge(uuid, cont[:log], {label: "log"})
+ end
+
+ gr
+ end
+
def generate_provenance_edges(uuid)
gr = ""
m = GenerateGraph::collection_uuid(uuid)
gr += job_edges job if job
elsif rsc == ContainerRequest
cr = @pdata[uuid]
- if cr
- child_crs = []
- col_uuids = []
- col_pdhs = []
- col_uuids << cr[:output_uuid] if cr[:output_uuid]
- col_pdhs += cr_input_pdhs(cr)
- # Search for child CRs
- if cr[:container_uuid]
- child_crs = ContainerRequest.where(requesting_container_uuid: cr[:container_uuid])
- child_crs.each do |child|
- col_uuids << child[:output_uuid] if child[:output_uuid]
- col_pdhs += cr_input_pdhs(child)
- end
- end
-
- output_cols = {} # Indexed by UUID
- input_cols = {} # Indexed by PDH
-
- # Batch requests to get all related collections
- Collection.filter([['uuid', 'in', col_uuids.uniq]]).each do |c|
- output_cols[c[:uuid]] = c
- end
- output_pdhs = output_cols.values.map{|c| c[:portable_data_hash]}.uniq
- Collection.filter([['portable_data_hash', 'in', col_pdhs - output_pdhs]]).each do |c|
- if input_cols[c[:portable_data_hash]]
- input_cols[c[:portable_data_hash]] << c
- else
- input_cols[c[:portable_data_hash]] = [c]
- end
- end
-
- # Make the graph
- visited_pdhs = []
- all_cr_nodes = [cr] + child_crs.results
-
- # First pass: add the CR nodes with their outputs, because they're
- # referenced by UUID.
- all_cr_nodes.each do |cr_node|
- # CR node
- gr += describe_node(cr_node[:uuid], {href: {controller: 'container_requests',
- id: cr_node[:uuid]},
- label: cr_node[:name],
- shape: 'oval'})
- # Connect child CRs with the main one
- if cr_node != cr
- gr += edge(cr_node[:uuid], cr[:uuid], {label: 'child'})
- end
- # Output collection node
- if cr_node[:output_uuid] and output_cols[cr_node[:output_uuid]]
- c = output_cols[cr_node[:output_uuid]]
- visited_pdhs << c[:portable_data_hash]
- gr += describe_node(c[:portable_data_hash],
- {
- label: c[:name],
- col_uuid: c[:uuid],
- })
- gr += edge(cr_node[:uuid],
- c[:portable_data_hash],
- {label: 'output'})
- end
- end
-
- # Second pass: add the input collection nodes.
- all_cr_nodes.each do |cr_node|
- cr_input_pdhs(cr_node).each do |pdh|
- if not visited_pdhs.include?(pdh)
- visited_pdhs << pdh
- if input_cols[pdh]
- # First search for collections within the CR project
- cols = input_cols[pdh].select{|x| x[:owner_uuid] == cr_node[:owner_uuid]}
- if cols.empty?
- # Search for any collection with this PDH
- cols = input_cols[pdh]
- end
- names = cols.collect{|x| x[:name]}.uniq
- input_name = names.first
- if names.length > 1
- input_name += " + #{names.length - 1} others"
- end
- else
- # No collection found by this PDH
- input_name = pdh
- end
- gr += describe_node(pdh, {label: input_name})
- end
- gr += edge(pdh, cr_node[:uuid], {label: 'input'})
- end
- end
- end
+ gr += cr_edges cr if cr
+ elsif rsc == Container
+ cr = @pdata[uuid]
+ gr += container_edges cr if cr
end
end
node [fontsize=10,fontname=\"Helvetica,Arial,sans-serif\"];
edge [fontsize=10,fontname=\"Helvetica,Arial,sans-serif\"];
"""
-
- if opts[:direction] == :bottom_up
- gr += "edge [dir=back];"
+ if ["LR", "RL"].include? opts[:direction]
+ gr += "rankdir=#{opts[:direction]};"
end
begin
end
end
end
+
+ def self.cr_input_pdhs cr
+ pdhs = []
+ input_obj = cr[:mounts].andand[:"/var/lib/cwl/cwl.input.json"].andand[:content] || cr[:mounts]
+ if input_obj
+ find_collections input_obj do |col_hash, col_uuid, key|
+ if col_hash
+ pdhs << col_hash
+ end
+ end
+ end
+ pdhs
+ end
end