Skip to content

Commit 94348b6

Browse files
committed
refactor(status): reorganize container state into per-container directories
Replace flat JSON file storage with per-container directories containing status.json and config.json. Introduces status_directory_manager for container discovery and enables exec to dynamically enter namespaces based on stored config. Signed-off-by: ComixHe <ComixHe1895@outlook.com>
1 parent 6805dfc commit 94348b6

19 files changed

Lines changed: 289 additions & 270 deletions

CMakeLists.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,13 @@ set(linyaps-box_LIBRARY_SOURCE
152152
src/linyaps_box/container_ref.cpp
153153
src/linyaps_box/container_ref.h
154154
src/linyaps_box/container_status.cpp
155-
src/linyaps_box/container_status.h
156-
src/linyaps_box/impl/disabled_cgroup_manager.cpp
157-
src/linyaps_box/impl/disabled_cgroup_manager.h
158-
src/linyaps_box/impl/json_printer.cpp
159-
src/linyaps_box/impl/json_printer.h
160-
src/linyaps_box/impl/status_directory.cpp
161-
src/linyaps_box/impl/status_directory.h
162-
src/linyaps_box/impl/table_printer.cpp
163-
src/linyaps_box/impl/table_printer.h
155+
src/linyaps_box/container_status.h
156+
src/linyaps_box/impl/disabled_cgroup_manager.cpp
157+
src/linyaps_box/impl/disabled_cgroup_manager.h
158+
src/linyaps_box/impl/json_printer.cpp
159+
src/linyaps_box/impl/json_printer.h
160+
src/linyaps_box/impl/table_printer.cpp
161+
src/linyaps_box/impl/table_printer.h
164162
src/linyaps_box/interface.cpp
165163
src/linyaps_box/interface.h
166164
src/linyaps_box/io/epoll.cpp
@@ -173,8 +171,10 @@ set(linyaps-box_LIBRARY_SOURCE
173171
src/linyaps_box/runtime.h
174172
src/linyaps_box/socket.cpp
175173
src/linyaps_box/socket.h
176-
src/linyaps_box/status_directory.cpp
177-
src/linyaps_box/status_directory.h
174+
src/linyaps_box/status_directory.cpp
175+
src/linyaps_box/status_directory.h
176+
src/linyaps_box/status_directory_manager.cpp
177+
src/linyaps_box/status_directory_manager.h
178178
src/linyaps_box/terminal.cpp
179179
src/linyaps_box/terminal.h
180180
src/linyaps_box/unix_socket.cpp

src/linyaps_box/command/exec.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
// SPDX-FileCopyrightText: 2022-2026 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

55
#include "linyaps_box/command/exec.h"
66

7-
#include "linyaps_box/impl/status_directory.h"
87
#include "linyaps_box/runtime.h"
9-
#include "linyaps_box/status_directory.h"
8+
#include "linyaps_box/status_directory_manager.h"
109

1110
auto linyaps_box::command::exec(const struct exec_options &options) -> int
1211
{
13-
std::unique_ptr<status_directory> dir =
14-
std::make_unique<impl::status_directory>(options.global_.get().root);
15-
runtime_t runtime(std::move(dir));
12+
status_directory_manager mgr(options.global_.get().root);
13+
runtime_t runtime(std::move(mgr));
1614

1715
auto container_refs = runtime.containers();
1816
auto container = container_refs.find(options.ID);
@@ -25,7 +23,7 @@ auto linyaps_box::command::exec(const struct exec_options &options) -> int
2523
option.proc.args = options.command;
2624
option.proc.terminal = options.tty;
2725
option.proc.no_new_privileges = options.no_new_privs;
28-
option.proc.env = options.envs.value_or(std::vector<std::string>{ });
26+
option.proc.env = options.envs.value_or(std::vector<std::string>{});
2927
option.preserve_fds = options.preserve_fds;
3028

3129
if (option.proc.terminal && options.console_socket) {
@@ -41,7 +39,7 @@ auto linyaps_box::command::exec(const struct exec_options &options) -> int
4139
caps.cend(),
4240
std::back_inserter(cap_set),
4341
[](const std::string &cap) {
44-
cap_value_t val{ 0 };
42+
cap_value_t val{0};
4543
if (cap_from_name(cap.c_str(), &val) < 0) {
4644
throw std::system_error(errno, std::system_category(), "cap_from_name");
4745
}
@@ -57,7 +55,5 @@ auto linyaps_box::command::exec(const struct exec_options &options) -> int
5755
}
5856
#endif
5957

60-
// TODO: support exec fully
61-
6258
return container->second.exec(std::move(option));
6359
}

src/linyaps_box/command/kill.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// SPDX-FileCopyrightText: 2022-2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

55
#include "linyaps_box/command/kill.h"
66

7-
#include "linyaps_box/impl/status_directory.h"
87
#include "linyaps_box/runtime.h"
8+
#include "linyaps_box/status_directory_manager.h"
99
#include "linyaps_box/utils/platform.h"
1010

1111
#include <algorithm>
@@ -28,12 +28,8 @@ void linyaps_box::command::kill(const struct kill_options &options)
2828
break;
2929
}
3030

31-
auto status_dir = std::make_unique<impl::status_directory>(options.global_.get().root);
32-
if (!status_dir) {
33-
throw std::runtime_error("failed to create status directory");
34-
}
35-
36-
runtime_t runtime(std::move(status_dir));
31+
status_directory_manager mgr(options.global_.get().root);
32+
runtime_t runtime(std::move(mgr));
3733
const auto &containers = runtime.containers();
3834
for (const auto &[id, ref] : containers) {
3935
if (id != options.container) {

src/linyaps_box/command/list.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
// SPDX-FileCopyrightText: 2022-2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

55
#include "linyaps_box/command/list.h"
66

77
#include "linyaps_box/impl/json_printer.h"
8-
#include "linyaps_box/impl/status_directory.h"
98
#include "linyaps_box/impl/table_printer.h"
109
#include "linyaps_box/runtime.h"
11-
12-
#include <memory>
10+
#include "linyaps_box/status_directory_manager.h"
1311

1412
void linyaps_box::command::list(const struct list_options &options)
1513
{
16-
auto status_dir = std::make_unique<impl::status_directory>(options.global_.get().root);
17-
if (!status_dir) {
18-
throw std::runtime_error("failed to create status directory");
19-
}
20-
21-
runtime_t runtime(std::move(status_dir));
14+
status_directory_manager mgr(options.global_.get().root);
15+
runtime_t runtime(std::move(mgr));
2216

2317
std::unique_ptr<printer> printer;
2418
if (options.output_format == list_options::output_format_t::json) {

src/linyaps_box/command/run.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
// SPDX-FileCopyrightText: 2022-2026 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

55
#include "linyaps_box/command/run.h"
66

7-
#include "linyaps_box/impl/status_directory.h"
87
#include "linyaps_box/runtime.h"
9-
#include "linyaps_box/status_directory.h"
8+
#include "linyaps_box/status_directory_manager.h"
109

1110
auto linyaps_box::command::run(const struct run_options &options) -> int
1211
{
13-
std::unique_ptr<status_directory> dir =
14-
std::make_unique<impl::status_directory>(options.global_.get().root);
15-
runtime_t runtime(std::move(dir));
12+
status_directory_manager mgr(options.global_.get().root);
13+
runtime_t runtime(std::move(mgr));
1614
const create_container_options_t create_container_options{ options.global_.get().manager,
1715
options.ID,
1816
options.bundle,

src/linyaps_box/container.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2401,9 +2401,9 @@ void poststop_hooks(const linyaps_box::container &container) noexcept
24012401

24022402
} // namespace
24032403

2404-
linyaps_box::container::container(const status_directory &status_dir,
2405-
const create_container_options_t &options)
2406-
: container_ref(status_dir, options.ID)
2404+
linyaps_box::container::container(status_directory status_dir,
2405+
const create_container_options_t &options)
2406+
: container_ref(std::move(status_dir), options.ID)
24072407
, bundle(options.bundle)
24082408
{
24092409
auto config = options.config;
@@ -2419,7 +2419,6 @@ linyaps_box::container::container(const status_directory &status_dir,
24192419
host_uid_ = ::geteuid();
24202420
host_gid_ = ::getegid();
24212421

2422-
// TODO: maybe find another way to get user name
24232422
#ifndef LINYAPS_BOX_STATIC_LINK
24242423
auto *pw = getpwuid(host_uid_);
24252424
if (pw == nullptr) {
@@ -2442,6 +2441,8 @@ linyaps_box::container::container(const status_directory &status_dir,
24422441
this->status_dir().write(status);
24432442
}
24442443

2444+
this->status_dir().write_config(config_str);
2445+
24452446
switch (options.manager) {
24462447
case cgroup_manager_t::disabled: {
24472448
this->manager = std::make_unique<disabled_cgroup_manager>();
@@ -2550,7 +2551,7 @@ int linyaps_box::container::run(run_container_options_t options)
25502551
LINYAPS_BOX_ERR() << "failed to run a container, caused by: " << e.what();
25512552
}
25522553

2553-
this->status_dir().remove(this->get_id());
2554+
this->status_dir().remove();
25542555

25552556
// TODO: cleanup cgroup
25562557

src/linyaps_box/container.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct run_container_options_t
3131
class container final : public container_ref
3232
{
3333
public:
34-
container(const status_directory &status_dir, const create_container_options_t &options);
34+
container(status_directory status_dir, const create_container_options_t &options);
3535

3636
container(const container &) = delete;
3737
auto operator=(const container &) -> container & = delete;

src/linyaps_box/container_ref.cpp

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,24 @@
1010
#include "linyaps_box/utils/log.h"
1111
#include "linyaps_box/utils/process.h"
1212
#include "linyaps_box/utils/session.h"
13+
#include "nlohmann/json.hpp"
1314

1415
#include <csignal> // IWYU pragma: keep
1516
#include <utility>
1617

1718
#include <unistd.h>
1819

19-
linyaps_box::container_ref::container_ref(const status_directory &status_dir, std::string id)
20+
linyaps_box::container_ref::container_ref(status_directory status_dir, std::string id)
2021
: id_(std::move(id))
21-
, status_dir_(status_dir)
22+
, status_dir_(std::move(status_dir))
2223
{
2324
}
2425

2526
linyaps_box::container_ref::~container_ref() noexcept = default;
2627

2728
linyaps_box::container_status_t linyaps_box::container_ref::status() const
2829
{
29-
return this->status_dir_.read(this->id_);
30+
return status_dir_.read();
3031
}
3132

3233
void linyaps_box::container_ref::kill(int signal) const
@@ -47,7 +48,6 @@ auto linyaps_box::container_ref::exec(exec_container_option option) -> int
4748
{
4849
auto target = std::to_string(this->status().PID);
4950

50-
// TODO: support detach later
5151
std::ignore = utils::prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
5252

5353
std::optional<unix_socket> recv_socketpair;
@@ -63,31 +63,45 @@ auto linyaps_box::container_ref::exec(exec_container_option option) -> int
6363
}
6464

6565
if (child == 0) {
66-
// TODO: create terminal after rewrite exec. it should be created in the container namespace
6766
if (option.console_socket) {
6867
utils::setsid();
6968
auto [master, slave] = create_pty_pair();
7069

7170
slave.setup_stdio();
72-
// TODO: use fchown after we implement exec option `--user`
7371
slave.set_size({ });
7472

7573
option.console_socket->send_fd(std::move(master).take());
7674
option.console_socket.reset();
7775
}
7876

79-
std::vector<const char *> argv{
80-
"nsenter",
81-
"--target",
82-
target.c_str(),
83-
"--user",
84-
"--mount",
85-
"--pid",
86-
// FIXME:
87-
// Old nsenter command do not support --wdns,
88-
// so we have to implement nsenter by ourself in the future.
89-
"--preserve-credentials",
90-
};
77+
std::vector<const char *> argv{ "nsenter", "--target", target.c_str() };
78+
79+
auto config_str = status_dir_.read_config();
80+
auto config = nlohmann::json::parse(config_str);
81+
const auto &linux = config.at("linux");
82+
assert(!linux.is_null());
83+
84+
// FIXME: we assume that container always unshare some namespaces for now
85+
// support exec commands without setns in the future
86+
for (const auto &ns : linux.at("namespaces")) {
87+
const auto &type = ns.at("type");
88+
if (type == "pid") {
89+
argv.push_back("--pid");
90+
} else if (type == "mount") {
91+
argv.push_back("--mount");
92+
} else if (type == "uts") {
93+
argv.push_back("--uts");
94+
} else if (type == "ipc") {
95+
argv.push_back("--ipc");
96+
} else if (type == "network") {
97+
argv.push_back("--net");
98+
} else if (type == "user") {
99+
argv.push_back("--user");
100+
} else if (type == "cgroup") {
101+
argv.push_back("--cgroup");
102+
}
103+
}
104+
argv.push_back("--preserve-credentials");
91105

92106
for (const auto &arg : option.proc.args) {
93107
argv.push_back(arg.c_str());
@@ -101,20 +115,6 @@ auto linyaps_box::container_ref::exec(exec_container_option option) -> int
101115
}
102116
c_env.push_back(nullptr);
103117

104-
// FIXME:
105-
// We only handle the command arguments for now
106-
// here are some other fields in process we need to consider:
107-
// terminal
108-
// console.height
109-
// console.width
110-
// cwd
111-
// env
112-
// rlimits
113-
// apparmor_profile
114-
// capabilities
115-
// no_new_privileges
116-
// oom_score_adj
117-
118118
::execvpe("nsenter", const_cast<char **>(argv.data()), const_cast<char **>(c_env.data()));
119119
_exit(EXIT_FAILURE);
120120
}
@@ -148,10 +148,10 @@ auto linyaps_box::container_ref::exec(exec_container_option option) -> int
148148

149149
const linyaps_box::status_directory &linyaps_box::container_ref::status_dir() const
150150
{
151-
return this->status_dir_;
151+
return status_dir_;
152152
}
153153

154154
const std::string &linyaps_box::container_ref::get_id() const
155155
{
156-
return this->id_;
156+
return id_;
157157
}

src/linyaps_box/container_ref.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "linyaps_box/status_directory.h"
1010
#include "linyaps_box/unix_socket.h"
1111

12+
#include <string>
13+
1214
namespace linyaps_box {
1315

1416
struct exec_container_option
@@ -21,13 +23,13 @@ struct exec_container_option
2123
class container_ref
2224
{
2325
public:
24-
container_ref(const status_directory &status_dir, std::string id);
26+
container_ref(status_directory status_dir, std::string id);
2527
virtual ~container_ref() noexcept;
2628

2729
container_ref(const container_ref &) = delete;
2830
auto operator=(const container_ref &) -> container_ref & = delete;
29-
container_ref(container_ref &&) = delete;
30-
auto operator=(container_ref &&) -> container_ref & = delete;
31+
container_ref(container_ref &&) = default;
32+
auto operator=(container_ref &&) -> container_ref & = default;
3133

3234
[[nodiscard]] auto status() const -> container_status_t;
3335
void kill(int signal) const;
@@ -39,7 +41,7 @@ class container_ref
3941

4042
private:
4143
std::string id_;
42-
const status_directory &status_dir_;
44+
status_directory status_dir_;
4345
};
4446

4547
} // namespace linyaps_box

0 commit comments

Comments
 (0)