From aa987a828409f618885413c12457a76cf5f3c369 Mon Sep 17 00:00:00 2001
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date: Fri, 3 Mar 2023 22:57:10 +0100
Subject: [PATCH] schema: replace 'cluster' -> 'replicaset_uuid'

Replicaset UUID was stored in _schema['cluster'] tuple. This is
going to be confusing soon, because there will be introduced an
actual concept of cluster as multiple replicasets.

The patch renames it to 'replicaset_uuid'.

Part of #5029

@TarantoolBot document
Title: Update '_schema' with new 'replicaset_uuid' key

Currently _schema system space is documented to have 'cluster' key
with replicaset UUID value. Now this key is deleted (since 3.0)
and the UUID is stored in 'replicaset_uuid' key.
---
 .../schema-new-replicaset-uuid-key.md         |   6 +++
 src/box/alter.cc                              |  28 +++++++++--
 src/box/bootstrap.snap                        | Bin 4925 -> 4939 bytes
 src/box/box.cc                                |   2 +-
 src/box/lua/upgrade.lua                       |  44 ++++++++++++++++++
 test/box-luatest/downgrade_test.lua           |  22 +++++++++
 test/box-luatest/schema_sys_space_test.lua    |  22 +++++++--
 test/box-luatest/upgrade_to_3_0_0_test.lua    |  28 +++++++++++
 test/box-py/bootstrap.result                  |   2 +-
 test/box/gh-6332-on-replace-schema.result     |   4 +-
 test/box/gh-6332-on-replace-schema.test.lua   |   4 +-
 test/box/info.result                          |   2 +-
 test/box/info.test.lua                        |   2 +-
 test/replication-py/cluster.test.py           |   2 +-
 14 files changed, 152 insertions(+), 16 deletions(-)
 create mode 100644 changelogs/unreleased/schema-new-replicaset-uuid-key.md
 create mode 100644 test/box-luatest/upgrade_to_3_0_0_test.lua

diff --git a/changelogs/unreleased/schema-new-replicaset-uuid-key.md b/changelogs/unreleased/schema-new-replicaset-uuid-key.md
new file mode 100644
index 0000000000..ceb96596d0
--- /dev/null
+++ b/changelogs/unreleased/schema-new-replicaset-uuid-key.md
@@ -0,0 +1,6 @@
+## bugfix/core
+
+* **[Breaking change]** The key `box.space._schema['cluster']` is renamed to
+  `'replicaset_uuid'`. That is not expected to be breaking because `_schema` is
+  an internal system space, but the key was visible in public and documented
+  (gh-5029).
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 2afa6e9491..933d6af302 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -3990,10 +3990,32 @@ on_replace_dd_schema(struct trigger * /* trigger */, void *event)
 					   BOX_SCHEMA_FIELD_KEY);
 	if (key == NULL)
 		return -1;
