Browse Source

jail: handle containers seperately

To make the API more clean and running containers less of a hidden
feature offer new object ubus 'containers' to handle container
operations similar to how services are handled.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Daniel Golle 3 years ago
parent
commit
b9b39e2061
4 changed files with 118 additions and 39 deletions
  1. 8 8
      jail/console.c
  2. 1 1
      jail/jail.c
  3. 108 30
      service/service.c
  4. 1 0
      service/service.h

+ 8 - 8
jail/console.c

@@ -56,14 +56,14 @@ static inline int setup_tios(int fd, struct termios *oldtios)
 
 
 
-#define OPT_ARGS	"i:s:"
+#define OPT_ARGS	"i:c:"
 
 static struct ustream_fd cufd;
 static struct ustream_fd lufd;
 
 static void usage()
 {
-	fprintf(stderr, "ujail-console -s <service> [-i <instance>]\n");
+	fprintf(stderr, "ujail-console -c <container> [-i <instance>]\n");
 	exit(1);
 }
 
@@ -115,7 +115,7 @@ int main(int argc, char **argv)
 	struct ubus_context *ctx;
 	uint32_t id;
 	static struct blob_buf req;
-	char *service_name = NULL, *instance_name = NULL;
+	char *container_name = NULL, *instance_name = NULL;
 	int client_fd, server_fd, tty_fd;
 	struct termios oldtermios;
 	int ch;
@@ -125,15 +125,15 @@ int main(int argc, char **argv)
 		case 'i':
 			instance_name = optarg;
 			break;
-		case 's':
-			service_name = optarg;
+		case 'c':
+			container_name = optarg;
 			break;
 		default:
 			usage();
 		}
 	}
 
-	if (!service_name)
+	if (!container_name)
 		usage();
 
 	ctx = ubus_connect(NULL);
@@ -166,11 +166,11 @@ int main(int argc, char **argv)
 
 	/* register server-side with procd */
 	blob_buf_init(&req, 0);
-	blobmsg_add_string(&req, "name", service_name);
+	blobmsg_add_string(&req, "name", container_name);
 	if (instance_name)
 		blobmsg_add_string(&req, "instance", instance_name);
 
