Skip to content

Commit

Permalink
rgw/lua: allow for multiple RGWs to install packages in the same host
Browse files Browse the repository at this point in the history
each RGW will install the luarocks packages in its own directory

Signed-off-by: Yuval Lifshitz <[email protected]>
  • Loading branch information
yuvalif committed Dec 15, 2020
1 parent 6ef3e52 commit f5dd15e
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 39 deletions.
2 changes: 1 addition & 1 deletion doc/radosgw/lua-scripting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ By default, all lua standard libraries are available in the script, however, in
- All packages in the allowlist are being re-installed using the luarocks package manager on radosgw restart. Therefore a restart is needed for adding or removing of packages to take effect
- To add a package that contains C source code that needs to be compiled, use the `--allow-compilation` flag. In this case a C compiler needs to be available on the host
- Lua packages are installed in, and used from, a directory local to the radosgw. Meaning that lua packages in the allowlist are separated from any lua packages available on the host.
By default, this directory would be `/tmp/luarocks/`, and could be set to a different location via the `rgw_luarocks_location` configuration parameter.
By default, this directory would be `/tmp/luarocks/<entity name>`. Its prefix part (`/tmp/luarocks/`) could be set to a different location via the `rgw_luarocks_location` configuration parameter.
Note that this parameter should not be set to one of the default locations where luarocks install packages (e.g. `$HOME/.luarocks`, `/usr/lib64/lua`, `/usr/share/lua`)


