initd: mount cgroup
[project/procd.git] / service / service.c
index 8d1217f..a0fa2d5 100644 (file)
@@ -24,6 +24,7 @@
 
 struct avl_tree services;
 static struct blob_buf b;
+static struct ubus_context *ctx;
 
 static void
 service_instance_add(struct service *s, struct blob_attr *attr)
@@ -65,6 +66,8 @@ service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new,
                DEBUG(2, "Create instance %s::%s\n", in_n->srv->name, in_n->name);
                instance_start(in_n);
        }
+       blob_buf_init(&b, 0);
+       trigger_event("instance.update", b.head);
 }
 
 static struct service *
@@ -146,6 +149,7 @@ service_update(struct service *s, struct blob_attr **tb, bool add)
 static void
 service_delete(struct service *s)
 {
+       service_event("service.stop", s->name, NULL);
        vlist_flush_all(&s->instances);
        avl_delete(&services, &s->avl);
        trigger_del(s);
@@ -207,6 +211,10 @@ static const struct blobmsg_policy validate_policy[__VALIDATE_MAX] = {
        [VALIDATE_SERVICE] = { .name = "service", .type = BLOBMSG_TYPE_STRING },
 };
 
+static const struct blobmsg_policy get_data_policy[] = {
+       { "type", BLOBMSG_TYPE_STRING }
+};
+
 static int
 service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
                   struct ubus_request_data *req, const char *method,
@@ -242,6 +250,8 @@ service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 
        avl_insert(&services, &s->avl);
 
+       service_event("service.start", s->name, NULL);
+
        return 0;
 }
 
@@ -398,6 +408,53 @@ service_handle_validate(struct ubus_context *ctx, struct ubus_object *obj,
        return 0;
 }
 
+static int
+service_get_data(struct ubus_context *ctx, struct ubus_object *obj,
+                struct ubus_request_data *req, const char *method,
+                struct blob_attr *msg)
+{
+       struct service_instance *in;
+       struct service *s;
+       struct blob_attr *tb;
+       const char *type = NULL;
+
+       blobmsg_parse(get_data_policy, 1, &tb, blob_data(msg), blob_len(msg));
+       if (tb)
+               type = blobmsg_data(tb);
+
+       blob_buf_init(&b, 0);
+       avl_for_each_element(&services, s, avl) {
+               void *cs = NULL;
+
+               vlist_for_each_element(&s->instances, in, node) {
+                       struct blobmsg_list_node *var;
+                       void *ci = NULL;
+
+                       blobmsg_list_for_each(&in->data, var) {
+                               if (type &&
+                                   strcmp(blobmsg_name(var->data), type) != 0)
+                                       continue;
+
+                               if (!cs)
+                                       cs = blobmsg_open_table(&b, s->name);
+                               if (!ci)
+                                       ci = blobmsg_open_table(&b, in->name);
+
+                               blobmsg_add_blob(&b, var->data);
+                       }
+
+                       if (ci)
+                               blobmsg_close_table(&b, ci);
+               }
+
+               if (cs)
+                       blobmsg_close_table(&b, cs);
+       }
+
+       ubus_send_reply(ctx, req, b.head);
+       return 0;
+}
+
 static struct ubus_method main_object_methods[] = {
        UBUS_METHOD("set", service_handle_set, service_set_attrs),
        UBUS_METHOD("add", service_handle_set, service_set_attrs),
@@ -407,6 +464,7 @@ static struct ubus_method main_object_methods[] = {
        UBUS_METHOD("update_complete", service_handle_update, service_attrs),
        UBUS_METHOD("event", service_handle_event, event_policy),
        UBUS_METHOD("validate", service_handle_validate, validate_policy),
+       UBUS_METHOD("get_data", service_get_data, get_data_policy),
 };
 
 static struct ubus_object_type main_object_type =
@@ -447,8 +505,21 @@ service_start_early(char *name, char *cmdline)
        return service_handle_set(NULL, NULL, NULL, "add", b.head);
 }
 
-void ubus_init_service(struct ubus_context *ctx)
+void service_event(const char *type, const char *service, const char *instance)
+{
+       if (!ctx)
+               return;
+
+       blob_buf_init(&b, 0);
+       blobmsg_add_string(&b, "service", service);
+       if (instance)
+               blobmsg_add_string(&b, "instance", instance);
+       ubus_notify(ctx, &main_object, type, b.head, -1);
+}
+
+void ubus_init_service(struct ubus_context *_ctx)
 {
+       ctx = _ctx;
        ubus_add_object(ctx, &main_object);
 }