-	if (ubus_lookup_id(ctx, "service", &id) ||
+	if (ubus_lookup_id(ctx, "container", &id) ||
 	    ubus_invoke_fd(ctx, id, "console_attach", req.head, NULL, NULL, 3000, server_fd)) {
 		fprintf(stderr, "ubus request failed\n");
 		close(server_fd);

+ 1 - 1
jail/jail.c

@@ -199,7 +199,7 @@ static void pass_console(int console_fd)
 	blob_buf_init(&req, 0);
 	blobmsg_add_string(&req, "name", opts.name);
 
-	if (ubus_lookup_id(ctx, "service", &id) ||
+	if (ubus_lookup_id(ctx, "container", &id) ||
 	    ubus_invoke_fd(ctx, id, "console_set", req.head, NULL, NULL, 3000, console_fd))
 		INFO("ubus request failed\n");
 	else

+ 108 - 30
service/service.c

@@ -12,6 +12,10 @@
  * GNU General Public License for more details.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include <libubox/blobmsg_json.h>
 #include <libubox/avl-cmp.h>
 
@@ -23,6 +27,7 @@
 #include "../rcS.h"
 
 AVL_TREE(services, avl_strcmp, false, NULL);
+AVL_TREE(containers, avl_strcmp, false, NULL);
 static struct blob_buf b;
 static struct ubus_context *ctx;
 static struct ubus_object main_object;
@@ -172,14 +177,16 @@ service_update(struct service *s, struct blob_attr **tb, bool add)
 	return 0;
 }
 
+static void _service_stopped(struct service *s, bool container);
+
 static void
-service_delete(struct service *s)
+service_delete(struct service *s, bool container)
 {
 	blobmsg_list_free(&s->data_blob);
 	free(s->data);
 	vlist_flush_all(&s->instances);
 	s->deleted = true;
-	service_stopped(s);
+	_service_stopped(s, container);
 }
 
 enum {
@@ -275,16 +282,21 @@ static const struct blobmsg_policy get_data_policy[] = {
 };
 
 enum {
-	SERVICE_CONSOLE_NAME,
-	SERVICE_CONSOLE_INSTANCE,
-	__SERVICE_CONSOLE_MAX,
+	CONTAINER_CONSOLE_NAME,
+	CONTAINER_CONSOLE_INSTANCE,
+	__CONTAINER_CONSOLE_MAX,
 };
 
-static const struct blobmsg_policy service_console_policy[__SERVICE_CONSOLE_MAX] = {
-	[SERVICE_CONSOLE_NAME] = { "name", BLOBMSG_TYPE_STRING },
-	[SERVICE_CONSOLE_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING },
+static const struct blobmsg_policy container_console_policy[__CONTAINER_CONSOLE_MAX] = {
+	[CONTAINER_CONSOLE_NAME] = { "name", BLOBMSG_TYPE_STRING },
+	[CONTAINER_CONSOLE_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING },
 };
 
+static inline bool is_container_obj(struct ubus_object *obj)
+{
+	return (obj && (strcmp(obj->name, "container") == 0));
+}
+
 static int
 service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 		   struct ubus_request_data *req, const char *method,
@@ -293,6 +305,7 @@ service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 	struct blob_attr *tb[__SERVICE_SET_MAX], *cur;
 	struct service *s = NULL;
 	const char *name;
+	bool container = is_container_obj(obj);
 	bool add = !strcmp(method, "add");
 	int ret;
 
@@ -303,7 +316,11 @@ service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 
 	name = blobmsg_data(cur);
 
-	s = avl_find_element(&services, name, s, avl);
+	if (container)
+		s = avl_find_element(&containers, name, s, avl);
+	else
+		s = avl_find_element(&services, name, s, avl);
+
 	if (s) {
 		DEBUG(2, "Update service %s\n", name);
 		return service_update(s, tb, add);
@@ -318,10 +335,15 @@ service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 	if (ret)
 		return ret;
 
-	avl_insert(&services, &s->avl);
+	if (container) {
+		avl_insert(&containers, &s->avl);
 
-	service_event("service.start", s->name, NULL);
+		service_event("container.start", s->name, NULL);
+	} else {
+		avl_insert(&services, &s->avl);
 
+		service_event("service.start", s->name, NULL);
+	}
 	return 0;
 }
 
@@ -366,6 +388,8 @@ service_handle_list(struct ubus_context *ctx, struct ubus_object *obj,
 	struct service *s;
 	const char *name = NULL;
 	bool verbose = false;
+	bool container = is_container_obj(obj);
+	const struct avl_tree *tree = container?&containers:&services;
 
 	blobmsg_parse(service_list_attrs, __SERVICE_LIST_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
 
@@ -375,7 +399,7 @@ service_handle_list(struct ubus_context *ctx, struct ubus_object *obj,
 		name = blobmsg_get_string(tb[SERVICE_LIST_ATTR_NAME]);
 
 	blob_buf_init(&b, 0);
-	avl_for_each_element(&services, s, avl) {
+	avl_for_each_element(tree, s, avl) {
 		if (name && strcmp(s->name, name) != 0)
 			continue;
 
@@ -395,6 +419,7 @@ service_handle_delete(struct ubus_context *ctx, struct ubus_object *obj,
 	struct blob_attr *tb[__SERVICE_DEL_ATTR_MAX], *cur;
 	struct service *s;
 	struct service_instance *in;
+	bool container = is_container_obj(obj);
 
 	blobmsg_parse(service_del_attrs, __SERVICE_DEL_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
 
@@ -402,13 +427,17 @@ service_handle_delete(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!cur)
 		return UBUS_STATUS_NOT_FOUND;
 
-	s = avl_find_element(&services, blobmsg_data(cur), s, avl);
+	if (container)
+		s = avl_find_element(&containers, blobmsg_data(cur), s, avl);
+	else
+		s = avl_find_element(&services, blobmsg_data(cur), s, avl);
+
 	if (!s)
 		return UBUS_STATUS_NOT_FOUND;
 
 	cur = tb[SERVICE_DEL_ATTR_INSTANCE];
 	if (!cur) {
-		service_delete(s);
+		service_delete(s, container);
 		return 0;
 	}
 
@@ -446,6 +475,7 @@ service_handle_signal(struct ubus_context *ctx, struct ubus_object *obj,
 	struct blob_attr *tb[__SERVICE_SIGNAL_ATTR_MAX], *cur;
 	struct service *s;
 	struct service_instance *in;
+	bool container = is_container_obj(obj);
 	int sig = SIGHUP;
 	int rv = 0;
 
@@ -459,7 +489,11 @@ service_handle_signal(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!cur)
 		return UBUS_STATUS_NOT_FOUND;
 
-	s = avl_find_element(&services, blobmsg_data(cur), s, avl);
+	if (container)
+		s = avl_find_element(&containers, blobmsg_data(cur), s, avl);
+	else
+		s = avl_find_element(&services, blobmsg_data(cur), s, avl);
+
 	if (!s)
 		return UBUS_STATUS_NOT_FOUND;
 
@@ -488,6 +522,7 @@ service_handle_state(struct ubus_context *ctx, struct ubus_object *obj,
 	struct blob_attr *tb[__SERVICE_STATE_ATTR_MAX];
 	struct service *s;
 	struct service_instance *in;
+	bool container = is_container_obj(obj);
 	int spawn;
 
 	blobmsg_parse(service_state_attrs, __SERVICE_STATE_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
@@ -498,7 +533,11 @@ service_handle_state(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!tb[SERVICE_STATE_ATTR_NAME])
 		return UBUS_STATUS_NOT_FOUND;
 
-	s = avl_find_element(&services, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl);
+	if (container)
+		s = avl_find_element(&containers, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl);
+	else
+		s = avl_find_element(&services, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl);
+
 	if (!s)
 		return UBUS_STATUS_NOT_FOUND;
 
@@ -522,6 +561,7 @@ service_handle_update(struct ubus_context *ctx, struct ubus_object *obj,
 {
 	struct blob_attr *tb[__SERVICE_ATTR_MAX], *cur;
 	struct service *s;
+	bool container = is_container_obj(obj);
 
 	blobmsg_parse(service_attrs, __SERVICE_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
 
@@ -529,7 +569,11 @@ service_handle_update(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!cur)
 		return UBUS_STATUS_INVALID_ARGUMENT;
 
-	s = avl_find_element(&services, blobmsg_data(cur), s, avl);
+	if (container)
+		s = avl_find_element(&containers, blobmsg_data(cur), s, avl);
+	else
+		s = avl_find_element(&services, blobmsg_data(cur), s, avl);
+
 	if (!s)
 		return UBUS_STATUS_NOT_FOUND;
 
@@ -684,12 +728,12 @@ service_get_data(struct ubus_context *ctx, struct ubus_object *obj,
 }
 
 static int
-service_handle_console(struct ubus_context *ctx, struct ubus_object *obj,
-			struct ubus_request_data *req, const char *method,
-			struct blob_attr *msg)
+container_handle_console(struct ubus_context *ctx, struct ubus_object *obj,
+			 struct ubus_request_data *req, const char *method,
+			 struct blob_attr *msg)
 {
 	bool attach = !strcmp(method, "console_attach");
-	struct blob_attr *tb[__SERVICE_CONSOLE_MAX];
+	struct blob_attr *tb[__CONTAINER_CONSOLE_MAX];
 	struct service *s;
 	struct service_instance *in;
 	int console_fd = -1;
@@ -701,16 +745,16 @@ service_handle_console(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!msg)
 		goto err_console_fd;
 
-	blobmsg_parse(service_console_policy, __SERVICE_CONSOLE_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
-	if (!tb[SERVICE_CONSOLE_NAME])
+	blobmsg_parse(container_console_policy, __CONTAINER_CONSOLE_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
+	if (!tb[CONTAINER_CONSOLE_NAME])
 		goto err_console_fd;
 
-	s = avl_find_element(&services, blobmsg_data(tb[SERVICE_CONSOLE_NAME]), s, avl);
+	s = avl_find_element(&containers, blobmsg_data(tb[CONTAINER_CONSOLE_NAME]), s, avl);
 	if (!s)
 		goto err_console_fd;
 
-	if (tb[SERVICE_CONSOLE_INSTANCE]) {
-		in = vlist_find(&s->instances, blobmsg_data(tb[SERVICE_CONSOLE_INSTANCE]), in, node);
+	if (tb[CONTAINER_CONSOLE_INSTANCE]) {
+		in = vlist_find(&s->instances, blobmsg_data(tb[CONTAINER_CONSOLE_INSTANCE]), in, node);
 	} else {
 		/* use first element in instances list */
 		vlist_for_each_element(&s->instances, in, node)
@@ -753,8 +797,6 @@ static struct ubus_method main_object_methods[] = {
 	UBUS_METHOD("validate", service_handle_validate, validate_policy),
 	UBUS_METHOD("get_data", service_get_data, get_data_policy),
 	UBUS_METHOD("state", service_handle_state, service_state_attrs),
-	UBUS_METHOD("console_set", service_handle_console, service_console_policy),
-	UBUS_METHOD("console_attach", service_handle_console, service_console_policy),
 };
 
 static struct ubus_object_type main_object_type =
@@ -796,10 +838,20 @@ service_start_early(char *name, char *cmdline)
 }
 
 void service_stopped(struct service *s)
+{
+	_service_stopped(s, false);
+}
+
+static void _service_stopped(struct service *s, bool container)
 {
 	if (s->deleted && avl_is_empty(&s->instances.avl)) {
-		service_event("service.stop", s->name, NULL);
-		avl_delete(&services, &s->avl);
+		if (container) {
+			service_event("container.stop", s->name, NULL);
+			avl_delete(&containers, &s->avl);
+		} else {
+			service_event("service.stop", s->name, NULL);
+			avl_delete(&services, &s->avl);
+		}
 		trigger_del(s);
 		service_validate_del(s);
 		free(s->trigger);
@@ -812,8 +864,34 @@ void service_event(const char *type, const char *service, const char *instance)
 	ubus_event_bcast(type, "service", service, "instance", instance);
 }
 
+static struct ubus_method container_object_methods[] = {
+	UBUS_METHOD("set", service_handle_set, service_set_attrs),
+	UBUS_METHOD("add", service_handle_set, service_set_attrs),
+	UBUS_METHOD("list", service_handle_list, service_list_attrs),
+	UBUS_METHOD("delete", service_handle_delete, service_del_attrs),
+	UBUS_METHOD("signal", service_handle_signal, service_signal_attrs),
+	UBUS_METHOD("state", service_handle_state, service_state_attrs),
+	UBUS_METHOD("console_set", container_handle_console, container_console_policy),
+	UBUS_METHOD("console_attach", container_handle_console, container_console_policy),
+};
+
+static struct ubus_object_type container_object_type =
+	UBUS_OBJECT_TYPE("container", container_object_methods);
+
+static struct ubus_object container_object = {
+	.name = "container",
+	.type = &container_object_type,
+	.methods = container_object_methods,
+	.n_methods = ARRAY_SIZE(container_object_methods),
+};
+
 void ubus_init_service(struct ubus_context *_ctx)
 {
+	struct stat statbuf;
+
 	ctx = _ctx;
 	ubus_add_object(ctx, &main_object);
+
+	if (!stat("/sbin/ujail", &statbuf))
+		ubus_add_object(ctx, &container_object);
 }

+ 1 - 0
service/service.h

@@ -21,6 +21,7 @@
 #include "../utils/utils.h"
 
 extern struct avl_tree services;
+extern struct avl_tree containers;
 
 struct vrule {
 	struct avl_node avl;