#include "ipmi.h"
enum default_priority {
- DEFAULT_PRIORITY_REMOTE = 1,
- DEFAULT_PRIORITY_LOCAL_FIRST = 2,
+ DEFAULT_PRIORITY_TEMP_USER = 1,
+ DEFAULT_PRIORITY_REMOTE = 2,
+ DEFAULT_PRIORITY_LOCAL_FIRST = 3,
DEFAULT_PRIORITY_LOCAL_LAST = 0xfe,
DEFAULT_PRIORITY_DISABLED = 0xff,
};
struct waiter *timeout_waiter;
bool autoboot_enabled;
unsigned int sec_to_boot;
+ struct autoboot_option *temp_autoboot;
struct discover_boot_option *default_boot_option;
int default_boot_option_priority;
return false;
}
+static bool autoboot_option_matches(struct autoboot_option *opt,
+ struct discover_device *dev)
+{
+ if (opt->boot_type == BOOT_DEVICE_UUID)
+ if (!strcmp(opt->uuid, dev->uuid))
+ return true;
+
+ if (opt->boot_type == BOOT_DEVICE_TYPE)
+ if (opt->type == dev->device->type ||
+ opt->type == DEVICE_TYPE_ANY)
+ return true;
+
+ return false;
+}
+
static int autoboot_option_priority(const struct config *config,
struct discover_boot_option *opt)
{
- enum device_type type = opt->device->device->type;
- const char *uuid = opt->device->uuid;
struct autoboot_option *auto_opt;
unsigned int i;
for (i = 0; i < config->n_autoboot_opts; i++) {
auto_opt = &config->autoboot_opts[i];
- if (auto_opt->boot_type == BOOT_DEVICE_UUID)
- if (!strcmp(auto_opt->uuid, uuid))
- return DEFAULT_PRIORITY_LOCAL_FIRST + i;
-
- if (auto_opt->boot_type == BOOT_DEVICE_TYPE)
- if (auto_opt->type == type ||
- auto_opt->type == DEVICE_TYPE_ANY)
- return DEFAULT_PRIORITY_LOCAL_FIRST + i;
+ if (autoboot_option_matches(auto_opt, opt->device))
+ return DEFAULT_PRIORITY_LOCAL_FIRST + i;
}
return -1;
* for these options.
*/
static enum default_priority default_option_priority(
+ struct device_handler *handler,
struct discover_boot_option *opt)
{
const struct config *config;
+ /* Temporary user-provided autoboot options have highest priority */
+ if (handler->temp_autoboot) {
+ if (autoboot_option_matches(handler->temp_autoboot,
+ opt->device))
+ return DEFAULT_PRIORITY_TEMP_USER;
+
+ pb_debug("handler: disabled default priority due to "
+ "temporary user override\n");
+ return DEFAULT_PRIORITY_DISABLED;
+ }
+
config = config_get();
- /* We give highest priority to IPMI-configured boot options. If
- * we have an IPMI bootdev configuration set, then we don't allow
- * any other defaults */
+ /* Next highest priority to IPMI-configured boot options. If we have an
+ * IPMI bootdev configuration set, then we don't allow any other
+ * defaults */
if (config->ipmi_bootdev) {
bool ipmi_match = ipmi_device_type_matches(config->ipmi_bootdev,
opt->device->device->type);
pb_debug("handler: new default option: %s\n", opt->option->id);
- new_prio = default_option_priority(opt);
+ new_prio = default_option_priority(handler, opt);
/* Anything outside our range prevents a default boot */
if (new_prio >= DEFAULT_PRIORITY_DISABLED)
default_timeout(handler);
}
+static char *autoboot_option_desc(void *ctx, const struct autoboot_option *opt)
+{
+ const char *type, *val;
+
+ if (opt->boot_type == BOOT_DEVICE_TYPE) {
+ type = _("device type");
+ val = device_type_display_name(opt->type);
+ } else if (opt->boot_type == BOOT_DEVICE_UUID) {
+ type = _("device UUID");
+ val = opt->uuid;
+ } else {
+ type = _("unknown specifier");
+ val = NULL;
+ }
+
+ return talloc_asprintf(ctx, "%s = %s", type, val);
+}
+
+void device_handler_apply_temp_autoboot(struct device_handler *handler,
+ struct autoboot_option *opt)
+{
+ unsigned int i;
+ char *desc;
+
+ handler->temp_autoboot = talloc_steal(handler, opt);
+
+ desc = autoboot_option_desc(handler, opt);
+ device_handler_status_info(handler,
+ _("Applying temporary autoboot override: %s"),
+ desc);
+ talloc_free(desc);
+
+ if (!handler->autoboot_enabled)
+ return;
+
+ if (!handler->default_boot_option)
+ return;
+
+ if (autoboot_option_matches(opt, handler->default_boot_option->device))
+ return;
+
+ /* cancel the default, and rescan available options */
+ device_handler_cancel_default(handler);
+
+ handler->autoboot_enabled = true;
+
+ for (i = 0; i < handler->n_devices; i++) {
+ struct discover_device *dev = handler->devices[i];
+ struct discover_boot_option *boot_opt;
+
+ if (!autoboot_option_matches(opt, dev))
+ continue;
+
+ list_for_each_entry(&dev->boot_options, boot_opt, list) {
+ if (boot_opt->option->is_default) {
+ set_default(handler, boot_opt);
+ break;
+ }
+ }
+ }
+}
+
static bool resource_is_resolved(struct resource *res)
{
return !res || res->resolved;