]> git.ozlabs.org Git - petitboot/blobdiff - discover/user-event.c
discover: Remove unnecessary event passing
[petitboot] / discover / user-event.c
index afc4c437e8a7809f685a1a03a3e2bb5af31d6819..275d9e24244a430b46201e0a55c7cce86877aa1e 100644 (file)
 #include <sys/un.h>
 
 #include <log/log.h>
+#include <url/url.h>
+#include <types/types.h>
 #include <talloc/talloc.h>
 #include <waiter/waiter.h>
 
 #include "device-handler.h"
+#include "resource.h"
 #include "event.h"
 #include "user-event.h"
 
@@ -42,22 +45,182 @@ struct user_event {
        int socket;
 };
 
+static const char *event_action_name(enum event_action action)
+{
+       switch (action) {
+       case EVENT_ACTION_ADD:
+               return "add";
+       case EVENT_ACTION_REMOVE:
+               return "remove";
+       case EVENT_ACTION_CONF:
+               return "conf";
+       default:
+               break;
+       }
+
+       return "unknown";
+}
+
 static void user_event_print_event(struct event __attribute__((unused)) *event)
 {
-       const char *action, *params[] = {
-               "name", "image", "args",
-               NULL,
-       };
        int i;
 
-       action = event->action == EVENT_ACTION_ADD ? "add" : "remove";
-
-       pb_log("user_event %s event:\n", action);
+       pb_log("user_event %s event:\n", event_action_name(event->action));
        pb_log("\tdevice: %s\n", event->device);
 
-       for (i = 0; params[i]; i++)
+       for (i = 0; i < event->n_params; i++)
                pb_log("\t%-12s => %s\n",
-                               params[i], event_get_param(event, params[i]));
+                       event->params[i].name, event->params[i].value);
+}
+
+static enum conf_method parse_conf_method(const char *str)
+{
+
+       if (!strcasecmp(str, "dhcp")) {
+               return CONF_METHOD_DHCP;
+       }
+       return CONF_METHOD_UNKNOWN;
+}
+
+static struct resource *user_event_resource(struct discover_boot_option *opt,
+               struct event *event, const char *param_name)
+{
+       struct resource *res;
+       struct pb_url *url;
+       const char *val;
+
+       val = event_get_param(event, param_name);
+       if (!val)
+               return NULL;
+
+       url = pb_url_parse(opt, val);
+       if (!url)
+               return NULL;
+
+       res = create_url_resource(opt, url);
+       if (!res) {
+               talloc_free(url);
+               return NULL;
+       }
+
+       return res;
+}
+
+static int parse_user_event(struct discover_context *ctx, struct event *event)
+{
+       struct discover_boot_option *d_opt;
+       struct boot_option *opt;
+       struct device *dev;
+       const char *p;
+
+       dev = ctx->device->device;
+
+       d_opt = discover_boot_option_create(ctx, ctx->device);
+       opt = d_opt->option;
+
+       if (!d_opt)
+               goto fail;
+
+       p = event_get_param(event, "name");
+
+       if (!p) {
+               pb_log("%s: no name found\n", __func__);
+               goto fail;
+       }
+
+       opt->id = talloc_asprintf(opt, "%s#%s", dev->id, p);
+       opt->name = talloc_strdup(opt, p);
+
+       d_opt->boot_image = user_event_resource(d_opt, event, "image");
+       if (!d_opt->boot_image) {
+               pb_log("%s: no boot image found for %s!\n", __func__,
+                               opt->name);
+               goto fail;
+       }
+
+       d_opt->initrd = user_event_resource(d_opt, event, "initrd");
+
+       p = event_get_param(event, "args");
+
+       if (p)
+               opt->boot_args = talloc_strdup(opt, p);
+
+       opt->description = talloc_asprintf(opt, "%s %s", opt->boot_image_file,
+               opt->boot_args ? : "");
+
+       if (event_get_param(event, "default"))
+               opt->is_default = true;
+
+       discover_context_add_boot_option(ctx, d_opt);
+
+       return 0;
+
+fail:
+       talloc_free(d_opt);
+       return -1;
+}
+
+static int user_event_conf(struct user_event *uev, struct event *event)
+{
+       struct device_handler *handler = uev->handler;
+       struct discover_device *dev;
+       enum conf_method method;
+       struct pb_url *url;
+       const char *val;
+
+       val = event_get_param(event, "url");
+       if (!val)
+               return 0;
+
+       url = pb_url_parse(event, val);
+       if (!url)
+               return 0;
+
+       val = event_get_param(event, "method");
+       if (!val)
+               return 0;
+
+       method = parse_conf_method(val);
+       if (method == CONF_METHOD_UNKNOWN)
+               return 0;
+
+       dev = discover_device_create(handler, event->device);
+
+       device_handler_conf(handler, dev, url, method);
+
+       return 0;
+}
+
+static int user_event_add(struct user_event *uev, struct event *event)
+{
+       struct device_handler *handler = uev->handler;
+       struct discover_context *ctx;
+       struct discover_device *dev;
+
+       dev = discover_device_create(handler, event->device);
+       ctx = device_handler_discover_context_create(handler, dev);
+
+       parse_user_event(ctx, event);
+
+       device_handler_discover_context_commit(handler, ctx);
+
+       talloc_free(ctx);
+
+       return 0;
+}
+
+static int user_event_remove(struct user_event *uev, struct event *event)
+{
+       struct device_handler *handler = uev->handler;
+       struct discover_device *dev;
+
+       dev = device_lookup_by_id(handler, event->device);
+       if (!dev)
+               return 0;
+
+       device_handler_remove(handler, dev);
+
+       return 0;
 }
 
 static void user_event_handle_message(struct user_event *uev, char *buf,
@@ -75,7 +238,21 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
                return;
 
        user_event_print_event(event);
-       device_handler_event(uev->handler, event);
+
+       switch (event->action) {
+       case EVENT_ACTION_ADD:
+               result = user_event_add(uev, event);
+               break;
+       case EVENT_ACTION_REMOVE:
+               result = user_event_remove(uev, event);
+               break;
+       case EVENT_ACTION_CONF:
+               result = user_event_conf(uev, event);
+               break;
+       default:
+               break;
+       }
+
        talloc_free(event);
 
        return;
@@ -118,7 +295,8 @@ static int user_event_destructor(void *arg)
        return 0;
 }
 
-struct user_event *user_event_init(struct device_handler *handler)
+struct user_event *user_event_init(struct waitset *waitset,
+               struct device_handler *handler)
 {
        struct sockaddr_un addr;
        struct user_event *uev;
@@ -147,7 +325,8 @@ struct user_event *user_event_init(struct device_handler *handler)
                        strerror(errno));
        }
 
-       waiter_register(uev->socket, WAIT_IN, user_event_process, uev);
+       waiter_register_io(waitset, uev->socket, WAIT_IN,
+                       user_event_process, uev);
 
        pb_log("%s: waiting on %s\n", __func__, PBOOT_USER_EVENT_SOCKET);
 
@@ -158,17 +337,6 @@ out_err:
        return NULL;
 }
 
-/**
- * user_event_trigger - Trigger known user events
- *
- * SIGUSR1 causes udhcpc to renew the current lease or obtain a new lease.
- */
-
-void user_event_trigger(struct user_event __attribute__((unused)) *uev)
-{
-       /* FIXME: todo */
-}
-
 void user_event_destroy(struct user_event *uev)
 {
        talloc_free(uev);