Browse Source

rpcd-mod-lxc: add package for rpcd lxc module

Signed-off-by: Luka Perkov <luka@openwrt.org>
Luka Perkov 10 years ago
parent
commit
153e482090
3 changed files with 481 additions and 0 deletions
  1. 35
    0
      utils/rpcd-mod-lxc/Makefile
  2. 19
    0
      utils/rpcd-mod-lxc/files/CMakeLists.txt
  3. 427
    0
      utils/rpcd-mod-lxc/files/lxc.c

+ 35
- 0
utils/rpcd-mod-lxc/Makefile View File

@@ -0,0 +1,35 @@
1
+#
2
+# Copyright (C) 2014 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=rpcd-mod-lxc
11
+PKG_RELEASE=20141012
12
+
13
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
14
+
15
+include $(INCLUDE_DIR)/package.mk
16
+include $(INCLUDE_DIR)/cmake.mk
17
+
18
+define Package/rpcd-mod-lxc
19
+  SECTION:=libs
20
+  CATEGORY:=Libraries
21
+  TITLE:=LXC rpcd module
22
+  DEPENDS:=+rpcd +liblxc
23
+  MAINTAINER:=Luka Perkov <luka@openwrt.org>
24
+endef
25
+
26
+define Build/Prepare
27
+	$(CP) ./files/* $(PKG_BUILD_DIR)/
28
+endef
29
+
30
+define Package/rpcd-mod-lxc/install
31
+	$(INSTALL_DIR) $(1)/usr/lib/rpcd
32
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/lxc.so $(1)/usr/lib/rpcd/
33
+endef
34
+
35
+$(eval $(call BuildPackage,rpcd-mod-lxc))

+ 19
- 0
utils/rpcd-mod-lxc/files/CMakeLists.txt View File

@@ -0,0 +1,19 @@
1
+cmake_minimum_required(VERSION 2.6)
2
+PROJECT(rpcd-mod-lxc)
3
+ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations)
4
+
5
+INCLUDE_DIRECTORIES(include)
6
+FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
7
+
8
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
9
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
10
+
11
+SET(SOURCES lxc.c)
12
+
13
+ADD_LIBRARY(rpcd-mod-lxc SHARED ${SOURCES})
14
+
15
+FIND_LIBRARY(lxc NAMES lxc liblxc)
16
+TARGET_LINK_LIBRARIES(rpcd-mod-lxc ${lxc})
17
+
18
+SET_TARGET_PROPERTIES(rpcd-mod-lxc PROPERTIES OUTPUT_NAME lxc PREFIX "")
19
+INSTALL(TARGETS rpcd-mod-lxc LIBRARY DESTINATION lib)

+ 427
- 0
utils/rpcd-mod-lxc/files/lxc.c View File

@@ -0,0 +1,427 @@
1
+/*
2
+ * rpcd-lxc-plugin
3
+ *
4
+ * Copyright (C) 2014 Cisco Systems, Inc.
5
+ * Author: Luka Perkov <luka@openwrt.org>
6
+ *
7
+ * Permission to use, copy, modify, and/or distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ */
19
+
20
+#include <libubus.h>
21
+
22
+#include <lxc/lxccontainer.h>
23
+
24
+#include <rpcd/plugin.h>
25
+
26
+static struct blob_buf buf;
27
+
28
+struct rpc_lxc {
29
+	/* ubus options */
30
+	char *name;
31
+	char *config;
32
+	/* lxc container */
33
+	struct lxc_container *container;
34
+};
35
+
36
+enum {
37
+	RPC_LXC_NAME,
38
+	RPC_LXC_CONFIG,
39
+	__RPC_LXC_MAX,
40
+};
41
+
42
+enum {
43
+	RPC_LXC_SHUTDOWN_NAME,
44
+	RPC_LXC_SHUTDOWN_CONFIG,
45
+	RPC_LXC_SHUTDOWN_TIMEOUT,
46
+	__RPC_LXC_SHUTDOWN_MAX,
47
+};
48
+
49
+enum {
50
+	RPC_LXC_RENAME_NAME,
51
+	RPC_LXC_RENAME_CONFIG,
52
+	RPC_LXC_RENAME_NEWNAME,
53
+	__RPC_LXC_RENAME_MAX,
54
+};
55
+
56
+static const struct blobmsg_policy rpc_lxc_min_policy[__RPC_LXC_MAX] = {
57
+	[RPC_LXC_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
58
+	[RPC_LXC_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
59
+};
60
+
61
+static const struct blobmsg_policy rpc_lxc_shutdown_policy[__RPC_LXC_SHUTDOWN_MAX] = {
62
+	[RPC_LXC_SHUTDOWN_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
63
+	[RPC_LXC_SHUTDOWN_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
64
+	[RPC_LXC_SHUTDOWN_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
65
+};
66
+
67
+static const struct blobmsg_policy rpc_lxc_rename_policy[__RPC_LXC_RENAME_MAX] = {
68
+	[RPC_LXC_RENAME_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
69
+	[RPC_LXC_RENAME_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
70
+	[RPC_LXC_RENAME_NEWNAME] = { .name = "newname", .type = BLOBMSG_TYPE_STRING },
71
+};
72
+
73
+static struct rpc_lxc *
74
+rpc_lxc_init(struct blob_attr *tb[__RPC_LXC_MAX])
75
+{
76
+	struct rpc_lxc *l = NULL;
77
+
78
+	l = calloc(1, sizeof(struct rpc_lxc));
79
+	if (!l) return NULL;
80
+
81
+	if (tb[RPC_LXC_NAME]) {
82
+		l->name = blobmsg_data(tb[RPC_LXC_NAME]);
83
+	} else {
84
+		goto error;
85
+	}
86
+
87
+	if (tb[RPC_LXC_CONFIG]) {
88
+		l->config = blobmsg_data(tb[RPC_LXC_CONFIG]);
89
+	} else {
90
+		l->config = NULL;
91
+	}
92
+
93
+	l->container = lxc_container_new(l->name, l->config);
94
+	if (!l->container) {
95
+		goto error;
96
+	}
97
+
98
+	return l;
99
+error:
100
+	free(l);
101
+	return NULL;
102
+}
103
+
104
+static void
105
+rpc_lxc_done(struct rpc_lxc *l)
106
+{
107
+	if (l) {
108
+		lxc_container_put(l->container);
109
+		free(l);
110
+	}
111
+
112
+	return;
113
+}
114
+
115
+static int
116
+rpc_lxc_start(struct ubus_context *ctx, struct ubus_object *obj,
117
+		struct ubus_request_data *req, const char *method,
118
+		struct blob_attr *msg)
119
+{
120
+	struct blob_attr *tb[__RPC_LXC_MAX];
121
+	struct rpc_lxc *l = NULL;
122
+	int rc;
123
+
124
+	blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
125
+
126
+	l = rpc_lxc_init(tb);
127
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
128
+
129
+	if (l->container->is_running(l->container)) {
130
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
131
+		goto out;
132
+	}
133
+
134
+	if (!l->container->start(l->container, 0, NULL)) {
135
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
136
+		goto out;
137
+	}
138
+
139
+	rc = UBUS_STATUS_OK;
140
+out:
141
+	rpc_lxc_done(l);
142
+	return rc;
143
+}
144
+
145
+
146
+static int
147
+rpc_lxc_reboot(struct ubus_context *ctx, struct ubus_object *obj,
148
+		struct ubus_request_data *req, const char *method,
149
+		struct blob_attr *msg)
150
+{
151
+	struct blob_attr *tb[__RPC_LXC_MAX];
152
+	struct rpc_lxc *l = NULL;
153
+	int rc;
154
+
155
+	blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
156
+
157
+	l = rpc_lxc_init(tb);
158
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
159
+
160
+	if (!l->container->is_running(l->container)) {
161
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
162
+		goto out;
163
+	}
164
+
165
+	if (!l->container->reboot(l->container)) {
166
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
167
+		goto out;
168
+	}
169
+
170
+	rc = UBUS_STATUS_OK;
171
+out:
172
+	rpc_lxc_done(l);
173
+	return rc;
174
+}
175
+
176
+static int
177
+rpc_lxc_shutdown(struct ubus_context *ctx, struct ubus_object *obj,
178
+		struct ubus_request_data *req, const char *method,
179
+		struct blob_attr *msg)
180
+{
181
+	struct blob_attr *tb[__RPC_LXC_SHUTDOWN_MAX];
182
+	struct rpc_lxc *l = NULL;
183
+	int rc;
184
+
185
+	blobmsg_parse(rpc_lxc_shutdown_policy, __RPC_LXC_SHUTDOWN_MAX, tb, blob_data(msg), blob_len(msg));
186
+
187
+	l = rpc_lxc_init(tb);
188
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
189
+
190
+	if (!l->container->is_running(l->container)) {
191
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
192
+		goto out;
193
+	}
194
+
195
+	/* define default timeout */
196
+	int timeout = 30;
197
+	if (tb[RPC_LXC_SHUTDOWN_TIMEOUT]) {
198
+		timeout = blobmsg_get_u32(tb[RPC_LXC_SHUTDOWN_TIMEOUT]);
199
+	}
200
+
201
+	if (!l->container->shutdown(l->container, timeout)) {
202
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
203
+		goto out;
204
+	}
205
+
206
+	rc = UBUS_STATUS_OK;
207
+out:
208
+	rpc_lxc_done(l);
209
+	return rc;
210
+}
211
+
212
+static int
213
+rpc_lxc_stop(struct ubus_context *ctx, struct ubus_object *obj,
214
+		struct ubus_request_data *req, const char *method,
215
+		struct blob_attr *msg)
216
+{
217
+	struct blob_attr *tb[__RPC_LXC_MAX];
218
+	struct rpc_lxc *l = NULL;
219
+	int rc;
220
+
221
+	blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
222
+
223
+	l = rpc_lxc_init(tb);
224
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
225
+
226
+	if (!l->container->is_running(l->container)) {
227
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
228
+		goto out;
229
+	}
230
+
231
+	if (!l->container->stop(l->container)) {
232
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
233
+		goto out;
234
+	}
235
+
236
+	rc = UBUS_STATUS_OK;
237
+out:
238
+	rpc_lxc_done(l);
239
+	return rc;
240
+}
241
+
242
+static int
243
+rpc_lxc_freeze(struct ubus_context *ctx, struct ubus_object *obj,
244
+		struct ubus_request_data *req, const char *method,
245
+		struct blob_attr *msg)
246
+{
247
+	struct blob_attr *tb[__RPC_LXC_MAX];
248
+	struct rpc_lxc *l = NULL;
249
+	int rc;
250
+
251
+	blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
252
+
253
+	l = rpc_lxc_init(tb);
254
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
255
+
256
+	if (!l->container->is_running(l->container)) {
257
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
258
+		goto out;
259
+	}
260
+
261
+	if (!l->container->freeze(l->container)) {
262
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
263
+		goto out;
264
+	}
265
+
266
+	rc = UBUS_STATUS_OK;
267
+out:
268
+	rpc_lxc_done(l);
269
+	return rc;
270
+}
271
+
272
+static int
273
+rpc_lxc_unfreeze(struct ubus_context *ctx, struct ubus_object *obj,
274
+		struct ubus_request_data *req, const char *method,
275
+		struct blob_attr *msg)
276
+{
277
+	struct blob_attr *tb[__RPC_LXC_MAX];
278
+	struct rpc_lxc *l = NULL;
279
+	int rc;
280
+
281
+	blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
282
+
283
+	l = rpc_lxc_init(tb);
284
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
285
+
286
+	if (!l->container->is_running(l->container)) {
287
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
288
+		goto out;
289
+	}
290
+
291
+	if (!l->container->unfreeze(l->container)) {
292
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
293
+		goto out;
294
+	}
295
+
296
+	rc = UBUS_STATUS_OK;
297
+out:
298
+	rpc_lxc_done(l);
299
+	return rc;
300
+}
301
+
302
+static int
303
+rpc_lxc_rename(struct ubus_context *ctx, struct ubus_object *obj,
304
+		struct ubus_request_data *req, const char *method,
305
+		struct blob_attr *msg)
306
+{
307
+	struct blob_attr *tb[__RPC_LXC_RENAME_MAX];
308
+	struct rpc_lxc *l = NULL;
309
+	int rc;
310
+
311
+	blobmsg_parse(rpc_lxc_rename_policy, __RPC_LXC_RENAME_MAX, tb, blob_data(msg), blob_len(msg));
312
+
313
+	l = rpc_lxc_init(tb);
314
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
315
+
316
+	if (!tb[RPC_LXC_RENAME_NEWNAME]) {
317
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
318
+		goto out;
319
+	}
320
+
321
+	if (l->container->is_running(l->container)) {
322
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
323
+		goto out;
324
+	}
325
+
326
+	char *newname = blobmsg_data(tb[RPC_LXC_RENAME_NEWNAME]);
327
+	if (!newname || !l->container->rename(l->container, newname)) {
328
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
329
+		goto out;
330
+	}
331
+
332
+	rc = UBUS_STATUS_OK;
333
+out:
334
+	rpc_lxc_done(l);
335
+	return rc;
336
+}
337
+
338
+static int
339
+rpc_lxc_destroy(struct ubus_context *ctx, struct ubus_object *obj,
340
+		struct ubus_request_data *req, const char *method,
341
+		struct blob_attr *msg)
342
+{
343
+	struct blob_attr *tb[__RPC_LXC_MAX];
344
+	struct rpc_lxc *l = NULL;
345
+	int rc;
346
+
347
+	blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
348
+
349
+	l = rpc_lxc_init(tb);
350
+	if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
351
+
352
+	if (l->container->is_running(l->container)) {
353
+		rc = UBUS_STATUS_UNKNOWN_ERROR;
354
+		goto out;
355
+	}
356
+
357
+	if (!l->container->destroy(l->container)) {
358
+		rc = UBUS_STATUS_INVALID_ARGUMENT;
359
+		goto out;
360
+	}
361
+
362
+	rc = UBUS_STATUS_OK;
363
+out:
364
+	rpc_lxc_done(l);
365
+	return rc;
366
+}
367
+
368
+static int
369
+rpc_lxc_list(struct ubus_context *ctx, struct ubus_object *obj,
370
+		struct ubus_request_data *req, const char *method,
371
+		struct blob_attr *msg)
372
+{
373
+
374
+	blob_buf_init(&buf, 0);
375
+
376
+	int rc;
377
+	char **names;
378
+	struct lxc_container **cret;
379
+
380
+	rc = list_all_containers(NULL, &names, &cret);
381
+	if (rc == -1)
382
+		return UBUS_STATUS_UNKNOWN_ERROR;
383
+
384
+	for (int i = 0; i < rc; i++) {
385
+		struct lxc_container *c = cret[i];
386
+		blobmsg_add_string(&buf, names[i], c->state(c));
387
+
388
+		free(names[i]);
389
+		lxc_container_put(c);
390
+	}
391
+
392
+	ubus_send_reply(ctx, req, buf.head);
393
+
394
+	return UBUS_STATUS_OK;
395
+}
396
+
397
+static int
398
+rpc_lxc_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
399
+{
400
+	static const struct ubus_method lxc_methods[] = {
401
+		UBUS_METHOD("start", rpc_lxc_start, rpc_lxc_min_policy),
402
+		UBUS_METHOD("reboot", rpc_lxc_reboot, rpc_lxc_min_policy),
403
+		UBUS_METHOD("shutdown", rpc_lxc_shutdown, rpc_lxc_shutdown_policy),
404
+		UBUS_METHOD("stop", rpc_lxc_stop, rpc_lxc_min_policy),
405
+		UBUS_METHOD("freeze", rpc_lxc_freeze, rpc_lxc_min_policy),
406
+		UBUS_METHOD("unfreeze", rpc_lxc_unfreeze, rpc_lxc_min_policy),
407
+		UBUS_METHOD("rename", rpc_lxc_rename, rpc_lxc_rename_policy),
408
+		UBUS_METHOD("destroy", rpc_lxc_destroy, rpc_lxc_min_policy),
409
+		UBUS_METHOD_NOARG("list", rpc_lxc_list),
410
+	};
411
+
412
+	static struct ubus_object_type lxc_type =
413
+		UBUS_OBJECT_TYPE("luci-rpc-lxc", lxc_methods);
414
+
415
+	static struct ubus_object obj = {
416
+		.name = "lxc",
417
+		.type = &lxc_type,
418
+		.methods = lxc_methods,
419
+		.n_methods = ARRAY_SIZE(lxc_methods),
420
+	};
421
+
422
+	return ubus_add_object(ctx, &obj);
423
+}
424
+
425
+struct rpc_plugin rpc_plugin = {
426
+	.init = rpc_lxc_api_init
427
+};