-	if (strcmp(key, "cluster") == 0) {
+	if (strcmp(key, "cluster") == 0 ||
+	    strcmp(key, "replicaset_uuid") == 0) {
 		if (new_tuple == NULL) {
-			diag_set(ClientError, ER_REPLICASET_UUID_IS_RO);
-			return -1;
+			/*
+			 * At least one of the keys has to stay. Or the
+			 * replicaset UUID would be lost after restart.
+			 */
+			const char *other_key = strcmp(key, "cluster") == 0 ?
+				"replicaset_uuid" : "cluster";
+			char mpkey[64];
+			char *mpkey_end = mp_encode_array(mpkey, 1);
+			mpkey_end = mp_encode_str0(mpkey_end, other_key);
+			struct tuple *other = NULL;
+			if (box_index_get(BOX_SCHEMA_ID, 0, mpkey, mpkey_end,
+					  &other) != 0)
+				return -1;
+			if (other == NULL) {
+				diag_set(ClientError, ER_REPLICASET_UUID_IS_RO);
+				return -1;
+			}
+			/*
+			 * Deletion of the old key is allowed for upgrade.
+			 * Deletion of the new one is needed for downgrade.
+			 * Can't ban either.
+			 */
+			return 0;
 		}
 		tt_uuid uu;
 		if (tuple_field_uuid(new_tuple, BOX_SCHEMA_FIELD_VALUE, &uu) != 0)
diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap
index f5ee0cbbce46b79d3475ff023688d7a2a6e04b95..cf4c66fe37bd845c574d9c8279acf9f84fc472d4 100644
GIT binary patch
literal 4939
zcmV-R6SVA8PC-x#FfK7O3RY!ub7^mGIv_JHFfK4HWo~qGd2nxOZged%FfuJ?GdVLc
zV`epCF$zg;b97;DV`VxZI5lK9Wn(rlEjT$gFfBAWW-%=|Fg7wRH#BBBVL3TDH)Uit
z3RXjGZ)0mZAbWiZ3e~y`y3G>C0M6ZVZ5E{f00000D77#B09fsn0E(vwB}fo>Y10AB
zz%%d+bQ5x;xrbJs0x38Q4FX(9S!+C#baI&Z_m+`pOS#=p?!D#i^0~2<K2LULkZ*{<
zr_G&4yIfUkB672IOA<^1UIGRJ`0)uf;(d--?-7sK)HgDlH?qt(@<yU5Q4*s;NfM(Z
zN{%E+iX%y0ktBEFB}p(ONgGJ+tnJ<o?7d$H_n!G`JPyv#cpGpKWl3C=C3zZbK$2!O
zAjvXjNOG4!8Fa)T19ZFq19U{krweLx$UM>Jj3JY2!t!x(j+il`7)FdJS`bFuRbWBp
zfvF&4kw*cTj71#JiGrHg7bh%w`GQ3`N@88SU@l!So`4I+TPCogmMvDyqQ#0<#FC}&
zu3+iArYrqs^_`Wb8XgI(L?A(EdH)M$^~N2CmiO=bi>FEi5LCJM0SNA;^1!}KRQ6qB
z+IL?EmhNr9fqSPkaPLma6x;J^Qf$wo)odT)Y|m4o)$k-K(eN;kM5alJOcS0c4AjJ+
zM4^c-0HxgEhkjbJd^Zd$_qJWV$@BZJ*pmfpsK65&A}L@)8y+Fu5;(fu5J=#5I{<+<
z;DG-E4ET3afCYC(PAs@9GO}Qn1$Rw~YGFi8Xkko<beZ3<ge_t61T6U<fPnv@0kqJN
z)&dA=9e@DWrX+xC3sQ1z*Onw`Y6?k`si`AKrlx?7{2KxKFJk1MND<D55aC?N5YB@L
zF-;&rOcMYgrfGLS0I2!+5$X-z@1phaA=)gZ|3v%kc=Wh&tFdkChlh#zsl(vsHT(IQ
z$*OML;?8g9BKxQ>@6SaQ=Lt&}T)p82u|{<j%P8n)CaY2tr;L~;FkP-})vLGGl3^JI
z)t{NHN+$c!8$Z9P&IKc&DwFL2S|fDENms!KpC%-D%w%f<z1vMzd$qTt`p9Z8D(a3t
zQ9C>CsPXEsgT|wy4jYBDQM@_m*r^<I>@*HJcDhqI;=t(}aNyL9H*kv6Hr(JS8*OlO
z4K_H+Q8m^;(KOURQ8dy(cW0nc3p3*kT38uopjjgtMn)ODk3k0SVvNB%?_r41I~ZZ~
z{skDl@4Wb;_b$BXeaA%?S-UN`AiEY@kUa}6$WC@FvgrK^EPA)%ir#lsSYbOARoFfS
z6}H>XXNsB~DfrOrL?K1`bHZ!#Enfb8>Dz%KivK5|_;=!o-!<VxEsTjKXkkk*q3hP^
z;~%EP68w`;g8!Z*`19}Wf%>r?)FUwl^-zBV68}aV@n3`y|3nn=KLio~LJaY{AcUyh
z(GvviP98lV4j+tzIQ%~RcYw%){|6xO`|tyP{5|+^pNAgq@4&<T`#S7kACC_9@8Gd-
zU+m82cEmQXV`uZt>D0+*4s`N~Lk{`OXBZClydlh<b8fJwJ>|^dn<t0w9glCm!FJ~U
z0yDSQm$}W|<;B&d<9dyI-j+`1wzSsDX^qpe=`5U0+mL0`HXX-?UPGMTX{e$18ED`#
z%)ogJGH?z<3>gj#IlllW=Ql5uCe|A_SfyE-F1Sh4HZG)BZPL{0s&_V4yB65wtQ`w2
z=)3|8I;*gP&N`={0tzXdfI^vZW#*Z1LahW7#>yQDC5)B35lG;PFaobigt1-X$~9wE
zHL5jZG&N&XV`aGuLCu&hK?p&YAAq1sU8eaUmmZ|a<&+1x%;jyWETwK`xr>r2v&vl>
zWznFiMblA>#-jQDnEzua{sA^y5O;O(qOt9-dw18Ck2*Ig=I58IO9$}#sFDE}i#Xio
z?#6e2OnziXEg0ER%kQIKt|k=#YE(?Wt%~G?-=6K)-)69GF9&tkG&iW*r_|NuY{4&Q
zREJk;+d^&sdkhBR{#av^-+sgI@tnUPXuk~ga=INaA4l8unxp-4-Q)b3mfO?oyBc?N
zbFf>uZCay6M{P3~+V3ZkRRL;L{Brfk2rK<`)u@QuGly|lQa9B2+p0xP;G~~dB_irJ
z{CJfK6K!wa+m^xGB|!`3I=B6EQdVOV$M1N%#=7(N*Mg%j3U&YMs!Nu<Nk3g3BA{E7
zZ*gn1S<H2fZtx59#p0L7qrO{jzO5=WK-9(Q-(Ht~UscJ_X-(Ysb8A^}=dJVB`PET7
zmxZM_?l$KQeqJ?5NYBkSn=`7v$6puCHqG6%#Z}#Ii5oTM{kPU!sgX%_^O`wpUK0FI
zSAlBJa&B`spJ>nN&$#gF5x+*c?s@B4A^t9C&*!?P)mm%X)DV9sy7|aOCA)c(C1|s)
z>-L*(_=T7AE8g(SH;vP;POY`~#z-iDASFqHP;v@Mk|Rifj@)wd{ziambcz_E(IHX<
z-!wky3?Whz6EcJ*7DNb-rc|TZMlm2kYIOhrLi<sBwMS0LvE-By+rBzJevnf=e2`N-
zdXQ7()DMr^toCY;R%@>YvN5tB*{rJeewxUts*I}ke(Db*nFvins36R&{Cx0}CQW_v
zVCH3t>82!w6lIhWp+j9s?d85U@j8R*)2C0LJ@pil-RC#O8s*wNX0qzWXi4*XqMxfx
zOc3Yu@~`@nZ{A!B#My?PTXj~d(bx=auGTk3NwvqO$|#cO?Q_$YE#Q+dW^U9COiwz$
zMBS83cTlqALpd!8c2V*Bs8;`rj=3s(W0ZuQ!i>RPS%vx*Asr!wcITtc@4qc7Lb~Aw
zkEHNvdUC?mCUS}rm8BY$8m&l)2Bnq+rAAAl;Sfhn(~}d<N>83VS8p~N6}jRxJvrfI
zThurTzmG<VBDHNf)S5(Ah0)QNMx2Sb+HVi9GFU^~RcN0&c>1{N88RGr*`RXKfQy-G
zrHqvfm@r_vfa&RKYqms2wlwDFs?CxZr7%hsC{>UICW(S1C!{Y(UaXM19C10C!0Kp=
zk(Mi?EJawZimnhf5m_OUfP70biC{^UB@irmV2H{P)6mjvCgec9vdUA18W5VIM2eDH
zt+XH|*_D-^i$Y<IZc*LKyOs>7_OOhKlC;I?xpB+)Y2MyNHM<~A`F-7w8uxzx(;NTa
z|8A&h7|?OG`Kmoiwpo3@$6nzEwff_*z>ilml&`!&FB_hy-d$j~X6{R0ZqKeTV-keZ
zHMYFJ-r!e?AFqZB%&AXL?5UOGSKsk_4EE(lP9>wjRkxr<dH=eq7o;}hh<X3GDwiWv
z>#9GR!H=t2Nx)5t`N@R9cr#8hKf3~k#i%oMcbY;oGa@1dNeYq<^BPzbm%~m%ZWDmO
z!NP%|k~ugSjieX`%X*A5G$JG-K?{;p3XK6nQa8=xr0)<NQRKlF4%F`EuJ+Ex4k|O7
z+OR=pCsRp_lVw%XRMl=O@RE<F%P~m0OeN`27MXd^`byXh=RMb{jqEY40WFHWrAkM<
zpxue5n6KDUIv1DyFoq+4)kJqdG3e&f^D5XDwoNZb1YCnvWH6~C&CmeFv=NB(+G3>o
zb`5KB3B~yLg)N2)m@OTx62*8rOi}S+JI^pCrMQ%<L}QBswb=UKha7c@GkvQ}*qXVn
zd17Y&+)9WHmu~9+=roLLRXzbgBuwYaQ+FcBdf+)?=^FB?FAJ70)O0AKiK3`_78aNp
ze>_0WZxtZj17L;1ejpnb>7of<`?jy?aA6;$N=s9DUkDYf=EOeGP<i)RL$!j3c|(T!
zlYMHc$OtD<I*)nI|BzkaJhRi|KIh@Y*{2qn)G#WKXyR~in*+st5Gt)rCD<1ap~Bh<
zdQbivveCo1;OzOiHI?^S+lD?h7MBf4kDed?o&k{p$@}*MfJPBlSNtoZM}Gd|>r)*Z
zIfQQ>W2!yWtK;jde^xf0g1OILZWKH+<zz(=@U`*-1=8V>*HV1Wp^++L4ipvI*TS^S
zgz7|Vg9GDO){fHV)2)!0;VT75GtS?<7ZZ*?FrtRRINUTGJ6B?8AgrN5BQt&QIH(VQ
zjAGLTKRgsa_cKu<PS=4;&a@TsC^l-E4>X@A88drjLkAw=YPqJG6&LqJS~ophsFZ=d
znl@qmh-<s2LM&W;9f;Z|Cq<a>J#5Gb`#0Z;TmPjP9hlt4Q1^Uw2!%!&0$Xo$j?f#$
zUx%Es@AU8DH)zl_yfI<Se=|38r9l8E6cPuoGEn1@G0JvWzgB1Otbm7NsfmxV2PGj$
zZN%PyM_qh!E%K?ATPi3q5FAkdJB!!aDdb6o6cy^s4W|D@)Pq4412GKwvlENELotj_
z&)qc_EQ|6WoV5`SIem(|d?qt~^zDsp7}s+%j_2ZI7{G?k$n)C30kA>2BSzSa3~8Gb
z*E#N=dp9$Ja@f(ek5xg)P~rMq0^79$y;|a&suthVkWpGpyq~y$Sc!i=vs7zqiAC~?
zP|`Pe5)68kDB`+MINkJuKb-9sD~A)bj5y!AHO4)QCrm2$%vm&kPRTg=GK(c4jub*%
z&l$`ht37VwfQ9@#p>5J3<w%iB2XClv5VyV5=4{7<4^;-ErZCS`ucA;#BL3eS#ON}I
zZUIn>p5l78zjJ<;fVyxtlFuI6nJirl!|64+qt-_IL$Ei~P&DWD6<9*_95|$BawG~{
zcj0M798c5pa?}(>i7_}gH!~8dV5bXeTRRQ=V+%hml4SUH+xOQB2}UCANS#22G-RHO
znKa!2DT^fF`{b~flKhIE<BIVMRNJI=X)Xvj=NAH7lz<f5A&}uS#|R&%R)vx1C@Jlx
z=&|S>BacYPD#aoYu#~)LD4=#HjI4QD0dZ?W>9Wv2%D0N3s|?N&O<58mzG6WO_&Wd(
z4le*RBsfP<acKZCgutS%7z&Sw&5jjkqo&LxS=YK5nLg9dVhBQ`QXuurjU>rv-7la6
zZ-96MAT_&m99e2)i{f24bADHofu62mFiP10@yWB{Y}AyQB<osx%La#WR-x8vbPUXh
zCBf7dYr=?~G#5(-ux=ajnAhfLY$X{?+gUiC8ANw2wBN#Lnav~cjz3_GgE_m$DZ|DG
zA`2q-LRIG}*29*89nXE@&q_y)7Xr|%PAPU*kW7c@zB)c&+tBt9Q7P^y-Pl401d}q=
zpdv#1fkP5;_!@*k;u(L*8+Us)r&E~52o)Wr5TgiO<dR8aZX`*D>JqTf5qzuZNWBva
z#qUBR1~TQ1pgO-jPgCTgK+q)}5ID(SHs-rofJI7N8vX^q2SNxEw#5jULQ9b7ctH;F
zY&aN&GUj|-^JZlJOh=0$Fol*tsq=z3(%WD#3dPLxa3-6P?3oTNM!*UhiBk6kd5UM_
zU?_^2=i-_+Bl2e*Sd4%vv;>Kc7vvDnhJ#TkW6sAlo1@92taVT==8K4-gaG6&yQE#&
zL?q(P0*VB}ZG>9xz>g@Gb!jmKsZl8q&251cDTEr5t>p9w`qP}jg`6dS%+ZsZGx2rr
zPw|X!)Y}X#1Sa@PgU}Js>)S$oY2bLs?`eFV;f>uqXDjGF7ePCdkOV=DK_$c>6p3}{
zqzzplD%ciUA~c2ABhS#=3XtO76O()k@(dJDM2zp@@TSA53|oddYNo0fMbs;MROM4_
z5hPFQmSSYdL*n5<RpR)TYZ**hXGXF##EZ;~CL2Q(h?MvU+X62Gn5SWxK7*OCn6G%-
z0P!_8YbH1nHanHZ8sVSD>9`pO!kbe%-S6;{T%1z03?62r!k%#^TJ9^}K0t5{+qOxL
zgxyZ1u?$#GV>)iufoOzZb=3&;G|bzkITLL6Rh~AWx{b;5$q$4nUe#SAWct{T;8%s?
ziVF!$!EQqNs_6K7&=}vS?r~CARs@X7t8K)u41W@3*BG1%H0F~Xr<hW-t7vv+&y3(|
z&2gwLTLz{<Q<OL_J4-Ni?NApxrd>1bJT0rVK>EykOAw2;kC_hRDq7|!zKU#P&vmfR
zV955iSU_CaJR{I*RzXZ~7H9GeOo|~0#g4eZvfliq`aNS@&>cKDULjh)ZF@wLU<G9;
ze+qiA41OBdV<wylw)iTC8VM)qYPgs#a^b;R2vMj3M4Gu<DS#gYIJ|619a0L=JE4(4
zn_A`Ipl?1UCRF*=%1W!dxs<*nsE6UH&sF%KMry9f2ZE8l$}J-#ecVUzRntVpA_34-
z2&sNv9FInQyn&+pp+-}CsB#MU{0WH8{EXYHYCSN`H{4vY<M7jLh~RkeHHyV2eA$fu
z81nP6gbRki4}7ygU^CYwa|44I$gpM{2*$kXUyb1PXjx0yyfr7h300s#)1#pu76T-A
zF<Njc7Y&$ZC3X=OMN{j#b}cTJ12{*kL009PX+nxlufunb<hIS&sQl#WFzkypDB<i#
z_zMg8I(63WHnpD__a+(^dj%SZa2OtXXQRvxE`Z}gmxQgwti_V{9C159!xO-9qesHl
zBGzJQ`^TiYmeUvABSxA8FD77=NJ6>B(5kMMHAX^DMoHXS-$Dfx*XF5i(?v&jTx?46
J=>pXdt?g(uQs4jp

delta 4923
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

diff --git a/src/box/box.cc b/src/box/box.cc
index 3110a9d112..315f489bb8 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -4217,7 +4217,7 @@ box_set_replicaset_uuid(void)
 		diag_raise();
 	if (tt_uuid_is_nil(&replicaset_uuid))
 		tt_uuid_create(&replicaset_uuid);
-	if (boxk(IPROTO_INSERT, BOX_SCHEMA_ID, "[%s%s]", "cluster",
+	if (boxk(IPROTO_INSERT, BOX_SCHEMA_ID, "[%s%s]", "replicaset_uuid",
 		 tt_uuid_str(&replicaset_uuid)))
 		diag_raise();
 }
diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index 7607212ff0..8e36a50598 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -1399,6 +1399,30 @@ end
 local function upgrade_to_2_11_1()
     drop_schema_max_id()
 end
+
+--------------------------------------------------------------------------------
+-- Tarantool 3.0.0
+--------------------------------------------------------------------------------
+local function change_replicaset_uuid_key(old_key, new_key)
+    local _schema = box.space._schema
+    local old = _schema:get{old_key}
+    -- 'replicaset_uuid' can be not found during bootstrap.snap generation when
+    -- the entire _schema is cleared.
+    if old ~= nil then
+        _schema:insert{new_key, old[2]}
+        _schema:delete{old_key}
+    end
+end
+
+local function store_replicaset_uuid_in_new_way()
+    log.info('update replicaset uuid key')
+    change_replicaset_uuid_key('cluster', 'replicaset_uuid')
+end
+
+local function upgrade_to_3_0_0()
+    store_replicaset_uuid_in_new_way()
+end
+
 --------------------------------------------------------------------------------
 
 local handlers = {
@@ -1421,6 +1445,7 @@ local handlers = {
     {version = mkversion(2, 10, 5), func = upgrade_to_2_10_5},
     {version = mkversion(2, 11, 0), func = upgrade_to_2_11_0},
     {version = mkversion(2, 11, 1), func = upgrade_to_2_11_1},
+    {version = mkversion(3, 0, 0), func = upgrade_to_3_0_0},
 }
 
 -- Schema version of the snapshot.
@@ -1913,6 +1938,23 @@ local function downgrade_from_2_11_1(issue_handler)
     add_schema_max_id(issue_handler)
 end
 
+--------------------------------------------------------------------------------
+-- Tarantool 3.0.0
+--------------------------------------------------------------------------------
+
+-- Revert store_replicaset_uuid_in_new_way().
+local function store_replicaset_uuid_in_old_way(issue_handler)
+    if issue_handler.dry_run then
+        return
+    end
+    log.info('drop replicaset uuid key')
+    change_replicaset_uuid_key('replicaset_uuid', 'cluster')
+end
+
+local function downgrade_from_3_0_0(issue_handler)
+    store_replicaset_uuid_in_old_way(issue_handler)
+end
+
 -- Versions should be ordered from newer to older.
 --
 -- Every step can be called in 2 modes. In dry_run mode (issue_handler.dry_run
@@ -1930,6 +1972,7 @@ end
 -- if schema version is 2.10.0.
 --
 local downgrade_handlers = {
+    {version = mkversion(3, 0, 0), func = downgrade_from_3_0_0},
     {version = mkversion(2, 11, 1), func = downgrade_from_2_11_1},
     {version = mkversion(2, 11, 0), func = downgrade_from_2_11_0},
     {version = mkversion(2, 10, 5), func = downgrade_from_2_10_5},
@@ -2011,6 +2054,7 @@ local downgrade_versions = {
     "2.10.5",
     "2.11.0",
     "2.11.1",
+    "3.0.0",
 }
 
 -- Downgrade or list downgrade issues depending of dry_run argument value.
diff --git a/test/box-luatest/downgrade_test.lua b/test/box-luatest/downgrade_test.lua
index 2559415e99..71b2f28590 100644
--- a/test/box-luatest/downgrade_test.lua
+++ b/test/box-luatest/downgrade_test.lua
@@ -887,3 +887,25 @@ g.test_downgrade_schema_max_id = function(cg)
         check_max_id(space_id)
     end)
 end
+
+-----------------------------
+-- Check downgrade from 3.0.0
+-----------------------------
+
+g.test_downgrade_replicaset_uuid_key = function(cg)
+    cg.server:exec(function()
+        local helper = require('test.box-luatest.downgrade_helper')
+        local _schema = box.space._schema
+        local rs_uuid = box.info.cluster.uuid
+        local prev_version = helper.prev_version(helper.app_version('3.0.0'))
+        t.assert_equals(box.schema.downgrade_issues(prev_version), {})
+        t.assert_equals(_schema:get{'cluster'}, nil)
+        t.assert_equals(_schema:get{'replicaset_uuid'}.value, rs_uuid)
+        -- 2 for idempotence.
+        for _ = 1, 2 do
+            box.schema.downgrade(prev_version)
+            t.assert_equals(_schema:get{'cluster'}.value, rs_uuid)
+            t.assert_equals(_schema:get{'replicaset_uuid'}, nil)
+        end
+    end)
+end
diff --git a/test/box-luatest/schema_sys_space_test.lua b/test/box-luatest/schema_sys_space_test.lua
index 678f7c7e8d..52eaba8db3 100644
--- a/test/box-luatest/schema_sys_space_test.lua
+++ b/test/box-luatest/schema_sys_space_test.lua
@@ -11,17 +11,17 @@ g.after_all = function(lg)
     lg.server:drop()
 end
 
-g.test_cluster_uuid_update_ban = function(lg)
+g.test_replicaset_uuid_update_ban = function(lg)
     lg.server:exec(function()
         local uuid = require('uuid')
         local _schema = box.space._schema
         local msg = "Can't reset replica set UUID"
         t.assert_error_msg_contains(msg, _schema.replace, _schema,
-                                    {'cluster', uuid.str()})
+                                    {'replicaset_uuid', uuid.str()})
         t.assert_error_msg_contains(msg, _schema.replace, _schema,
-                                    {'cluster', tostring(uuid.NULL)})
+                                    {'replicaset_uuid', tostring(uuid.NULL)})
         -- Fine to replace with the same value.
-        _schema:replace{'cluster', box.info.cluster.uuid}
+        _schema:replace{'replicaset_uuid', box.info.cluster.uuid}
     end)
 end
 
@@ -40,3 +40,17 @@ g.test_version_transactional = function(lg)
         t.assert_equals(dd_version, ffi.C.box_dd_version_id())
     end)
 end
+
+g.test_old_cluster_uuid_key = function(lg)
+    lg.server:exec(function()
+        local uuid = require('uuid')
+        local _schema = box.space._schema
+        -- It still can be inserted and is validated.
+        t.assert_equals(_schema:get{'cluster'}, nil)
+        local msg = "Can't reset replica set UUID"
+        t.assert_error_msg_contains(msg, _schema.replace, _schema,
+                                    {'cluster', uuid.str()})
+        _schema:replace{'cluster', box.info.cluster.uuid}
+        _schema:delete{'cluster'}
+    end)
+end
diff --git a/test/box-luatest/upgrade_to_3_0_0_test.lua b/test/box-luatest/upgrade_to_3_0_0_test.lua
new file mode 100644
index 0000000000..b338f1a9c2
--- /dev/null
+++ b/test/box-luatest/upgrade_to_3_0_0_test.lua
@@ -0,0 +1,28 @@
+local server = require('luatest.server')
+local t = require('luatest')
+
+local g = t.group("Upgrade to 3.0.0")
+
+g.before_all(function(cg)
+    cg.server = server:new({
+        datadir = 'test/box-luatest/upgrade/2.11.0',
+    })
+    cg.server:start()
+    cg.server:exec(function()
+        t.assert_equals(box.space._schema:get{'version'}, {'version', 2, 11, 0})
+        box.schema.upgrade()
+    end)
+end)
+
+g.after_all(function(cg)
+    cg.server:drop()
+end)
+
+g.test_new_replicaset_uuid_key = function(cg)
+    cg.server:exec(function()
+        local _schema = box.space._schema
+        t.assert_equals(_schema:get{'cluster'}, nil)
+        t.assert_equals(_schema:get{'replicaset_uuid'}.value,
+                        box.info.cluster.uuid)
+    end)
+end
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index a5ca5d40fd..e81c49dcac 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -3,7 +3,7 @@ box.internal.bootstrap()
 ...
 box.space._schema:select{}
 ---
-- - ['version', 2, 11, 1]
+- - ['version', 3, 0, 0]
 ...
 box.space._cluster:select{}
 ---
diff --git a/test/box/gh-6332-on-replace-schema.result b/test/box/gh-6332-on-replace-schema.result
index ded742ba80..df549e2dd7 100644
--- a/test/box/gh-6332-on-replace-schema.result
+++ b/test/box/gh-6332-on-replace-schema.result
@@ -30,11 +30,11 @@ box.space._schema:replace{'version', 123}
  | ---
  | - error: 'Wrong _schema version: expected ''major.minor[.patch]'''
  | ...
-box.space._schema:replace{'cluster'}
+box.space._schema:replace{'replicaset_uuid'}
  | ---
  | - error: 'Invalid UUID: (null)'
  | ...
-box.space._schema:replace{'cluster', 666}
+box.space._schema:replace{'replicaset_uuid', 666}
  | ---
  | - error: 'Invalid UUID: (null)'
  | ...
diff --git a/test/box/gh-6332-on-replace-schema.test.lua b/test/box/gh-6332-on-replace-schema.test.lua
index e52e605c5f..0ba28bb1d7 100644
--- a/test/box/gh-6332-on-replace-schema.test.lua
+++ b/test/box/gh-6332-on-replace-schema.test.lua
@@ -10,8 +10,8 @@ test_run:cmd("switch test")
 
 box.space._schema:replace{'version'}
 box.space._schema:replace{'version', 123}
-box.space._schema:replace{'cluster'}
-box.space._schema:replace{'cluster', 666}
+box.space._schema:replace{'replicaset_uuid'}
+box.space._schema:replace{'replicaset_uuid', 666}
 box.space._schema:replace{'asd'}
 box.space._schema:replace{666}
 
diff --git a/test/box/info.result b/test/box/info.result
index a7444cad39..17c365a601 100644
--- a/test/box/info.result
+++ b/test/box/info.result
@@ -59,7 +59,7 @@ string.match(box.info.uptime, '^[1-9][0-9]*$') ~= nil
 ---
 - true
 ...
-box.info.cluster.uuid == box.space._schema:get{'cluster'}[2]
+box.info.cluster.uuid == box.space._schema:get{'replicaset_uuid'}[2]
 ---
 - true
 ...
diff --git a/test/box/info.test.lua b/test/box/info.test.lua
index 60ee3216dc..66935af10f 100644
--- a/test/box/info.test.lua
+++ b/test/box/info.test.lua
@@ -16,7 +16,7 @@ box.info.replication[1].id
 box.info.status
 string.len(box.info.uptime) > 0
 string.match(box.info.uptime, '^[1-9][0-9]*$') ~= nil
-box.info.cluster.uuid == box.space._schema:get{'cluster'}[2]
+box.info.cluster.uuid == box.space._schema:get{'replicaset_uuid'}[2]
 t = {}
 for k, _ in pairs(box.info()) do table.insert(t, k) end
 table.sort(t)
diff --git a/test/replication-py/cluster.test.py b/test/replication-py/cluster.test.py
index 1f36511ede..a84e490992 100644
--- a/test/replication-py/cluster.test.py
+++ b/test/replication-py/cluster.test.py
@@ -8,7 +8,7 @@ from lib.tarantool_server import TarantoolServer
 ## Get cluster uuid
 cluster_uuid = ""
 try:
-    cluster_uuid = yaml.safe_load(server.admin("box.space._schema:get('cluster')",
+    cluster_uuid = yaml.safe_load(server.admin("box.space._schema:get('replicaset_uuid')",
         silent = True))[0][1]
     uuid.UUID("{" + cluster_uuid + "}")
     print("ok - cluster uuid")
-- 
GitLab