Expand Down
2 changes: 1 addition & 1 deletion src/rgw/rgw_admin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9374,7 +9374,7 @@ int main(int argc, const char **argv)
return -rc;
}
#else
cerr << "ERROR: adding lua packages in not permitted" << std::endl;
cerr << "ERROR: adding lua packages is not permitted" << std::endl;
return EPERM;
#endif
}
Expand Down
11 changes: 5 additions & 6 deletions src/rgw/rgw_lua.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ int add_package(rgw::sal::RGWRadosStore* store, optional_yield y, const std::str

std::string line;
bool package_found = false;
// TODO: yield on reading the output
while (c.running() && std::getline(is, line) && !line.empty()) {
package_found = true;
}
Expand Down Expand Up @@ -230,9 +229,9 @@ int list_packages(rgw::sal::RGWRadosStore* store, optional_yield y, packages_t&

int install_packages(rgw::sal::RGWRadosStore* store, optional_yield y, packages_t& failed_packages, std::string& output) {
// luarocks directory cleanup
const auto& luarocks_location = g_conf().get_val<std::string>("rgw_luarocks_location");
boost::system::error_code ec;
boost::filesystem::remove_all(luarocks_location, ec);
const auto& luarocks_path = store->get_luarocks_path();
boost::filesystem::remove_all(luarocks_path, ec);
if (ec.value() != 0 && ec.value() != ENOENT) {
output.append("failed to clear luarock directory: ");
output.append(ec.message());
Expand All @@ -258,13 +257,13 @@ int install_packages(rgw::sal::RGWRadosStore* store, optional_yield y, packages_
// the lua rocks install dir will be created by luarocks the first time it is called
for (const auto& package : packages) {
bp::ipstream is;
bp::child c(p, "install", "--lua-version", CEPH_LUA_VERSION, "--tree", luarocks_location, "--deps-mode", "one", package,
bp::child c(p, "install", "--lua-version", CEPH_LUA_VERSION, "--tree", luarocks_path, "--deps-mode", "one", package,
bp::std_in.close(),
(bp::std_err & bp::std_out) > is);

// TODO: yield until wait returns
// once package reload is supported, code should yield when reading output
std::string line = "CMD: luarocks install --lua-version " + std::string(CEPH_LUA_VERSION) + std::string(" --tree ") +
luarocks_location + " --deps-mode one " + package;
luarocks_path + " --deps-mode one " + package;

do {
if (!line.empty()) {
Expand Down
7 changes: 4 additions & 3 deletions src/rgw/rgw_lua_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -774,15 +774,16 @@ int execute(
OpsLogSocket* olog,
req_state* s,
const char* op_name,
const std::string& script,
const std::string& package_path)
const std::string& script)

{
auto L = luaL_newstate();
lua_state_guard lguard(L);

open_standard_libs(L);
set_package_path(L, package_path);
set_package_path(L, store ?
store->get_luarocks_path() :
"");

create_debug_action(L, s->cct);

Expand Down
3 changes: 1 addition & 2 deletions src/rgw/rgw_lua_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ int execute(
OpsLogSocket* olog,
req_state *s,
const char* op_name,
const std::string& script,
const std::string& package_path);
const std::string& script);

}

6 changes: 6 additions & 0 deletions src/rgw/rgw_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,12 @@ int radosgw_Main(int argc, const char **argv)
#endif
}

const auto& luarocks_path = g_conf().get_val<std::string>("rgw_luarocks_location");
if (luarocks_path.empty()) {
store->set_luarocks_path("");
} else {
store->set_luarocks_path(luarocks_path+"/"+g_conf()->name.to_str());
}
#ifdef WITH_RADOSGW_LUA_PACKAGES
rgw::lua::packages_t failed_packages;
std::string output;
Expand Down
5 changes: 2 additions & 3 deletions src/rgw/rgw_process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ int process_request(rgw::sal::RGWRadosStore* const store,
frontend_prefix,
client_io, &mgr, &init_error);
rgw::dmclock::SchedulerCompleter c;
const auto& lua_package_path = g_conf().get_val<std::string>("rgw_luarocks_location");

if (init_error != 0) {
abort_early(s, nullptr, init_error, nullptr, yield);
Expand All @@ -249,7 +248,7 @@ int process_request(rgw::sal::RGWRadosStore* const store,
} else if (rc < 0) {
ldpp_dout(op, 5) << "WARNING: failed to read pre request script. error: " << rc << dendl;
} else {
rc = rgw::lua::request::execute(store, rest, olog, s, op->name(), script, lua_package_path);
rc = rgw::lua::request::execute(store, rest, olog, s, op->name(), script);
if (rc < 0) {
ldpp_dout(op, 5) << "WARNING: failed to execute pre request script. error: " << rc << dendl;
}
Expand Down Expand Up @@ -317,7 +316,7 @@ int process_request(rgw::sal::RGWRadosStore* const store,
} else if (rc < 0) {
ldpp_dout(op, 5) << "WARNING: failed to read post request script. error: " << rc << dendl;
} else {
rc = rgw::lua::request::execute(store, rest, olog, s, op->name(), script, lua_package_path);
rc = rgw::lua::request::execute(store, rest, olog, s, op->name(), script);
if (rc < 0) {
ldpp_dout(op, 5) << "WARNING: failed to execute post request script. error: " << rc << dendl;
}
Expand Down
5 changes: 5 additions & 0 deletions src/rgw/rgw_sal.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ class RGWStore : public DoutPrefixProvider {
virtual void finalize(void)=0;

virtual CephContext *ctx(void)=0;

// get the location of where lua packages are installed
virtual const std::string& get_luarocks_path() const = 0;
// set the location of where lua packages are installed
virtual void set_luarocks_path(const std::string& path) = 0;
};

class RGWUser {
Expand Down
8 changes: 8 additions & 0 deletions src/rgw/rgw_sal_rados.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class RGWRadosStore : public RGWStore {
private:
RGWRados *rados;
RGWUserCtl *user_ctl;
std::string luarocks_path;

public:
RGWRadosStore()
Expand Down Expand Up @@ -331,6 +332,13 @@ class RGWRadosStore : public RGWStore {
CephContext* get_cct() const override { return rados->ctx(); }
unsigned get_subsys() const override { return ceph_subsys_rgw; }

const std::string& get_luarocks_path() const override {
return luarocks_path;
}

void set_luarocks_path(const std::string& path) override {
luarocks_path = path;
}
};

class MPRadosSerializer : public MPSerializer {
Expand Down
46 changes: 23 additions & 23 deletions src/test/rgw/test_rgw_lua.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ TEST(TestRGWLua, EmptyScript)
uint64_t id = 0;
req_state s(cct, &e, id);

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -95,7 +95,7 @@ TEST(TestRGWLua, SyntaxError)

DEFINE_REQ_STATE;

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script);
ASSERT_EQ(rc, -1);
}

Expand All @@ -107,7 +107,7 @@ TEST(TestRGWLua, Hello)

DEFINE_REQ_STATE;

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -119,7 +119,7 @@ TEST(TestRGWLua, RGWDebugLogNumber)

DEFINE_REQ_STATE;

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -131,7 +131,7 @@ TEST(TestRGWLua, RGWDebugNil)

DEFINE_REQ_STATE;

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script);
ASSERT_EQ(rc, -1);
}

Expand All @@ -145,7 +145,7 @@ TEST(TestRGWLua, URI)
DEFINE_REQ_STATE;
s.decoded_uri = "http://hello.world/";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -164,7 +164,7 @@ TEST(TestRGWLua, Response)
s.err.err_code = "Bad Request";
s.err.message = "This is a bad request";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -179,7 +179,7 @@ TEST(TestRGWLua, SetResponse)
DEFINE_REQ_STATE;
s.err.message = "this is a bad request";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -193,7 +193,7 @@ TEST(TestRGWLua, SetRGWId)
DEFINE_REQ_STATE;
s.host_id = "foo";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_NE(rc, 0);
}

Expand All @@ -206,7 +206,7 @@ TEST(TestRGWLua, InvalidField)
DEFINE_REQ_STATE;
s.host_id = "foo";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "kaboom", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "kaboom", script);
ASSERT_EQ(rc, -1);
}

Expand All @@ -218,7 +218,7 @@ TEST(TestRGWLua, InvalidSubField)

DEFINE_REQ_STATE;

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "kaboom", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "kaboom", script);
ASSERT_EQ(rc, -1);
}

Expand Down Expand Up @@ -252,7 +252,7 @@ TEST(TestRGWLua, Bucket)
b.bucket_id = "myid";
s.bucket.reset(new sal::RGWRadosBucket(nullptr, b));

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -275,7 +275,7 @@ TEST(TestRGWLua, GenericAttributes)
s.generic_attrs["goodbye"] = "cruel world";
s.generic_attrs["ka"] = "boom";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -298,7 +298,7 @@ TEST(TestRGWLua, Environment)
s.env["goodbye"] = "cruel world";
s.env["ka"] = "boom";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -319,7 +319,7 @@ TEST(TestRGWLua, Tags)
s.tagset.add_tag("goodbye", "cruel world");
s.tagset.add_tag("ka", "boom");

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -332,7 +332,7 @@ TEST(TestRGWLua, TagsNotWriteable)
DEFINE_REQ_STATE;
s.tagset.add_tag("hello", "world");

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_NE(rc, 0);
}

Expand All @@ -358,7 +358,7 @@ TEST(TestRGWLua, Metadata)
s.info.x_meta_map["foo"] = "bar";
s.info.x_meta_map["ka"] = "boom";

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand Down Expand Up @@ -409,7 +409,7 @@ TEST(TestRGWLua, Acl)
s.user_acl->get_acl().add_grant(&grant3);
s.user_acl->get_acl().add_grant(&grant4);
s.user_acl->get_acl().add_grant(&grant5);
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand Down Expand Up @@ -453,7 +453,7 @@ TEST(TestRGWLua, UseFunction)
s.object_acl->get_owner().set_name("user five");
s.object_acl->get_owner().set_id(rgw_user("tenant5", "user5"));

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -474,7 +474,7 @@ TEST(TestRGWLua, WithLib)
b.name = "my-bucket-name-is-fish";
s.bucket.reset(new sal::RGWRadosBucket(nullptr, b));

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_EQ(rc, 0);
}

Expand All @@ -487,7 +487,7 @@ TEST(TestRGWLua, NotAllowedInLib)

DEFINE_REQ_STATE;

const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script, "");
const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
ASSERT_NE(rc, 0);
}
#include <sys/socket.h>
Expand Down Expand Up @@ -563,11 +563,11 @@ TEST(TestRGWLua, OpsLog)
s.cio = &ac;
s.cct->_conf->rgw_ops_log_rados = false;

auto rc = lua::request::execute(store.get(), nullptr, olog.get(), &s, "put_obj", script, "");
auto rc = lua::request::execute(store.get(), nullptr, olog.get(), &s, "put_obj", script);
EXPECT_EQ(rc, 0);

s.err.http_ret = 400;
rc = lua::request::execute(store.get(), nullptr, olog.get(), &s, "put_obj", script, "");
rc = lua::request::execute(store.get(), nullptr, olog.get(), &s, "put_obj", script);
EXPECT_EQ(rc, 0);

// give the socket client time to read
Expand Down

0 comments on commit f5dd15e

Please sign in to comment.