hybrid_platforms_conductor 32.7.0 → 32.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34ae09b6107332c4f51418677736cabed358f01c3e5c47ff2f5752f6c597a809
4
- data.tar.gz: 99358ffeb3d2f70819c5408c18b5b8d8e5531331da0c96073e5577f02cebcb72
3
+ metadata.gz: 04d2e323c123bfaa35c0fb61f95dcc7a9ade67b19f184eff75c61419e249ac8e
4
+ data.tar.gz: 25afb265a466103db73b891c62ec9a9ee32e5529bf8d9f0df71df379bab5ec7a
5
5
  SHA512:
6
- metadata.gz: 873851a3e54538b2915df041e9dca3decde7cbfe4f7e8b82ea7102bbe5e75668ef5d7adb828979f4eab8493245f982b3e5da0bb492c116688b9151d10bc979a2
7
- data.tar.gz: 72418b66806746d05589f08f773eb065b0811d760e35908410405f1cbd9a6fadc94aa2ec85a83ac7f314f53d6a7ebc6396460894c4f595aee9c9b0ffd65625c0
6
+ metadata.gz: d8112983393928123c7f8f35395506c4ec5e401e84577e3ab1e24380ab0cd92affd90b6be0cb75645314d06cc8350cd8c478e1d1b9e3c600143296bdec73af47
7
+ data.tar.gz: 6177c45b5489b077ee2d3e6d7535d6c07e94715c755c282ea8dc424e54d35ac1603c4be9d2e2d9b4cbfc4f450463c792a3e449f6dbbc5eb6bba4a0161c695c65
@@ -574,28 +574,33 @@ module HybridPlatformsConductor
574
574
  end
575
575
  end
576
576
  end
577
+ else
578
+ # We have not created any ControlMaster, but still consider the nodes to be ready to connect
579
+ user_locks = Hash[nodes.map { |node| [node, nil]} ]
577
580
  end
578
581
  yield user_locks.keys
579
582
  ensure
580
- user_locks_mutex.synchronize do
581
- user_locks.each do |node, user_id|
582
- with_lock_on_control_master_for(node, user_id: user_id) do |current_users, user_id|
583
- ssh_url = "hpc.#{node}"
584
- log_warn "[ ControlMaster - #{ssh_url} ] - Current process/thread was not part of the ControlMaster users anymore whereas it should have been" unless current_users.include?(user_id)
585
- remaining_users = current_users - [user_id]
586
- if remaining_users.empty?
587
- # Stop the ControlMaster
588
- log_debug "[ ControlMaster - #{ssh_url} ] - Stopping ControlMaster..."
589
- # Dumb verbose ssh! Tricky trick to just silence what is useless.
590
- # Don't fail if the connection close fails (but still log the error), as it can be seen as only a warning: it means the connection was closed anyway.
591
- @cmd_runner.run_cmd "#{ssh_exec_for(node)} -O exit #{ssh_url} 2>&1 | grep -v 'Exit request sent.'", log_to_stdout: log_debug?, expected_code: 1, timeout: timeout, no_exception: true
592
- log_debug "[ ControlMaster - #{ssh_url} ] - ControlMaster stopped"
593
- # Uncomment if you want to test that the connection has been closed
594
- # @cmd_runner.run_cmd "#{ssh_exec_for(node)} -O check #{ssh_url}", log_to_stdout: log_debug?, expected_code: 255, timeout: timeout
595
- else
596
- log_debug "[ ControlMaster - #{ssh_url} ] - Leaving ControlMaster started as #{remaining_users.size} processes/threads are still using it."
583
+ if @ssh_use_control_master
584
+ user_locks_mutex.synchronize do
585
+ user_locks.each do |node, user_id|
586
+ with_lock_on_control_master_for(node, user_id: user_id) do |current_users, user_id|
587
+ ssh_url = "hpc.#{node}"
588
+ log_warn "[ ControlMaster - #{ssh_url} ] - Current process/thread was not part of the ControlMaster users anymore whereas it should have been" unless current_users.include?(user_id)
589
+ remaining_users = current_users - [user_id]
590
+ if remaining_users.empty?
591
+ # Stop the ControlMaster
592
+ log_debug "[ ControlMaster - #{ssh_url} ] - Stopping ControlMaster..."
593
+ # Dumb verbose ssh! Tricky trick to just silence what is useless.
594
+ # Don't fail if the connection close fails (but still log the error), as it can be seen as only a warning: it means the connection was closed anyway.
595
+ @cmd_runner.run_cmd "#{ssh_exec_for(node)} -O exit #{ssh_url} 2>&1 | grep -v 'Exit request sent.'", log_to_stdout: log_debug?, expected_code: 1, timeout: timeout, no_exception: true
596
+ log_debug "[ ControlMaster - #{ssh_url} ] - ControlMaster stopped"
597
+ # Uncomment if you want to test that the connection has been closed
598
+ # @cmd_runner.run_cmd "#{ssh_exec_for(node)} -O check #{ssh_url}", log_to_stdout: log_debug?, expected_code: 255, timeout: timeout
599
+ else
600
+ log_debug "[ ControlMaster - #{ssh_url} ] - Leaving ControlMaster started as #{remaining_users.size} processes/threads are still using it."
601
+ end
602
+ false
597
603
  end
