Skip to content

Commit 7ca0f8b

Browse files
committed
config: issue an alert on isolated instance
This way it is harder to overlook that the instance is isolated. It is likely important information for a person who performs administration tasks. Closes tarantool#10796 NO_DOC=tarantool/doc#4632 NO_CHANGELOG=added together with the configuration option
1 parent 2ee6dc0 commit 7ca0f8b

File tree

2 files changed

+140
-22
lines changed

2 files changed

+140
-22
lines changed

src/box/lua/config/applier/box_cfg.lua

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,26 @@ end
7171

7272
-- Modify box-level configuration values and perform other actions
7373
-- to enable the isolated mode (if configured).
74-
local function switch_isolated_mode_before_box_cfg(configdata, box_cfg)
74+
local function switch_isolated_mode_before_box_cfg(config, box_cfg)
75+
local configdata = config._configdata
76+
7577
-- If the isolated mode is not enabled, there is nothing to do.
7678
if not configdata:get('isolated', {use_default = true}) then
7779
return
7880
end
7981

82+
-- Issue a warning to highlight the unusual instance status to
83+
-- the administrator.
84+
local key = 'isolated_mode_enabled'
85+
local message = ('The isolated mode is set for the instance %q'):format(
86+
config._instance_name)
87+
config._aboard:set({
88+
type = 'warn',
89+
message = message,
90+
}, {
91+
key = key,
92+
})
93+
8094
-- An application or a role may perform background database
8195
-- modification if the instance is in the RW mode: for
8296
-- example, a role may perform eviction of stale records.
@@ -855,7 +869,7 @@ local function apply(config)
855869

856870
-- RO may be enforced by the isolated mode, so we call the
857871
-- function after all the other logic that may set RW.
858-
switch_isolated_mode_before_box_cfg(configdata, box_cfg)
872+
switch_isolated_mode_before_box_cfg(config, box_cfg)
859873
post_box_cfg_hooks:add(switch_isolated_mode_after_box_cfg, config)
860874

861875
-- First box.cfg() call.

test/config-luatest/isolated_mode_test.lua

Lines changed: 124 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -272,25 +272,25 @@ g.test_iproto_stop_failure = function(g)
272272

273273
-- Verify that an alert is issued.
274274
--
275-
-- The alert is set in background, so let's retry the check
276-
-- until the alert is found.
275+
-- The drop connection alert is set in background, so let's
276+
-- retry the check until the alert is found.
277277
local info
278-
local exp = 'isolated mode: can\'t drop iproto connections during 0 ' ..
278+
local exp_1 = 'The isolated mode is set for the instance "i-001"'
279+
local exp_2 = 'isolated mode: can\'t drop iproto connections during 0 ' ..
279280
'seconds (continued in background): timed out'
280281
t.helpers.retrying({timeout = 60}, function()
281282
info = g.it:roundtrip("require('config'):info()")
282283
t.assert_covers(info, {
283284
alerts = {
284-
{
285-
type = 'warn',
286-
message = exp,
287-
}
285+
{type = 'warn', message = exp_1},
286+
{type = 'warn', message = exp_2},
288287
},
289288
})
290289
end)
291290

