jail: handle containers seperately master
authorDaniel Golle <daniel@makrotopia.org>
Wed, 20 May 2020 14:26:08 +0000 (15:26 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Thu, 28 May 2020 10:44:23 +0000 (11:44 +0100)
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>
jail/console.c
jail/jail.c
service/service.c
service/service.h

index d03edc54a25e8f53959f9282bdb269982f2af1ac..eacb2fa9649199cc90c1fc37bdc25c3d5db2b3d5 100644 (file)
@@ -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);
index 540b8d4e0d7ad2150b03dd24cd811857b2f18251..45906904451bee621108f7e5df3fb12930fe2538 100644 (file)
@@ -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
index 1d262917641ea741ef11c875962e55f957711951..fcf021556df8910614187baa13709cd9d8e9230e 100644 (file)
  * 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);
 }
index 8f94ecdaa317c6e87a5731dbbd4480d00a8010d3..fac5da9d2d047058d6b81ac179df8d33df05829c 100644 (file)
@@ -21,6 +21,7 @@
 #include "../utils/utils.h"
 
 extern struct avl_tree services;
+extern struct avl_tree containers;
 
 struct vrule {
        struct avl_node avl;