From 2a9e3a38973499aad922ba080f3d236f938137d8 Mon Sep 17 00:00:00 2001 From: Marius Tomaschewski Date: Wed, 30 Jul 2014 09:21:09 +0200 Subject: [PATCH] ifup/ifreload: use interface wait time settings --- client/ifreload.c | 19 ++--- client/ifup.c | 157 +++++++++++++++++++++++++++++++---------- client/wicked-client.h | 12 +++- 3 files changed, 134 insertions(+), 54 deletions(-) diff --git a/client/ifreload.c b/client/ifreload.c index ba1688cfc..16ad0e3b9 100644 --- a/client/ifreload.c +++ b/client/ifreload.c @@ -364,6 +364,7 @@ ni_do_ifreload_nanny(int argc, char **argv) ni_string_array_t opt_ifconfig = NI_STRING_ARRAY_INIT; ni_ifworker_array_t up_marked = NI_IFWORKER_ARRAY_INIT; ni_ifworker_array_t down_marked = NI_IFWORKER_ARRAY_INIT; + ni_nanny_fsm_monitor_t *monitor = NULL; ni_ifmatcher_t ifmatch; ni_bool_t check_prio = TRUE; ni_bool_t set_persistent = FALSE; @@ -592,29 +593,20 @@ ni_do_ifreload_nanny(int argc, char **argv) /* anything to ifup? */ if (up_marked.count) { - if (!ni_client_create(fsm, &up_marked)) { + if (!(monitor = ni_nanny_fsm_monitor_new(fsm))) { /* Severe error we always explicitly return */ status = NI_WICKED_RC_ERROR; goto cleanup; } + ni_nanny_fsm_monitor_arm(monitor, ni_wait_for_interfaces); /* And trigger up */ ni_debug_application("Reloading all changed devices"); if (!ni_ifup_hire_nanny(&up_marked, set_persistent)) status = NI_WICKED_RC_NOT_CONFIGURED; - /* Wait for device-up events */ - ni_timer_register(ni_wait_for_interfaces, ni_client_timer_expires, &status); - while (status == NI_WICKED_RC_SUCCESS) { - /* status is already success */ - if (0 == up_marked.count) - break; - - if (ni_socket_wait(ni_wait_for_interfaces) != 0) - ni_fatal("ni_socket_wait failed"); - - ni_timer_next_timeout(); - } + /* Wait for device up-transition progress events */ + status = ni_nanny_fsm_monitor_run(monitor, &up_marked, status); /* Do not report any transient errors to systemd (e.g. dhcp * or whatever not ready in time) -- returning an error may @@ -628,6 +620,7 @@ ni_do_ifreload_nanny(int argc, char **argv) } cleanup: + ni_nanny_fsm_monitor_free(monitor); ni_string_array_destroy(&opt_ifconfig); ni_ifworker_array_destroy(&down_marked); ni_ifworker_array_destroy(&up_marked); diff --git a/client/ifup.c b/client/ifup.c index 1ec55a49a..2ec1c0487 100644 --- a/client/ifup.c +++ b/client/ifup.c @@ -45,6 +45,14 @@ #include "appconfig.h" #include "ifup.h" +struct ni_nanny_fsm_monitor { + const ni_timer_t * timer; + unsigned long timeout; + ni_ifworker_array_t * marked; + /* TODO: per worker status reporting */ + int status; +}; + static xml_node_t * __ni_ifup_generate_match_dev(xml_node_t *node, ni_ifworker_t *w) { @@ -234,18 +242,18 @@ ni_ifup_hire_nanny(ni_ifworker_array_t *array, ni_bool_t set_persistent) * We want to wait for this signal and when it is >= device-up return TRUE. * After timeout we fail... */ -void -ni_state_change_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *msg, void *user_data) +static void +ni_nanny_fsm_monitor_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *msg, void *user_data) { const char *signal_name = dbus_message_get_member(msg); const char *object_path = dbus_message_get_path(msg); ni_dbus_variant_t argv = NI_DBUS_VARIANT_INIT; - ni_ifworker_array_t *ifworkers = user_data; + ni_nanny_fsm_monitor_t *monitor = user_data; ni_fsm_state_t cur_state, target_state; const char *ifname; unsigned int i; - if (ni_string_empty(object_path)) + if (ni_string_empty(object_path) || !monitor || !monitor->marked) return; /* Deserialize dbus message */ @@ -268,8 +276,8 @@ ni_state_change_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *ms signal_name, object_path, ni_ifworker_state_name(target_state), ni_ifworker_state_name(cur_state)); - for (i = 0; i < ifworkers->count; ++i) { - ni_ifworker_t *w = ifworkers->data[i]; + for (i = 0; i < monitor->marked->count; ++i) { + ni_ifworker_t *w = monitor->marked->data[i]; if (cur_state != NI_FSM_STATE_NONE && cur_state != target_state) continue; @@ -279,41 +287,122 @@ ni_state_change_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *ms ni_note("%s: %s [%s]", ifname, ni_ifworker_state_name(target_state), cur_state == target_state ? "success" : "failure"); - ni_ifworker_array_remove_with_children(ifworkers, w); + ni_ifworker_array_remove_with_children(monitor->marked, w); + break; } ni_dbus_variant_destroy(&argv); } void -ni_client_timer_expires(void *user_data, const ni_timer_t *timer) +ni_nanny_fsm_monitor_timeout(void *user_data, const ni_timer_t *timer) +{ + ni_nanny_fsm_monitor_t *monitor = user_data; + + if (monitor && timer == monitor->timer) { + monitor->timer = NULL; + monitor->timeout = 0; + ni_info("Interface wait time reached"); + /* TODO: status reporting */ + monitor->status = NI_WICKED_RC_ERROR; + } +} + +ni_nanny_fsm_monitor_t * +ni_nanny_fsm_monitor_new(ni_fsm_t *fsm) { - int *status; + ni_nanny_fsm_monitor_t *monitor; + ni_dbus_client_t *client; + + if (!fsm) + return NULL; - ni_assert(user_data); - status = user_data; + if (!(fsm->client_root_object = ni_call_create_client())) + return NULL; - (void) timer; - *status = NI_WICKED_RC_ERROR; - ni_note("Interface wait time reached"); + if (!(client = ni_dbus_object_get_client(fsm->client_root_object))) + return NULL; + + monitor = calloc(1, sizeof(*monitor)); + if (monitor) { + monitor->status = NI_WICKED_RC_SUCCESS; + ni_dbus_client_add_signal_handler(client, NULL, NULL, + NI_OBJECTMODEL_MANAGED_NETIF_INTERFACE, + ni_nanny_fsm_monitor_handler, monitor); + } + return monitor; } ni_bool_t -ni_client_create(ni_fsm_t *fsm, void *user_data) +ni_nanny_fsm_monitor_arm(ni_nanny_fsm_monitor_t *monitor, unsigned long timeout) { - ni_dbus_client_t *client; + if (monitor) { + monitor->timeout = timeout; + if (monitor->timer) + monitor->timer = ni_timer_rearm(monitor->timer, timeout); + else + monitor->timer = ni_timer_register(timeout, + ni_nanny_fsm_monitor_timeout, monitor); + return monitor->timer != NULL; + } + return FALSE; +} - if (!(fsm->client_root_object = ni_call_create_client())) - return FALSE; +int +ni_nanny_fsm_monitor_run(ni_nanny_fsm_monitor_t *monitor, ni_ifworker_array_t *marked, int status) +{ + if (!monitor || monitor->marked || !marked) + return NI_WICKED_RC_ERROR; - client = ni_dbus_object_get_client(fsm->client_root_object); + /* TODO: status reporting */ + monitor->status = status; + monitor->marked = marked; + while (!ni_caught_terminal_signal()) { + long timeout; - ni_dbus_client_add_signal_handler(client, NULL, NULL, - NI_OBJECTMODEL_MANAGED_NETIF_INTERFACE, - ni_state_change_signal_handler, user_data); + /* TODO: status reporting */ + if (monitor->status != NI_WICKED_RC_SUCCESS) + break; + if (!monitor->marked || !monitor->marked->count) + break; - return TRUE; + timeout = ni_timer_next_timeout(); + if (monitor->timeout == 0 || + (monitor->timeout > 0 && timeout < 0)) + break; + + if (ni_socket_wait(timeout) != 0) + break; + } + + if (monitor->timer) { + ni_timer_cancel(monitor->timer); + monitor->timer = NULL; + } + return monitor->status; +} + +void +ni_nanny_fsm_monitor_reset(ni_nanny_fsm_monitor_t *monitor) +{ + if (monitor) { + monitor->timeout = 0; + if (monitor->timer) { + ni_timer_cancel(monitor->timer); + monitor->timer = NULL; + } + monitor->marked = NULL; + /* TODO: status reporting */ + monitor->status = NI_WICKED_RC_SUCCESS; + } +} + +void +ni_nanny_fsm_monitor_free(ni_nanny_fsm_monitor_t *monitor) +{ + ni_nanny_fsm_monitor_reset(monitor); + free(monitor); } static int @@ -345,6 +434,7 @@ ni_do_ifup_nanny(int argc, char **argv) ni_ifmatcher_t ifmatch; ni_ifworker_array_t ifmarked; + ni_nanny_fsm_monitor_t *monitor = NULL; ni_string_array_t opt_ifconfig = NI_STRING_ARRAY_INIT; ni_bool_t check_prio = TRUE, set_persistent = FALSE; ni_bool_t opt_transient = FALSE; @@ -461,7 +551,7 @@ ni_do_ifup_nanny(int argc, char **argv) goto usage; } - if (!ni_client_create(fsm, &ifmarked) || !ni_fsm_refresh_state(fsm)) { + if (!(monitor = ni_nanny_fsm_monitor_new(fsm)) || !ni_fsm_refresh_state(fsm)) { /* Severe error we always explicitly return */ status = NI_WICKED_RC_ERROR; goto cleanup; @@ -491,8 +581,8 @@ ni_do_ifup_nanny(int argc, char **argv) else ni_wait_for_interfaces *= 1000; /* in msec */ - if (ni_wait_for_interfaces) - fsm->worker_timeout = ni_wait_for_interfaces; + fsm->worker_timeout = ni_wait_for_interfaces; + ni_nanny_fsm_monitor_arm(monitor, ni_wait_for_interfaces); if (ni_fsm_build_hierarchy(fsm, TRUE) < 0) { ni_error("ifup: unable to build device hierarchy"); @@ -521,18 +611,8 @@ ni_do_ifup_nanny(int argc, char **argv) if (!ni_ifup_hire_nanny(&ifmarked, set_persistent)) status = NI_WICKED_RC_NOT_CONFIGURED; - /* Wait for device-up events */ - ni_timer_register(ni_wait_for_interfaces, ni_client_timer_expires, &status); - while (status == NI_WICKED_RC_SUCCESS) { - /* status is already success */ - if (0 == ifmarked.count) - break; - - if (ni_socket_wait(ni_wait_for_interfaces) != 0) - ni_fatal("ni_socket_wait failed"); - - ni_timer_next_timeout(); - } + /* Wait for device up-transition progress events */ + status = ni_nanny_fsm_monitor_run(monitor, &ifmarked, status); /* Do not report any transient errors to systemd (e.g. dhcp * or whatever not ready in time) -- returning an error may @@ -542,6 +622,7 @@ ni_do_ifup_nanny(int argc, char **argv) status = NI_LSB_RC_SUCCESS; cleanup: + ni_nanny_fsm_monitor_free(monitor); ni_ifworker_array_destroy(&ifmarked); ni_string_array_destroy(&opt_ifconfig); return status; diff --git a/client/wicked-client.h b/client/wicked-client.h index 0c6ce3495..60be65c42 100644 --- a/client/wicked-client.h +++ b/client/wicked-client.h @@ -122,9 +122,15 @@ extern void ni_ifconfig_metadata_add_to_node(xml_node_t *, ni_client_state_con extern ni_bool_t ni_ifconfig_metadata_get_from_node(ni_client_state_config_t *, xml_node_t *); extern void ni_ifconfig_metadata_clear(xml_node_t *); -extern void ni_state_change_signal_handler(ni_dbus_connection_t *, ni_dbus_message_t *, void *); -extern void ni_client_timer_expires(void *, const ni_timer_t *); -extern ni_bool_t ni_client_create(ni_fsm_t *, void *); +typedef struct ni_nanny_fsm_monitor ni_nanny_fsm_monitor_t; + +extern ni_nanny_fsm_monitor_t * ni_nanny_fsm_monitor_new(ni_fsm_t *); +extern ni_bool_t ni_nanny_fsm_monitor_arm(ni_nanny_fsm_monitor_t *, + unsigned long); +extern int ni_nanny_fsm_monitor_run(ni_nanny_fsm_monitor_t *, + ni_ifworker_array_t *, int); +extern void ni_nanny_fsm_monitor_reset(ni_nanny_fsm_monitor_t *); +extern void ni_nanny_fsm_monitor_free(ni_nanny_fsm_monitor_t *); static inline void ni_client_get_state_strings(ni_stringbuf_t *sb, const ni_uint_range_t *range)