598
- false
599
604
  end
600
605
  end
601
606
  end
@@ -1,5 +1,5 @@
1
1
  module HybridPlatformsConductor
2
2
 
3
- VERSION = '32.7.0'
3
+ VERSION = '32.7.1'
4
4
 
5
5
  end
@@ -118,8 +118,12 @@ describe HybridPlatformsConductor::ActionsExecutor do
118
118
  ['which env', proc { [0, "/usr/bin/env\n", ''] }],
119
119
  ['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }]
120
120
  ] + ssh_expected_commands_for(
121
- 'node1' => { connection: '192.168.42.1', user: 'test_user' },
122
- 'node3' => { connection: '192.168.42.3', user: 'test_user' }
121
+ {
122
+ 'node1' => { connection: '192.168.42.1', user: 'test_user' },
123
+ 'node3' => { connection: '192.168.42.3', user: 'test_user' }
124
+ },
125
+ # Here the threads for node1's and node3's ControlMasters might not trigger before the one for node2, so they will not destroy it.
126
+ with_control_master_destroy_optional: true
123
127
  ) + ssh_expected_commands_for(
124
128
  {
125
129
  'node2' => { connection: '192.168.42.2', user: 'test_user', control_master_create_error: 'Can\'t connect to 192.168.42.2' }
@@ -294,7 +298,8 @@ describe HybridPlatformsConductor::ActionsExecutor do
294
298
  ) do
295
299
  test_connector.ssh_use_control_master = false
296
300
  test_connector.ssh_user = 'test_user'
297
- test_connector.with_connection_to(['node']) do
301
+ test_connector.with_connection_to(['node']) do |connected_nodes|
302
+ expect(connected_nodes).to eq %w[node]
298
303
  end
299
304
  end
300
305
  end
@@ -50,7 +50,8 @@ describe 'executables\' common options' do
50
50
  with_test_platform_for_common_options do
51
51
  exit_code, stdout, stderr = run executable, *(['--debug'] + default_options)
52
52
  expect(exit_code).to eq 0
53
- expect(stderr).to eq ''
53
+ # Make sure to ignore the deployment markers from stderr.
54
+ expect(stderr.gsub("===== [ node1 / node1_service ] - HPC Service Check ===== Begin\n===== [ node1 / node1_service ] - HPC Service Check ===== End\n", '')).to eq ''
54
55
  end
55
56
  end
56
57
 
@@ -8,13 +8,27 @@ module HybridPlatformsConductorTest
8
8
  # Run expectations on the expected commands to be called.
9
9
  #
10
10
  # Parameters::
11
- # * *commands* (Array< [String or Regexp, Proc] >): Expected commands that should be called on CmdRunner: the command name or regexp and the corresponding mocked code
12
- # * Parameters::
13
- # * Same parameters as CmdRunner@run_cmd
11
+ # * *commands* (Array<Array>): List of expected commands that should be called on CmdRunner. Each specification is a list containing those items:
12
+ # * *0* (String or Regexp): The command name or regexp matching the command name
13
+ # * *1* (Proc): The mocking code to be called in place of the real command:
14
+ # * Parameters::
15
+ # * Same parameters as CmdRunner@run_cmd
16
+ # * Result::
17
+ # * Same results as CmdRunner@run_cmd
18
+ # * *2* (Hash): Optional hash of options. Can be ommited. [default = {}]
19
+ # * *optional* (Boolean): If true then don't fail if the command to be mocked has not been called [default: false]
14
20
  # * *cmd_runner* (CmdRunner): The CmdRunner to mock [default: test_cmd_runner]
15
21
  # * Proc: Code called with the command runner mocked
16
22
  def with_cmd_runner_mocked(commands, cmd_runner: test_cmd_runner)
17
- remaining_expected_commands = commands.clone
23
+ remaining_expected_commands = commands.map do |(expected_command, command_code, options)|
24
+ [
25
+ expected_command,
26
+ command_code,
27
+ {
28
+ optional: false
29
+ }.merge(options || {})
30
+ ]
31
+ end
18
32
  # We need to protect the access to this array as the mocked commands can be called by competing threads
19
33
  remaining_expected_commands_mutex = Mutex.new
20
34
  allow(cmd_runner).to receive(:run_cmd) do |cmd, log_to_file: nil, log_to_stdout: true, log_stdout_to_io: nil, log_stderr_to_io: nil, expected_code: 0, timeout: nil, no_exception: false|
@@ -22,7 +36,7 @@ module HybridPlatformsConductorTest
22
36
  found_command = nil
23
37
  found_command_code = nil
24
38
  remaining_expected_commands_mutex.synchronize do
25
- remaining_expected_commands.delete_if do |(expected_command, command_code)|
39
+ remaining_expected_commands.delete_if do |(expected_command, command_code, _options)|
26
40
  break unless found_command.nil?
27
41
  if (expected_command.is_a?(String) && expected_command == cmd) || (expected_command.is_a?(Regexp) && cmd =~ expected_command)
28
42
  found_command = expected_command
@@ -67,7 +81,11 @@ module HybridPlatformsConductorTest
67
81
  end
68
82
  end
69
83
  yield
70
- expect(remaining_expected_commands).to eq([]), "Expected CmdRunner commands were not run:\n#{remaining_expected_commands.map(&:first).join("\n")}"
84
+ expect(
85
+ remaining_expected_commands.select do |(_expected_command, _command_code, options)|
86
+ !options[:optional]
87
+ end
88
+ ).to eq([]), "Expected CmdRunner commands were not run:\n#{remaining_expected_commands.map(&:first).join("\n")}"
71
89
  # Un-mock the command runner
72
90
  allow(cmd_runner).to receive(:run_cmd).and_call_original
73
91
  end
@@ -17,16 +17,18 @@ module HybridPlatformsConductorTest
17
17
  # * *with_control_master_create* (Boolean): Do we create the control master? [default: true]
18
18
  # * *with_control_master_check* (Boolean): Do we check the control master? [default: false]
19
19
  # * *with_control_master_destroy* (Boolean): Do we destroy the control master? [default: true]
20
+ # * *with_control_master_destroy_optional* (Boolean): If true, then consider the ControlMaster destruction to be optional [default: false]
20
21
  # * *with_strict_host_key_checking* (Boolean): Do we use strict host key checking? [default: true]
21
22
  # * *with_batch_mode* (Boolean): Do we use BatchMode when creating the control master? [default: true]
22
23
  # * *with_session_exec* (Boolean): Do we use Sessien Exec capabilities when creating the control master? [default: true]
23
24
  # Result::
24
- # * Array< [String or Regexp, Proc] >: The expected commands that should be used, and their corresponding mocked code
25
+ # * Array<Array>: The expected commands that should be used, and their corresponding mocked code and options
25
26
  def ssh_expected_commands_for(
26
27
  nodes_connections,
27
28
  with_control_master_create: true,
28
29
  with_control_master_check: false,
29
30
  with_control_master_destroy: true,
31
+ with_control_master_destroy_optional: false,
30
32
  with_strict_host_key_checking: true,
31
33
  with_batch_mode: true,
32
34
  with_session_exec: true
@@ -45,12 +47,19 @@ module HybridPlatformsConductorTest
45
47
  ])
