class Syskit::NetworkGeneration::SystemNetworkDeployer
Algorithm that transforms a network generated by {SystemNetworkGenerator} into a deployed network
It does not deal with adapting an existing network
Attributes
event_logger[R]
merge_solver[R]
plan[R]
task_context_deployment_candidates[R]
Public Class Methods
new(plan, event_logger: plan.event_logger, merge_solver: MergeSolver.new(plan))
click to toggle source
# File lib/syskit/network_generation/system_network_deployer.rb, line 18 def initialize(plan, event_logger: plan.event_logger, merge_solver: MergeSolver.new(plan)) @plan = plan @event_logger = event_logger @merge_solver = merge_solver @task_context_deployment_candidates = compute_task_context_deployment_candidates end
Public Instance Methods
apply_selected_deployments(selected_deployments)
click to toggle source
# File lib/syskit/network_generation/system_network_deployer.rb, line 123 def apply_selected_deployments(selected_deployments) deployment_tasks = Hash.new selected_deployments.each do |task, selected| machine, configured_deployment, task_name = *selected deployment_task = (deployment_tasks[[machine, configured_deployment]] ||= configured_deployment.new(on: machine)) if Syskit.conf.permanent_deployments? plan.add_permanent_task(deployment_task) else plan.add(deployment_task) end deployed_task = deployment_task.task(task_name) debug { "deploying #{task} with #{task_name} of #{configured_deployment.short_name} (#{deployed_task})" } # We MUST merge one-by-one here. Calling apply_merge_group # on all the merges at once would NOT copy the connections # that exist between the tasks of the "from" group to the # "to" group, which is really not what we want # # Calling with all the mappings would be useful if what # we wanted is replace a subnet of the plan by another # subnet. This is not the goal here. merge_solver.apply_merge_group(task => deployed_task) end end
available_deployments()
click to toggle source
Returns the set of deployments that are available for this network generation
# File lib/syskit/network_generation/system_network_deployer.rb, line 29 def available_deployments Syskit.conf.deployments end
compute_task_context_deployment_candidates()
click to toggle source
Computes a mapping from task models to the set of registered deployments that apply on these task models
deploy(validate: true)
click to toggle source
# File lib/syskit/network_generation/system_network_deployer.rb, line 33 def deploy(validate: true) debug do debug "Deploying the system network" debug "Available deployments" log_nest(2) do task_context_deployment_candidates.each do |model, deployments| if !deployments debug "#{model}: no deployments" elsif deployments.size == 1 debug "#{model}: #{deployments.first}" else debug "#{model}" log_nest(2) do deployments.each do |deployment| debug deployment.to_s end end end end end break end selected_deployments, missing_deployments = select_deployments log_timepoint 'select_deployments' apply_selected_deployments(selected_deployments) log_timepoint 'apply_selected_deployments' if validate validate_deployed_network log_timepoint 'validate_deployed_network' end return missing_deployments end
find_suitable_deployment_for(task)
click to toggle source
# File lib/syskit/network_generation/system_network_deployer.rb, line 94 def find_suitable_deployment_for(task) # task.model would be wrong here as task.model could be the # singleton class (if there are dynamic services) candidates = task_context_deployment_candidates[task.model] if !candidates || candidates.empty? candidates = task_context_deployment_candidates[task.concrete_model] if !candidates || candidates.empty? debug { "no deployments found for #{task} (#{task.concrete_model})" } return end end if candidates.size > 1 debug { "#{candidates.size} deployments available for #{task} (#{task.concrete_model}), trying to resolve" } selected = log_nest(2) do resolve_deployment_ambiguity(candidates, task) end if selected debug { " selected #{selected}" } return selected else debug { " deployment of #{task} (#{task.concrete_model}) is ambiguous" } return end else return candidates.first end end
resolve_deployment_ambiguity(candidates, task)
click to toggle source
Try to resolve a set of deployment candidates for a given task
@param [Array<(String,Model<Deployment>,String)>] candidates set
of deployment candidates as (process_server_name,deployment_model,task_name) tuples
@param [Syskit::TaskContext] task the task context for which
candidates are possible deployments
@return [(String,Model<Deployment>,String),nil] the resolved
deployment, if finding a single best candidate was possible, or nil otherwise.
# File lib/syskit/network_generation/system_network_deployer.rb, line 210 def resolve_deployment_ambiguity(candidates, task) if task.orocos_name debug { "#{task} requests orocos_name to be #{task.orocos_name}" } resolved = candidates.find { |_, _, task_name| task_name == task.orocos_name } if !resolved debug { "cannot find requested orocos name #{task.orocos_name}" } end return resolved end hints = task.deployment_hints debug { "#{task}.deployment_hints: #{hints.map(&:to_s).join(", ")}" } # Look to disambiguate using deployment hints resolved = candidates.find_all do |_, deployment_model, task_name| task.deployment_hints.any? do |rx| rx == deployment_model || rx === task_name end end if resolved.size != 1 info do info { "ambiguous deployment for #{task} (#{task.model})" } candidates.each do |machine, deployment_model, task_name| info { " #{task_name} of #{deployment_model.short_name} on #{machine}" } end break end return end return resolved.first end
select_deployments()
click to toggle source
# File lib/syskit/network_generation/system_network_deployer.rb, line 70 def select_deployments used_deployments = Set.new missing_deployments = Set.new selected_deployments = Hash.new all_tasks = plan.find_local_tasks(TaskContext).to_a all_tasks.each do |task| next if task.execution_agent if !(selected = find_suitable_deployment_for(task)) missing_deployments << task elsif used_deployments.include?(selected) debug do machine, configured_deployment, task_name = *selected "#{task} resolves to #{configured_deployment}.#{task_name} on #{machine} for its deployment, but it is already used" end missing_deployments << task else used_deployments << selected selected_deployments[task] = selected end end return selected_deployments, missing_deployments end
validate_deployed_network()
click to toggle source
Sanity checks to verify that the result of deploy_system_network is valid
@raise [MissingDeployments] if some tasks could not be deployed
# File lib/syskit/network_generation/system_network_deployer.rb, line 153 def validate_deployed_network verify_all_tasks_deployed end
verify_all_tasks_deployed()
click to toggle source
# File lib/syskit/network_generation/system_network_deployer.rb, line 157 def verify_all_tasks_deployed not_deployed = plan.find_local_tasks(TaskContext). not_finished.not_abstract. find_all { |t| !t.execution_agent } if !not_deployed.empty? tasks_with_candidates = Hash.new not_deployed.each do |task| candidates = task_context_deployment_candidates[task.concrete_model] || [] candidates = candidates.map do |process_server_name, deployment, task_name| existing = plan.find_local_tasks(task.model). find_all { |t| t.orocos_name == task_name } [process_server_name, deployment, task_name, existing] end tasks_with_candidates[task] = candidates end raise MissingDeployments.new(tasks_with_candidates), "there are tasks for which it exists no deployed equivalent: #{not_deployed.map { |m| "#{m}(#{m.orogen_model.name})" }}" end end