292-
-- Only one alert, no duplicates or extra warnings.
293-
t.assert_equals(#info.alerts, 1)
291+
-- Only one drop connection alert, no duplicates or extra
292+
-- warnings.
293+
t.assert_equals(#info.alerts, 2)
294294

295295
-- The existing connection is dropped despite the alert.
296296
t.assert_not(g.conn:ping())
@@ -356,26 +356,27 @@ g.test_iproto_stop_failure_on_startup = function(g)
356356

357357
-- Verify that an alert is issued.
358358
--
359-
-- The alert is set in background, so let's retry the check
360-
-- until the alert is found or a short timeout exceeds
361-
-- (in this case the outer retrying logic will catch it).
362-
local exp = 'isolated mode: can\'t drop iproto connections during 0 ' ..
363-
'seconds (continued in background): timed out'
359+
-- The drop connection alert is set in background, so
360+
-- let's retry the check until the alert is found or a
361+
-- short timeout exceeds (in this case the outer
362+
-- retrying logic will catch it).
363+
local exp_1 = 'The isolated mode is set for the instance "i-001"'
364+
local exp_2 = 'isolated mode: can\'t drop iproto connections during ' ..
365+
'0 seconds (continued in background): timed out'
364366
t.helpers.retrying({timeout = 1}, function()
365367
info = g.it:roundtrip("require('config'):info()")
366368
t.assert_covers(info, {
367369
alerts = {
368-
{
369-
type = 'warn',
370-
message = exp,
371-
}
370+
{type = 'warn', message = exp_1},
371+
{type = 'warn', message = exp_2},
372372
},
373373
})
374374
end)
375375
end)
376376

377-
-- Only one alert, no duplicates or extra warnings.
378-
t.assert_equals(#info.alerts, 1)
377+
-- Only one drop connection alert, no duplicates or extra
378+
-- warnings.
379+
t.assert_equals(#info.alerts, 2)
379380

380381
-- A new connection is not accepted despite the alert.
381382
local uri = cluster['i-001'].net_box_uri
@@ -552,3 +553,106 @@ g.test_replication_from = function(g)
552553
instance_uri('i-003'),
553554
})
554555
end
556+
557+
-- Verify that an alert is issued on an isolated instance.
558+
g.test_alert = function(g)
559+
local config = cbuilder:new()
560+
:add_instance('i-001', {})
561+
:config()
562+
563+
local cluster = cluster.new(g, config)
564+
cluster:start()
565+
566+
-- Connect to the server's console.
567+
g.it = it.connect(cluster['i-001'])
568+
569+
-- Verify a test case prerequisite: no alerts.
570+
local info = g.it:roundtrip("require('config'):info()")
571+
t.assert_equals(info.alerts, {})
572+
573+
-- Go to the isolated mode.
574+
local config_2 = cbuilder:new(config)
575+
:set_instance_option('i-001', 'isolated', true)
576+
:config()
577+
cluster:sync(config_2)
578+
g.it:roundtrip("require('config'):reload()")
579+
580+
-- Verify that the alert is issued.
581+
local exp = 'The isolated mode is set for the instance "i-001"'
582+
local info = g.it:roundtrip("require('config'):info()")
583+
t.assert_covers(info.alerts, {
584+
{type = 'warn', message = exp},
585+
})
586+
587+
-- Only one alert, no duplicates or extra warnings.
588+
t.assert_equals(#info.alerts, 1)
589+
590+
-- Disable the isolated mode on i-001.
591+
local config_3 = cbuilder:new(config_2)
592+
:set_instance_option('i-001', 'isolated', nil)
593+
:config()
594+
cluster:sync(config_3)
595+
g.it:roundtrip("require('config'):reload()")
596+
597+
-- The alert disappears.
598+
local info = g.it:roundtrip("require('config'):info()")
599+
t.assert_equals(info.alerts, {})
600+
end
601+
602+
-- Similar to the previous one, but enables the isolated mode on
603+
-- startup.
604+
--
605+
-- The test case mostly to verify that the alert is not
606+
-- duplicated.
607+
g.test_alert_on_startup = function(g)
608+
local config = cbuilder:new()
609+
:add_instance('i-001', {})
610+
:config()
611+
612+
local cluster = cluster.new(g, config)
613+
cluster:start()
614+
615+
-- Stop i-001. It leaves a local snapshot, so it can be
616+
-- started in the isolated mode.
617+
cluster['i-001']:stop()
618+
619+
-- Enable the isolated mode, write the new config.
620+
local config_2 = cbuilder:new(config)
621+
:set_instance_option('i-001', 'isolated', true)
622+
:config()
623+
cluster:sync(config_2)
624+
625+
-- Start the instance from the local snapshot in the
626+
-- isolated mode.
627+
--
628+
-- Don't check the readiness condition, because it is
629+
-- performed over an iproto connection and it has no
630+
-- chance to succeed (iproto stops listening in the
631+
-- isolated mode).
632+
cluster['i-001']:start({wait_until_ready = false})
633+
634+
-- Use the console connection, because an instance in the
635+
-- isolated mode doesn't accept iproto requests.
636+
connect_console(g, cluster['i-001'])
637+
638+
-- Verify that the alert is issued.
639+
local exp = 'The isolated mode is set for the instance "i-001"'
640+
local info = g.it:roundtrip("require('config'):info()")
641+
t.assert_covers(info.alerts, {
642+
{type = 'warn', message = exp},
643+
})
644+
645+
-- Only one alert, no duplicates or extra warnings.
646+
t.assert_equals(#info.alerts, 1)
647+
648+
-- Disable the isolated mode on i-001.
649+
local config_3 = cbuilder:new(config_2)
650+
:set_instance_option('i-001', 'isolated', nil)
651+
:config()
652+
cluster:sync(config_3)
653+
g.it:roundtrip("require('config'):reload()")
654+
655+
-- The alert disappears.
656+
local info = g.it:roundtrip("require('config'):info()")
657+
t.assert_equals(info.alerts, {})
658+
end

0 commit comments

Comments
 (0)