Class: HybridPlatformsConductor::HpcPlugins::Log::RemoteFs
- Defined in:
- lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb
Overview
Save logs on the remote node’s file system
Constant Summary collapse
- MARKER_STDOUT =
'===== STDOUT ====='
- MARKER_STDERR =
'===== STDERR ====='
Constants included from LoggerHelpers
LoggerHelpers::LEVELS_MODIFIERS, LoggerHelpers::LEVELS_TO_STDERR
Instance Method Summary collapse
-
#actions_to_read_logs(node) ⇒ Object
Get actions to read logs.
-
#actions_to_save_logs(node, services, deployment_info, exit_status, stdout, stderr) ⇒ Object
Get actions to save logs [API] - This method is mandatory.
-
#logs_for(node, exit_status, stdout, stderr) ⇒ Object
Get deployment logs from a node.
Methods inherited from Log
Methods inherited from Plugin
extend_config_dsl_with, #initialize, valid?
Methods included from LoggerHelpers
#err, #init_loggers, #log_component=, #log_debug?, #log_level=, #out, #section, #set_loggers_format, #stderr_device, #stderr_device=, #stderr_displayed?, #stdout_device, #stdout_device=, #stdout_displayed?, #stdouts_to_s, #with_progress_bar
Constructor Details
This class inherits a constructor from HybridPlatformsConductor::Log
Instance Method Details
#actions_to_read_logs(node) ⇒ Object
Get actions to read logs. If provided, this method can return some actions to be executed that will fetch logs from servers or remote nodes. By using this method to run actions instead of the synchronous method logs_from, such actions will be run in parallel which can greatly improve time-consuming operations when querying a lot of nodes.
- API
-
This method is optional.
-
- API
-
The following API components are accessible:
-
-
*@config* (Config): Main configuration API.
-
*@nodes_handler* (NodesHandler): Nodes handler API.
-
*@actions_executor* (ActionsExecutor): Actions executor API.
- Parameters
-
node (String): Node for which deployment logs are being read
- Result
-
Array< Hash<Symbol,Object> >: List of actions to be done
87 88 89 90 91 92 |
# File 'lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb', line 87 def actions_to_read_logs(node) sudo_prefix = @actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} " [ { remote_bash: "#{sudo_prefix}cat /var/log/deployments/`#{sudo_prefix}ls -t /var/log/deployments/ | head -1`" } ] end |
#actions_to_save_logs(node, services, deployment_info, exit_status, stdout, stderr) ⇒ Object
Get actions to save logs
- API
-
This method is mandatory.
-
- API
-
The following API components are accessible:
-
-
*@config* (Config): Main configuration API.
-
*@nodes_handler* (NodesHandler): Nodes handler API.
-
*@actions_executor* (ActionsExecutor): Actions executor API.
- Parameters
-
node (String): Node for which logs are being saved
-
services (Array<String>): The list of services that have been deployed on this node
-
deployment_info (Hash<Symbol,Object>): Additional information to attach to the logs
-
exit_status (Integer or Symbol): Exit status of the deployment
-
stdout (String): Deployment’s stdout
-
stderr (String): Deployment’s stderr
- Result
-
Array< Hash<Symbol,Object> >: List of actions to be done
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb', line 31 def actions_to_save_logs(node, services, deployment_info, exit_status, stdout, stderr) # Create a log file to be scp with all relevant info ssh_user = @actions_executor.connector(:ssh).ssh_user sudo_prefix = ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} " log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{ssh_user}" [ { ruby: proc do FileUtils.mkdir_p File.dirname(log_file) File.write(log_file, <<~EOS) #{ deployment_info.merge( debug: log_debug? ? 'Yes' : 'No', services: services.join(', '), exit_status: exit_status ).map { |property, value| "#{property}: #{value}" }.join("\n") } #{MARKER_STDOUT} #{stdout} #{MARKER_STDERR} #{stderr} EOS end, remote_bash: "#{sudo_prefix}mkdir -p /var/log/deployments && #{sudo_prefix}chmod 600 /var/log/deployments" }, { scp: { log_file => '/var/log/deployments', :sudo => ssh_user != 'root', :owner => 'root', :group => 'root' } }, { remote_bash: "#{sudo_prefix}chmod 600 /var/log/deployments/#{File.basename(log_file)}", # Remove temporary files storing logs for security ruby: proc do File.unlink(log_file) end } ] end |
#logs_for(node, exit_status, stdout, stderr) ⇒ Object
Get deployment logs from a node. This method can use the result of actions previously run to read logs, as returned by the actions_to_read_logs method.
- API
-
This method is mandatory.
-
- API
-
The following API components are accessible:
-
-
*@config* (Config): Main configuration API.
-
*@nodes_handler* (NodesHandler): Nodes handler API.
-
*@actions_executor* (ActionsExecutor): Actions executor API.
- Parameters
-
node (String): The node we want deployment logs from
-
exit_status (Integer, Symbol or nil): Exit status of actions to read logs, or nil if no action was returned by actions_to_read_logs
-
stdout (String or nil): stdout of actions to read logs, or nil if no action was returned by actions_to_read_logs
-
stderr (String or nil): stderr of actions to read logs, or nil if no action was returned by actions_to_read_logs
- Result
-
Hash<Symbol,Object>: Deployment log information:
-
error (String): Error string in case deployment logs could not be retrieved. If set then further properties will be ignored. [optional]
-
services (Array<String>): List of services deployed on the node
-
deployment_info (Hash<Symbol,Object>): Deployment metadata
-
exit_status (Integer or Symbol): Deployment exit status
-
stdout (String): Deployment stdout
-
stderr (String): Deployment stderr
-
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb', line 115 def logs_for(node, exit_status, stdout, stderr) # Expected format for stdout: # Property1: Value1 # ... # PropertyN: ValueN # ===== STDOUT ===== # ... # ===== STDERR ===== # ... if exit_status.is_a?(Symbol) { error: "Error: #{exit_status}\n#{stderr}" } else stdout_lines = stdout.split("\n") if stdout_lines.first =~ /No such file or directory/ { error: '/var/log/deployments missing' } else stdout_idx = stdout_lines.index(MARKER_STDOUT) stderr_idx = stdout_lines.index(MARKER_STDERR) deploy_info = {} stdout_lines[0..stdout_idx - 1].each do |line| if line =~ /^([^:]+): (.+)$/ key_str, value = $1, $2 key = key_str.to_sym # Type-cast some values case key_str when 'date' # Date and time values # Thu Nov 23 18:43:01 UTC 2017 deploy_info[key] = Time.parse("#{value} UTC") when 'debug' # Boolean values # Yes deploy_info[key] = (value == 'Yes') when /^diff_files_.+$/, 'services' # Array of strings # my_file.txt, other_file.txt deploy_info[key] = value.split(', ') else deploy_info[key] = value end else deploy_info[:unknown_lines] = [] unless deploy_info.key?(:unknown_lines) deploy_info[:unknown_lines] << line end end services = deploy_info.delete(:services) exit_status = deploy_info.delete(:exit_status) { services: services, deployment_info: deploy_info, exit_status: exit_status =~ /^\d+$/ ? Integer(exit_status) : exit_status.to_sym, stdout: stdout_lines[stdout_idx + 1..stderr_idx - 1].join("\n"), stderr: stdout_lines[stderr_idx + 1..-1].join("\n") } end end end |