46
48
  end
47
49
  if with_control_master_create
50
+ control_master_created = false
48
51
  ssh_commands_per_connection << [
49
52
  if with_session_exec
50
53
  /^.+\/ssh #{with_batch_mode ? '-o BatchMode=yes ' : ''}-o ControlMaster=yes -o ControlPersist=yes hpc\.#{Regexp.escape(node)} true$/
51
54
  else
52
- # Mock the user hitting enter as the Control MAster will be created in another thread and the main thread waits for user input.
53
- expect($stdin).to receive(:gets) { "\n" }
55
+ # Mock the user hitting enter as the Control Master will be created in another thread and the main thread waits for user input.
56
+ expect($stdin).to receive(:gets) do
57
+ # We have to wait for the Control Master creation thread to actually create the Control Master before hitting Enter.
58
+ while !control_master_created do
59
+ sleep 0.1
60
+ end
61
+ "\n"
62
+ end
54
63
  /^xterm -e '.+\/ssh -o ControlMaster=yes -o ControlPersist=yes hpc\.#{Regexp.escape(node)}'$/
55
64
  end,
56
65
  proc do
@@ -61,6 +70,7 @@ module HybridPlatformsConductorTest
61
70
  elsif node_connection_info[:control_master_create_error].nil?
62
71
  # Really touch a fake control file, as ssh connector checks for its existence
63
72
  File.write(control_file, '')
73
+ control_master_created = true
64
74
  # If there is no Session Exec, this is done in a separate thread.
65
75
  # So keep it alive until the user wants to stop it (which is done using an ssh -O exit command).
66
76
  loop { sleep 0.1 } unless with_session_exec
@@ -84,7 +94,8 @@ module HybridPlatformsConductorTest
84
94
  # Really mock the control file deletion
85
95
  File.unlink(test_actions_executor.connector(:ssh).send(:control_master_file, node_connection_info[:connection], '22', node_connection_info[:user]))
86
96
  [1, '', '']
87
- end
97
+ end,
98
+ { optional: with_control_master_destroy_optional }
88
99
  ]
89
100
  end
90
101
  ssh_commands_once + ssh_commands_per_connection * node_connection_info[:times]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hybrid_platforms_conductor
3
3
  version: !ruby/object:Gem::Version
4
- version: 32.7.0
4
+ version: 32.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muriel Salvan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-11 00:00:00.000000000 Z
11
+ date: 2021-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: range_operators