4 #include "common/dout.h"
5 #include "services/svc_zone.h"
6 #include "rgw_lua_utils.h"
8 #include "rgw_common.h"
10 #include "rgw_process.h"
13 #include "rgw_sal_rados.h"
15 #define dout_subsys ceph_subsys_rgw
17 namespace rgw::lua::request
{
19 // closure that perform ops log action
23 constexpr const char* RequestLogAction
{"Log"};
25 int RequestLog(lua_State
* L
)
27 const auto store
= reinterpret_cast<rgw::sal::RGWRadosStore
*>(lua_touserdata(L
, lua_upvalueindex(1)));
28 const auto rest
= reinterpret_cast<RGWREST
*>(lua_touserdata(L
, lua_upvalueindex(2)));
29 const auto olog
= reinterpret_cast<OpsLogSocket
*>(lua_touserdata(L
, lua_upvalueindex(3)));
30 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(4)));
31 const std::string
op_name(reinterpret_cast<const char*>(lua_touserdata(L
, lua_upvalueindex(5))));
33 const auto rc
= rgw_log_op(store
->getRados(), rest
, s
, op_name
, olog
);
34 lua_pushinteger(L
, rc
);
36 ldpp_dout(s
, 1) << "Lua ERROR: missing rados store, cannot use ops log" << dendl
;
37 lua_pushinteger(L
, -EINVAL
);
43 struct ResponseMetaTable
: public EmptyMetaTable
{
44 static std::string
TableName() {return "Response";}
45 static std::string
Name() {return TableName() + "Meta";}
47 static int IndexClosure(lua_State
* L
) {
48 const auto err
= reinterpret_cast<const rgw_err
*>(lua_touserdata(L
, lua_upvalueindex(1)));
50 const char* index
= luaL_checkstring(L
, 2);
52 if (strcasecmp(index
, "HTTPStatusCode") == 0) {
53 lua_pushinteger(L
, err
->http_ret
);
54 } else if (strcasecmp(index
, "RGWCode") == 0) {
55 lua_pushinteger(L
, err
->ret
);
56 } else if (strcasecmp(index
, "HTTPStatus") == 0) {
57 pushstring(L
, err
->err_code
);
58 } else if (strcasecmp(index
, "Message") == 0) {
59 pushstring(L
, err
->message
);
61 throw_unknown_field(index
, TableName());
66 static int NewIndexClosure(lua_State
* L
) {
67 auto err
= reinterpret_cast<rgw_err
*>(lua_touserdata(L
, lua_upvalueindex(1)));
69 const char* index
= luaL_checkstring(L
, 2);
71 if (strcasecmp(index
, "HTTPStatusCode") == 0) {
72 err
->http_ret
= luaL_checkinteger(L
, 3);
73 } else if (strcasecmp(index
, "RGWCode") == 0) {
74 err
->ret
= luaL_checkinteger(L
, 3);
75 } else if (strcasecmp(index
, "HTTPStatus") == 0) {
76 err
->err_code
.assign(luaL_checkstring(L
, 3));
77 } else if (strcasecmp(index
, "Message") == 0) {
78 err
->message
.assign(luaL_checkstring(L
, 3));
80 throw_unknown_field(index
, TableName());
86 struct QuotaMetaTable
: public EmptyMetaTable
{
87 static std::string
TableName() {return "Quota";}
88 static std::string
Name() {return TableName() + "Meta";}
90 static int IndexClosure(lua_State
* L
) {
91 const auto info
= reinterpret_cast<RGWQuotaInfo
*>(lua_touserdata(L
, lua_upvalueindex(1)));
93 const char* index
= luaL_checkstring(L
, 2);
95 if (strcasecmp(index
, "MaxSize") == 0) {
96 lua_pushinteger(L
, info
->max_size
);
97 } else if (strcasecmp(index
, "MaxObjects") == 0) {
98 lua_pushinteger(L
, info
->max_objects
);
99 } else if (strcasecmp(index
, "Enabled") == 0) {
100 lua_pushboolean(L
, info
->enabled
);
101 } else if (strcasecmp(index
, "Rounded") == 0) {
102 lua_pushboolean(L
, !info
->check_on_raw
);
104 throw_unknown_field(index
, TableName());
106 return ONE_RETURNVAL
;
110 struct PlacementRuleMetaTable
: public EmptyMetaTable
{
111 static std::string
TableName() {return "PlacementRule";}
112 static std::string
Name() {return TableName() + "Meta";}
114 static int IndexClosure(lua_State
* L
) {
115 const auto rule
= reinterpret_cast<rgw_placement_rule
*>(lua_touserdata(L
, lua_upvalueindex(1)));
117 const char* index
= luaL_checkstring(L
, 2);
119 if (strcasecmp(index
, "Name") == 0) {
120 pushstring(L
, rule
->name
);
121 } else if (strcasecmp(index
, "StorageClass") == 0) {
122 pushstring(L
, rule
->storage_class
);
124 throw_unknown_field(index
, TableName());
126 return ONE_RETURNVAL
;
130 struct UserMetaTable
: public EmptyMetaTable
{
131 static std::string
TableName() {return "User";}
132 static std::string
Name() {return TableName() + "Meta";}
134 static int IndexClosure(lua_State
* L
) {
135 const auto user
= reinterpret_cast<const rgw_user
*>(lua_touserdata(L
, lua_upvalueindex(1)));
137 const char* index
= luaL_checkstring(L
, 2);
139 if (strcasecmp(index
, "Tenant") == 0) {
140 pushstring(L
, user
->tenant
);
141 } else if (strcasecmp(index
, "Id") == 0) {
142 pushstring(L
, user
->id
);
144 throw_unknown_field(index
, TableName());
146 return ONE_RETURNVAL
;
150 struct OwnerMetaTable
: public EmptyMetaTable
{
151 static std::string
TableName() {return "Owner";}
152 static std::string
Name() {return TableName() + "Meta";}
154 static int IndexClosure(lua_State
* L
) {
155 const auto owner
= reinterpret_cast<ACLOwner
*>(lua_touserdata(L
, lua_upvalueindex(1)));
157 const char* index
= luaL_checkstring(L
, 2);
159 if (strcasecmp(index
, "DisplayName") == 0) {
160 pushstring(L
, owner
->get_display_name());
161 } else if (strcasecmp(index
, "User") == 0) {
162 create_metatable
<UserMetaTable
>(L
, false, &(owner
->get_id()));
164 throw_unknown_field(index
, TableName());
166 return ONE_RETURNVAL
;
170 struct BucketMetaTable
: public EmptyMetaTable
{
171 static std::string
TableName() {return "Bucket";}
172 static std::string
Name() {return TableName() + "Meta";}
174 using Type
= rgw::sal::RGWBucket
;
176 static int IndexClosure(lua_State
* L
) {
177 const auto bucket
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
179 const char* index
= luaL_checkstring(L
, 2);
181 if (strcasecmp(index
, "Tenant") == 0) {
182 pushstring(L
, bucket
->get_tenant());
183 } else if (strcasecmp(index
, "Name") == 0) {
184 pushstring(L
, bucket
->get_name());
185 } else if (strcasecmp(index
, "Marker") == 0) {
186 pushstring(L
, bucket
->get_marker());
187 } else if (strcasecmp(index
, "Id") == 0) {
188 pushstring(L
, bucket
->get_bucket_id());
189 } else if (strcasecmp(index
, "Count") == 0) {
190 lua_pushinteger(L
, bucket
->get_count());
191 } else if (strcasecmp(index
, "Size") == 0) {
192 lua_pushinteger(L
, bucket
->get_size());
193 } else if (strcasecmp(index
, "ZoneGroupId") == 0) {
194 pushstring(L
, bucket
->get_info().zonegroup
);
195 } else if (strcasecmp(index
, "CreationTime") == 0) {
196 pushtime(L
, bucket
->get_creation_time());
197 } else if (strcasecmp(index
, "MTime") == 0) {
198 pushtime(L
, bucket
->get_modification_time());
199 } else if (strcasecmp(index
, "Quota") == 0) {
200 create_metatable
<QuotaMetaTable
>(L
, false, &(bucket
->get_info().quota
));
201 } else if (strcasecmp(index
, "PlacementRule") == 0) {
202 create_metatable
<PlacementRuleMetaTable
>(L
, false, &(bucket
->get_info().placement_rule
));
203 } else if (strcasecmp(index
, "User") == 0) {
204 create_metatable
<UserMetaTable
>(L
, false, &(bucket
->get_info().owner
));
206 throw_unknown_field(index
, TableName());
208 return ONE_RETURNVAL
;
212 struct ObjectMetaTable
: public EmptyMetaTable
{
213 static const std::string
TableName() {return "Object";}
214 static std::string
Name() {return TableName() + "Meta";}
216 using Type
= rgw::sal::RGWObject
;
218 static int IndexClosure(lua_State
* L
) {
219 const auto obj
= reinterpret_cast<const Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
221 const char* index
= luaL_checkstring(L
, 2);
223 if (strcasecmp(index
, "Name") == 0) {
224 pushstring(L
, obj
->get_name());
225 } else if (strcasecmp(index
, "Instance") == 0) {
226 pushstring(L
, obj
->get_instance());
227 } else if (strcasecmp(index
, "Id") == 0) {
228 pushstring(L
, obj
->get_oid());
229 } else if (strcasecmp(index
, "Size") == 0) {
230 lua_pushinteger(L
, obj
->get_obj_size());
231 } else if (strcasecmp(index
, "MTime") == 0) {
232 pushtime(L
, obj
->get_mtime());
234 throw_unknown_field(index
, TableName());
236 return ONE_RETURNVAL
;
240 typedef int MetaTableClosure(lua_State
* L
);
242 template<typename MapType
>
243 int StringMapWriteableNewIndex(lua_State
* L
) {
244 const auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
246 const char* index
= luaL_checkstring(L
, 2);
247 const char* value
= luaL_checkstring(L
, 3);
248 map
->insert_or_assign(index
, value
);
252 template<typename MapType
=std::map
<std::string
, std::string
>,
253 MetaTableClosure NewIndex
=EmptyMetaTable::NewIndexClosure
>
254 struct StringMapMetaTable
: public EmptyMetaTable
{
256 static std::string
TableName() {return "StringMap";}
257 static std::string
Name() {return TableName() + "Meta";}
259 static int IndexClosure(lua_State
* L
) {
260 const auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
262 const char* index
= luaL_checkstring(L
, 2);
264 const auto it
= map
->find(std::string(index
));
265 if (it
== map
->end()) {
268 pushstring(L
, it
->second
);
270 return ONE_RETURNVAL
;
273 static int NewIndexClosure(lua_State
* L
) {
277 static int PairsClosure(lua_State
* L
) {
278 auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
280 lua_pushlightuserdata(L
, map
);
281 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
282 lua_pushnil(L
); // indicate this is the first call
283 // return stateless_iter, nil
285 return TWO_RETURNVALS
;
288 static int stateless_iter(lua_State
* L
) {
289 // based on: http://lua-users.org/wiki/GeneralizedPairsAndIpairs
290 auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
291 typename
MapType::const_iterator next_it
;
292 if (lua_isnil(L
, -1)) {
293 next_it
= map
->begin();
295 const char* index
= luaL_checkstring(L
, 2);
296 const auto it
= map
->find(std::string(index
));
297 ceph_assert(it
!= map
->end());
298 next_it
= std::next(it
);
301 if (next_it
== map
->end()) {
302 // index of the last element was provided
307 pushstring(L
, next_it
->first
);
308 pushstring(L
, next_it
->second
);
312 return TWO_RETURNVALS
;
315 static int LenClosure(lua_State
* L
) {
316 const auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
318 lua_pushinteger(L
, map
->size());
320 return ONE_RETURNVAL
;
324 struct GrantMetaTable
: public EmptyMetaTable
{
325 static std::string
TableName() {return "Grant";}
326 static std::string
Name() {return TableName() + "Meta";}
328 static int IndexClosure(lua_State
* L
) {
329 const auto grant
= reinterpret_cast<ACLGrant
*>(lua_touserdata(L
, lua_upvalueindex(1)));
331 const char* index
= luaL_checkstring(L
, 2);
333 if (strcasecmp(index
, "Type") == 0) {
334 lua_pushinteger(L
, grant
->get_type().get_type());
335 } else if (strcasecmp(index
, "User") == 0) {
336 const auto id_ptr
= grant
->get_id();
338 create_metatable
<UserMetaTable
>(L
, false, const_cast<rgw_user
*>(id_ptr
));
342 } else if (strcasecmp(index
, "Permission") == 0) {
343 lua_pushinteger(L
, grant
->get_permission().get_permissions());
344 } else if (strcasecmp(index
, "GroupType") == 0) {
345 lua_pushinteger(L
, grant
->get_group());
346 } else if (strcasecmp(index
, "Referer") == 0) {
347 pushstring(L
, grant
->get_referer());
349 throw_unknown_field(index
, TableName());
351 return ONE_RETURNVAL
;
355 struct GrantsMetaTable
: public EmptyMetaTable
{
356 static std::string
TableName() {return "Grants";}
357 static std::string
Name() {return TableName() + "Meta";}
359 static int IndexClosure(lua_State
* L
) {
360 const auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
362 const char* index
= luaL_checkstring(L
, 2);
364 const auto it
= map
->find(std::string(index
));
365 if (it
== map
->end()) {
368 create_metatable
<GrantMetaTable
>(L
, false, &(it
->second
));
370 return ONE_RETURNVAL
;
373 static int PairsClosure(lua_State
* L
) {
374 auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
376 lua_pushlightuserdata(L
, map
);
377 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
378 lua_pushnil(L
); // indicate this is the first call
379 // return stateless_iter, nil
381 return TWO_RETURNVALS
;
384 static int stateless_iter(lua_State
* L
) {
385 // based on: http://lua-users.org/wiki/GeneralizedPairsAndIpairs
386 auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
387 ACLGrantMap::iterator next_it
;
388 if (lua_isnil(L
, -1)) {
389 next_it
= map
->begin();
391 const char* index
= luaL_checkstring(L
, 2);
392 const auto it
= map
->find(std::string(index
));
393 ceph_assert(it
!= map
->end());
394 next_it
= std::next(it
);
397 if (next_it
== map
->end()) {
398 // index of the last element was provided
401 return TWO_RETURNVALS
;
405 while (next_it
->first
.empty()) {
406 // this is a multimap and the next element does not have a unique key
408 if (next_it
== map
->end()) {
409 // index of the last element was provided
412 return TWO_RETURNVALS
;
417 pushstring(L
, next_it
->first
);
418 create_metatable
<GrantMetaTable
>(L
, false, &(next_it
->second
));
421 return TWO_RETURNVALS
;
424 static int LenClosure(lua_State
* L
) {
425 const auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
427 lua_pushinteger(L
, map
->size());
429 return ONE_RETURNVAL
;
433 struct ACLMetaTable
: public EmptyMetaTable
{
434 static std::string
TableName() {return "ACL";}
435 static std::string
Name() {return TableName() + "Meta";}
437 using Type
= RGWAccessControlPolicy
;
439 static int IndexClosure(lua_State
* L
) {
440 const auto acl
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
442 const char* index
= luaL_checkstring(L
, 2);
444 if (strcasecmp(index
, "Owner") == 0) {
445 create_metatable
<OwnerMetaTable
>(L
, false, &(acl
->get_owner()));
446 } else if (strcasecmp(index
, "Grants") == 0) {
447 create_metatable
<GrantsMetaTable
>(L
, false, &(acl
->get_acl().get_grant_map()));
449 throw_unknown_field(index
, TableName());
451 return ONE_RETURNVAL
;
455 struct StatementsMetaTable
: public EmptyMetaTable
{
456 static std::string
TableName() {return "Statements";}
457 static std::string
Name() {return TableName() + "Meta";}
459 using Type
= std::vector
<rgw::IAM::Statement
>;
461 static std::string
statement_to_string(const rgw::IAM::Statement
& statement
) {
462 std::stringstream ss
;
467 static int IndexClosure(lua_State
* L
) {
468 const auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
470 const auto index
= luaL_checkinteger(L
, 2);
472 if (index
>= (int)statements
->size() || index
< 0) {
475 // TODO: policy language could be interpreted to lua and executed as such
476 pushstring(L
, statement_to_string((*statements
)[index
]));
478 return ONE_RETURNVAL
;
481 static int PairsClosure(lua_State
* L
) {
482 auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
483 ceph_assert(statements
);
484 lua_pushlightuserdata(L
, statements
);
485 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
486 lua_pushnil(L
); // indicate this is the first call
487 // return stateless_iter, nil
489 return TWO_RETURNVALS
;
492 static int stateless_iter(lua_State
* L
) {
493 auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
495 if (lua_isnil(L
, -1)) {
498 const auto it
= luaL_checkinteger(L
, -1);
502 if (next_it
>= statements
->size()) {
503 // index of the last element was provided
508 lua_pushinteger(L
, next_it
);
509 pushstring(L
, statement_to_string((*statements
)[next_it
]));
513 return TWO_RETURNVALS
;
516 static int LenClosure(lua_State
* L
) {
517 const auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
519 lua_pushinteger(L
, statements
->size());
521 return ONE_RETURNVAL
;
525 struct PolicyMetaTable
: public EmptyMetaTable
{
526 static std::string
TableName() {return "Policy";}
527 static std::string
Name() {return TableName() + "Meta";}
529 static int IndexClosure(lua_State
* L
) {
530 const auto policy
= reinterpret_cast<rgw::IAM::Policy
*>(lua_touserdata(L
, lua_upvalueindex(1)));
532 const char* index
= luaL_checkstring(L
, 2);
534 if (strcasecmp(index
, "Text") == 0) {
535 pushstring(L
, policy
->text
);
536 } else if (strcasecmp(index
, "Id") == 0) {
537 // TODO create pushstring for std::unique_ptr
541 pushstring(L
, policy
->id
.get());
543 } else if (strcasecmp(index
, "Statements") == 0) {
544 create_metatable
<StatementsMetaTable
>(L
, &(policy
->statements
));
546 throw_unknown_field(index
, TableName());
548 return ONE_RETURNVAL
;
552 struct PoliciesMetaTable
: public EmptyMetaTable
{
553 static std::string
TableName() {return "Policies";}
554 static std::string
Name() {return TableName() + "Meta";}
556 using Type
= std::vector
<rgw::IAM::Policy
>;
558 static int IndexClosure(lua_State
* L
) {
559 const auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
561 const auto index
= luaL_checkinteger(L
, 2);
563 if (index
>= (int)policies
->size() || index
< 0) {
566 create_metatable
<PolicyMetaTable
>(L
, false, &((*policies
)[index
]));
568 return ONE_RETURNVAL
;
571 static int PairsClosure(lua_State
* L
) {
572 auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
573 ceph_assert(policies
);
574 lua_pushlightuserdata(L
, policies
);
575 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
576 lua_pushnil(L
); // indicate this is the first call
577 // return stateless_iter, nil
579 return TWO_RETURNVALS
;
582 static int stateless_iter(lua_State
* L
) {
583 auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
585 if (lua_isnil(L
, -1)) {
588 ceph_assert(lua_isinteger(L
, -1));
589 const auto it
= luaL_checkinteger(L
, -1);
593 if (next_it
>= policies
->size()) {
594 // index of the last element was provided
599 lua_pushinteger(L
, next_it
);
600 create_metatable
<PolicyMetaTable
>(L
, false, &((*policies
)[next_it
]));
604 return TWO_RETURNVALS
;
607 static int LenClosure(lua_State
* L
) {
608 const auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
610 lua_pushinteger(L
, policies
->size());
612 return ONE_RETURNVAL
;
616 struct HTTPMetaTable
: public EmptyMetaTable
{
617 static std::string
TableName() {return "HTTP";}
618 static std::string
Name() {return TableName() + "Meta";}
620 static int IndexClosure(lua_State
* L
) {
621 const auto info
= reinterpret_cast<req_info
*>(lua_touserdata(L
, lua_upvalueindex(1)));
623 const char* index
= luaL_checkstring(L
, 2);
625 if (strcasecmp(index
, "Parameters") == 0) {
626 create_metatable
<StringMapMetaTable
<>>(L
, false, &(info
->args
.get_params()));
627 } else if (strcasecmp(index
, "Resources") == 0) {
628 // TODO: add non-const api to get resources
629 create_metatable
<StringMapMetaTable
<>>(L
, false,
630 const_cast<std::map
<std::string
, std::string
>*>(&(info
->args
.get_sub_resources())));
631 } else if (strcasecmp(index
, "Metadata") == 0) {
632 create_metatable
<StringMapMetaTable
<meta_map_t
, StringMapWriteableNewIndex
<meta_map_t
>>>(L
, false, &(info
->x_meta_map
));
633 } else if (strcasecmp(index
, "Host") == 0) {
634 pushstring(L
, info
->host
);
635 } else if (strcasecmp(index
, "Method") == 0) {
636 pushstring(L
, info
->method
);
637 } else if (strcasecmp(index
, "URI") == 0) {
638 pushstring(L
, info
->request_uri
);
639 } else if (strcasecmp(index
, "QueryString") == 0) {
640 pushstring(L
, info
->request_params
);
641 } else if (strcasecmp(index
, "Domain") == 0) {
642 pushstring(L
, info
->domain
);
644 throw_unknown_field(index
, TableName());
646 return ONE_RETURNVAL
;
650 struct CopyFromMetaTable
: public EmptyMetaTable
{
651 static std::string
TableName() {return "CopyFrom";}
652 static std::string
Name() {return TableName() + "Meta";}
654 static int IndexClosure(lua_State
* L
) {
655 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
657 const char* index
= luaL_checkstring(L
, 2);
659 if (strcasecmp(index
, "Tenant") == 0) {
660 pushstring(L
, s
->src_tenant_name
);
661 } else if (strcasecmp(index
, "Bucket") == 0) {
662 pushstring(L
, s
->src_bucket_name
);
663 } else if (strcasecmp(index
, "Object") == 0) {
664 create_metatable
<ObjectMetaTable
>(L
, false, s
->src_object
);
666 throw_unknown_field(index
, TableName());
668 return ONE_RETURNVAL
;
672 struct ZoneGroupMetaTable
: public EmptyMetaTable
{
673 static std::string
TableName() {return "ZoneGroup";}
674 static std::string
Name() {return TableName() + "Meta";}
676 static int IndexClosure(lua_State
* L
) {
677 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
679 const char* index
= luaL_checkstring(L
, 2);
681 if (strcasecmp(index
, "Name") == 0) {
682 pushstring(L
, s
->zonegroup_name
);
683 } else if (strcasecmp(index
, "Endpoint") == 0) {
684 pushstring(L
, s
->zonegroup_endpoint
);
686 throw_unknown_field(index
, TableName());
688 return ONE_RETURNVAL
;
692 struct RequestMetaTable
: public EmptyMetaTable
{
693 static std::string
TableName() {return "Request";}
694 static std::string
Name() {return TableName() + "Meta";}
696 // __index closure that expect req_state to be captured
697 static int IndexClosure(lua_State
* L
) {
698 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
699 const auto op_name
= reinterpret_cast<const char*>(lua_touserdata(L
, lua_upvalueindex(2)));
701 const char* index
= luaL_checkstring(L
, 2);
703 if (strcasecmp(index
, "RGWOp") == 0) {
704 pushstring(L
, op_name
);
705 } else if (strcasecmp(index
, "DecodedURI") == 0) {
706 pushstring(L
, s
->decoded_uri
);
707 } else if (strcasecmp(index
, "ContentLength") == 0) {
708 lua_pushinteger(L
, s
->content_length
);
709 } else if (strcasecmp(index
, "GenericAttributes") == 0) {
710 create_metatable
<StringMapMetaTable
<>>(L
, false, &(s
->generic_attrs
));
711 } else if (strcasecmp(index
, "Response") == 0) {
712 create_metatable
<ResponseMetaTable
>(L
, false, &(s
->err
));
713 } else if (strcasecmp(index
, "SwiftAccountName") == 0) {
714 if (s
->dialect
== "swift") {
715 pushstring(L
, s
->account_name
);
719 } else if (strcasecmp(index
, "Bucket") == 0) {
720 create_metatable
<BucketMetaTable
>(L
, false, s
->bucket
);
721 } else if (strcasecmp(index
, "Object") == 0) {
722 create_metatable
<ObjectMetaTable
>(L
, false, s
->object
);
723 } else if (strcasecmp(index
, "CopyFrom") == 0) {
724 if (s
->op_type
== RGW_OP_COPY_OBJ
) {
725 create_metatable
<CopyFromMetaTable
>(L
, s
);
729 } else if (strcasecmp(index
, "ObjectOwner") == 0) {
730 create_metatable
<OwnerMetaTable
>(L
, false, &(s
->owner
));
731 } else if (strcasecmp(index
, "ZoneGroup") == 0) {
732 create_metatable
<ZoneGroupMetaTable
>(L
, false, s
);
733 } else if (strcasecmp(index
, "UserACL") == 0) {
734 create_metatable
<ACLMetaTable
>(L
, false, s
->user_acl
);
735 } else if (strcasecmp(index
, "BucketACL") == 0) {
736 create_metatable
<ACLMetaTable
>(L
, false, s
->bucket_acl
);
737 } else if (strcasecmp(index
, "ObjectACL") == 0) {
738 create_metatable
<ACLMetaTable
>(L
, false, s
->object_acl
);
739 } else if (strcasecmp(index
, "Environment") == 0) {
740 create_metatable
<StringMapMetaTable
<rgw::IAM::Environment
>>(L
, false, &(s
->env
));
741 } else if (strcasecmp(index
, "Policy") == 0) {
742 // TODO: create a wrapper to std::optional
743 if (!s
->iam_policy
) {
746 create_metatable
<PolicyMetaTable
>(L
, false, s
->iam_policy
.get_ptr());
748 } else if (strcasecmp(index
, "UserPolicies") == 0) {
749 create_metatable
<PoliciesMetaTable
>(L
, false, &(s
->iam_user_policies
));
750 } else if (strcasecmp(index
, "RGWId") == 0) {
751 pushstring(L
, s
->host_id
);
752 } else if (strcasecmp(index
, "HTTP") == 0) {
753 create_metatable
<HTTPMetaTable
>(L
, false, &(s
->info
));
754 } else if (strcasecmp(index
, "Time") == 0) {
755 pushtime(L
, s
->time
);
756 } else if (strcasecmp(index
, "Dialect") == 0) {
757 pushstring(L
, s
->dialect
);
758 } else if (strcasecmp(index
, "Id") == 0) {
759 pushstring(L
, s
->req_id
);
760 } else if (strcasecmp(index
, "TransactionId") == 0) {
761 pushstring(L
, s
->trans_id
);
762 } else if (strcasecmp(index
, "Tags") == 0) {
763 create_metatable
<StringMapMetaTable
<RGWObjTags::tag_map_t
>>(L
, false, &(s
->tagset
.get_tags()));
765 throw_unknown_field(index
, TableName());
767 return ONE_RETURNVAL
;
772 rgw::sal::RGWRadosStore
* store
,
777 const std::string
& script
)
780 auto L
= luaL_newstate();
781 lua_state_guard
lguard(L
);
783 open_standard_libs(L
);
784 set_package_path(L
, store
?
785 store
->get_luarocks_path() :
788 create_debug_action(L
, s
->cct
);
790 create_metatable
<RequestMetaTable
>(L
, true, s
, const_cast<char*>(op_name
));
792 // add the ops log action
793 lua_getglobal(L
, RequestMetaTable::TableName().c_str());
794 ceph_assert(lua_istable(L
, -1));
795 pushstring(L
, RequestLogAction
);
796 lua_pushlightuserdata(L
, store
);
797 lua_pushlightuserdata(L
, rest
);
798 lua_pushlightuserdata(L
, olog
);
799 lua_pushlightuserdata(L
, s
);
800 lua_pushlightuserdata(L
, const_cast<char*>(op_name
));
801 lua_pushcclosure(L
, RequestLog
, FIVE_UPVALS
);
805 // execute the lua script
806 if (luaL_dostring(L
, script
.c_str()) != LUA_OK
) {
807 const std::string
err(lua_tostring(L
, -1));
808 ldpp_dout(s
, 1) << "Lua ERROR: " << err
<< dendl
;
811 } catch (const std::runtime_error
& e
) {
812 ldpp_dout(s
, 1) << "Lua ERROR: " << e
.what() << dendl
;