@@ -27,6 +27,19 @@ local fiber = require('fiber')
2727
2828local utils = {}
2929
30+ --- Returns a full call string for a storage function name.
31+ --
32+ -- @param string name a base name of the storage function.
33+ --
34+ -- @return a full string for the call.
35+ function utils .get_storage_call (name )
36+ dev_checks (' string' )
37+
38+ return ' _crud.' .. name
39+ end
40+
41+ local CRUD_STORAGE_INFO_FUNC_NAME = utils .get_storage_call (' storage_info_on_storage' )
42+
3043local space_format_cache = setmetatable ({}, {__mode = ' k' })
3144
3245-- copy from LuaJIT lj_char.c
@@ -1034,8 +1047,11 @@ function utils.update_storage_call_error_description(err, func_name, replicaset_
10341047 return nil
10351048 end
10361049
1037- if err .type == ' ClientError' and type (err .message ) == ' string' then
1038- if err .message == string.format (" Procedure '%s' is not defined" , func_name ) then
1050+ if (err .type == ' ClientError' or err .type == ' AccessDeniedError' )
1051+ and type (err .message ) == ' string' then
1052+ local not_defined_str = string.format (" Procedure '%s' is not defined" , func_name )
1053+ local access_denied_str = string.format (" Execute access to function '%s' is denied" , func_name )
1054+ if err .message == not_defined_str or err .message :startswith (access_denied_str ) then
10391055 if func_name :startswith (' _crud.' ) then
10401056 err = NotInitializedError :new (" Function %s is not registered: " ..
10411057 " crud isn't initialized on replicaset %q or crud module versions mismatch " ..
@@ -1121,7 +1137,7 @@ function utils.storage_info(opts)
11211137 status = " error" ,
11221138 is_master = replicaset .master == replica
11231139 }
1124- local ok , res = pcall (replica .conn .call , replica .conn , " _crud.storage_info_on_storage " ,
1140+ local ok , res = pcall (replica .conn .call , replica .conn , CRUD_STORAGE_INFO_FUNC_NAME ,
11251141 {}, async_opts )
11261142 if ok then
11271143 futures_by_replicas [replica_uuid ] = res
@@ -1177,6 +1193,30 @@ function utils.storage_info_on_storage()
11771193 return {status = " running" }
11781194end
11791195
1196+ --- Initializes a storage function by its name.
1197+ --
1198+ -- It adds the function into the global scope by its name and required
1199+ -- access to a vshard storage user.
1200+ --
1201+ -- @function init_storage_call
1202+ --
1203+ -- @param string name of a user or nil if there is no need to setup access.
1204+ -- @param string name a name of the function.
1205+ -- @param function func the function.
1206+ --
1207+ -- @return nil
1208+ function utils .init_storage_call (user , name , func )
1209+ dev_checks (' ?string' , ' string' , ' function' )
1210+
1211+ rawset (_G [' _crud' ], name , func )
1212+
1213+ if user ~= nil then
1214+ name = utils .get_storage_call (name )
1215+ box .schema .func .create (name , {setuid = true , if_not_exists = true })
1216+ box .schema .user .grant (user , ' execute' , ' function' , name , {if_not_exists = true })
1217+ end
1218+ end
1219+
11801220local expected_vshard_api = {
11811221 ' routeall' , ' route' , ' bucket_id_strcrc32' ,
11821222 ' callrw' , ' callro' , ' callbro' , ' callre' ,
0 commit comments