Skip to content

Commit

Permalink
Merge pull request #109 from pwieczorkiewicz/client-state-feature
Browse files Browse the repository at this point in the history
Client-state feature: persistent state, fsm correction with ifup, ifdown, ifcheck corrections
  • Loading branch information
mtomaschewski committed Nov 22, 2013
2 parents c84d121 + a1b8d89 commit ace458c
Show file tree
Hide file tree
Showing 25 changed files with 1,064 additions and 142 deletions.
4 changes: 2 additions & 2 deletions client/compat-redhat.c
Expand Up @@ -192,8 +192,8 @@ __ni_redhat_startmode(const char *mode)
const char * name;
ni_ifworker_control_t control;
} __ni_redhat_control_params[] = {
{ "manual", { NULL, NULL, TRUE, FALSE, 30 } },
{ "onboot", { "auto", NULL, TRUE, TRUE, 30 } },
{ "manual", { NULL, NULL, TRUE, FALSE, FALSE, 30 } },
{ "onboot", { "auto", NULL, TRUE, TRUE, FALSE, 30 } },
{ NULL }
};
struct __ni_control_params *p;
Expand Down
18 changes: 9 additions & 9 deletions client/compat-suse.c
Expand Up @@ -1042,18 +1042,18 @@ __ni_suse_startmode(const char *mode)
ni_ifworker_control_t control;
} __ni_suse_control_params[] = {
/* manual is the default in ifcfg */
{ "manual", { NULL, NULL, TRUE, FALSE, 30 } },
{ "manual", { NULL, NULL, TRUE, FALSE, FALSE, 30 } },

{ "auto", { "boot", NULL, FALSE, TRUE, 30 } },
{ "boot", { "boot", NULL, FALSE, TRUE, 30 } },
{ "onboot", { "boot", NULL, FALSE, TRUE, 30 } },
{ "on", { "boot", NULL, FALSE, TRUE, 30 } },
{ "auto", { "boot", NULL, FALSE, TRUE, FALSE, 30 } },
{ "boot", { "boot", NULL, FALSE, TRUE, FALSE, 30 } },
{ "onboot", { "boot", NULL, FALSE, TRUE, FALSE, 30 } },
{ "on", { "boot", NULL, FALSE, TRUE, FALSE, 30 } },

{ "hotplug", { "boot", NULL, FALSE, FALSE, 30 } },
{ "ifplugd", { "ignore", NULL, FALSE, FALSE, 30 } },
{ "hotplug", { "boot", NULL, FALSE, FALSE, FALSE, 30 } },
{ "ifplugd", { "ignore", NULL, FALSE, FALSE, FALSE, 30 } },

{ "nfsroot", { "boot", "localfs", TRUE, TRUE, NI_IFWORKER_INFINITE_TIMEOUT } },
{ "off", { "off", NULL, FALSE, FALSE, 0 } },
{ "nfsroot", { "boot", "localfs", TRUE, TRUE, TRUE, NI_IFWORKER_INFINITE_TIMEOUT } },
{ "off", { "off", NULL, FALSE, FALSE, FALSE, 0 } },

{ NULL }
};
Expand Down
8 changes: 8 additions & 0 deletions client/compat.c
Expand Up @@ -22,6 +22,7 @@
#include <netlink/netlink.h>
#include <sys/param.h>

#include "client/client_state.h"

/* Helper functions */
static const char * ni_sprint_uint(unsigned int value);
Expand Down Expand Up @@ -984,6 +985,13 @@ __ni_compat_generate_ifcfg(xml_node_t *ifnode, const ni_compat_netdev_t *compat)
if (control->link_required)
(void) xml_node_new("require-link", linkdet);
}

/* <client-state> node generation based on STARTMODE value parsed in control */
if (control->persistent) {
child = xml_node_create(ifnode, NI_CLIENT_STATE_XML_STATE_NODE);
xml_node_new_element(NI_CLIENT_STATE_XML_PERSISTENT_NODE, child,
ni_format_boolean(control->persistent));
}
}

switch (dev->link.type) {
Expand Down
141 changes: 103 additions & 38 deletions client/ifup.c
Expand Up @@ -63,10 +63,25 @@ ni_ifup_down_init(void)
return fsm;
}

static void
fill_state_string(ni_stringbuf_t *sb, const ni_uint_range_t *range)
{
unsigned int state;

if (!sb)
return;

for (state = (range ? range->min : NI_FSM_STATE_NONE);
state <= (range ? range->max : __NI_FSM_STATE_MAX - 1);
state++) {
ni_stringbuf_printf(sb, "%s ", ni_ifworker_state_name(state));
}
}

int
do_ifup(int argc, char **argv)
{
enum { OPT_HELP, OPT_IFCONFIG, OPT_IFPOLICY, OPT_CONTROL_MODE, OPT_STAGE, OPT_TIMEOUT, OPT_SKIP_ACTIVE, OPT_SKIP_ORIGIN, OPT_FORCE };
enum { OPT_HELP, OPT_IFCONFIG, OPT_IFPOLICY, OPT_CONTROL_MODE, OPT_STAGE, OPT_TIMEOUT, OPT_SKIP_ACTIVE, OPT_SKIP_ORIGIN, OPT_FORCE, OPT_PERSISTENT };
static struct option ifup_options[] = {
{ "help", no_argument, NULL, OPT_HELP },
{ "ifconfig", required_argument, NULL, OPT_IFCONFIG },
Expand All @@ -77,6 +92,7 @@ do_ifup(int argc, char **argv)
{ "skip-origin",required_argument, NULL, OPT_SKIP_ORIGIN },
{ "timeout", required_argument, NULL, OPT_TIMEOUT },
{ "force", no_argument, NULL, OPT_FORCE },
{ "persistent", no_argument, NULL, OPT_PERSISTENT },
{ NULL }
};
ni_uint_range_t state_range = { .min = NI_FSM_STATE_ADDRCONF_UP, .max = __NI_FSM_STATE_MAX };
Expand All @@ -87,6 +103,7 @@ do_ifup(int argc, char **argv)
const char *opt_skip_origin = NULL;
ni_bool_t opt_force = FALSE;
ni_bool_t opt_skip_active = FALSE;
ni_bool_t opt_persistent = FALSE;
unsigned int nmarked, i;
ni_fsm_t *fsm;
int c, status = 1;
Expand Down Expand Up @@ -135,6 +152,10 @@ do_ifup(int argc, char **argv)
opt_force = TRUE;
break;

case OPT_PERSISTENT:
opt_persistent = TRUE;
break;

default:
case OPT_HELP:
usage:
Expand Down Expand Up @@ -162,6 +183,8 @@ do_ifup(int argc, char **argv)
" Timeout after <nsec> seconds\n"
" --force\n"
" Force reconfiguring the interface without checking the config origin\n"
" --persistent\n"
" Set interface into persistent mode (no regular ifdown allowed)\n"
);
goto cleanup;
}
Expand Down Expand Up @@ -202,19 +225,24 @@ do_ifup(int argc, char **argv)
goto cleanup;
}

ni_fsm_set_client_state(fsm, opt_persistent);

nmarked = 0;
while (optind < argc) {
static ni_ifmatcher_t ifmatch;

memset(&ifmatch, 0, sizeof(ifmatch));
ifmatch.name = argv[optind++];
/* Allow ifup on all interfaces we have config for */
ifmatch.require_configured = FALSE;
ifmatch.allow_persistent = TRUE;
ifmatch.require_config = TRUE;
ifmatch.skip_active = opt_skip_active;
ifmatch.skip_origin = opt_skip_origin;

if (!strcmp(ifmatch.name, "boot")) {
ifmatch.name = "all";
ifmatch.mode = "boot";
ifmatch.require_config = TRUE;
} else {
ifmatch.mode = opt_control_mode;
ifmatch.boot_stage = opt_boot_stage;
Expand All @@ -241,30 +269,44 @@ do_ifup(int argc, char **argv)
int
do_ifdown(int argc, char **argv)
{
enum { OPT_HELP, OPT_DELETE, OPT_TIMEOUT };
enum { OPT_HELP, OPT_FORCE, OPT_TIMEOUT };
static struct option ifdown_options[] = {
{ "help", no_argument, NULL, OPT_HELP },
{ "delete", no_argument, NULL, OPT_DELETE },
{ "force", required_argument, NULL, OPT_FORCE },
{ "timeout", required_argument, NULL, OPT_TIMEOUT },
{ NULL }
};
static ni_ifmatcher_t ifmatch;
ni_uint_range_t target_range = { .min = NI_FSM_STATE_NONE, .max = NI_FSM_STATE_DEVICE_UP };
ni_uint_range_t target_range = { .min = NI_FSM_STATE_DEVICE_DOWN, .max = __NI_FSM_STATE_MAX - 2};
unsigned int force_state = NI_FSM_STATE_NONE;
unsigned int nmarked;
/* int opt_delete = 0; */
ni_stringbuf_t sb = NI_STRINGBUF_INIT_DYNAMIC;
ni_fsm_t *fsm;
int c, status = 1;

fsm = ni_ifup_down_init();

/* Allow ifdown only on non-persistent interfaces previously configured by ifup */
memset(&ifmatch, 0, sizeof(ifmatch));
ifmatch.require_configured = TRUE;
ifmatch.allow_persistent = FALSE;
ifmatch.require_config = FALSE;

optind = 1;
while ((c = getopt_long(argc, argv, "", ifdown_options, NULL)) != EOF) {
switch (c) {
case OPT_DELETE:
target_range.max = NI_FSM_STATE_DEVICE_DOWN;
/* opt_delete = 1; */
case OPT_FORCE:
if (!ni_ifworker_state_from_name(optarg, &force_state) ||
!ni_ifworker_state_in_range(&target_range, force_state)) {
ni_error("ifdown: wrong force option \"%s\"", optarg);
goto usage;
}
target_range.min = NI_FSM_STATE_NONE;
target_range.max = force_state;
/* Allow ifdown on persistent, unconfigured interfaces */
ifmatch.require_configured = FALSE;
ifmatch.allow_persistent = TRUE;
ifmatch.require_config = FALSE;
break;

case OPT_TIMEOUT:
Expand All @@ -281,17 +323,21 @@ do_ifdown(int argc, char **argv)
default:
case OPT_HELP:
usage:
fill_state_string(&sb, &target_range);
fprintf(stderr,
"wicked [options] ifdown [ifdown-options] all\n"
"wicked [options] ifdown [ifdown-options] <ifname> [options ...]\n"
"\nSupported ifdown-options:\n"
" --help\n"
" Show this help text.\n"
" --delete\n"
" Delete virtual interfaces\n"
" --force <state>\n"
" Force putting interface into the <state> state. Despite of persistent mode being set. Possible states:\n"
" %s\n"
" --timeout <nsec>\n"
" Timeout after <nsec> seconds\n"
" Timeout after <nsec> seconds\n",
sb.string
);
ni_stringbuf_destroy(&sb);
return status;
}
}
Expand All @@ -301,6 +347,12 @@ do_ifdown(int argc, char **argv)
goto usage;
}

/* If no force_state - use default target states for ifdown */
if (NI_FSM_STATE_NONE == force_state) {
target_range.min = NI_FSM_STATE_NONE;
target_range.max = NI_FSM_STATE_DEVICE_UP;
}

if (!ni_fsm_create_client(fsm))
return status;

Expand All @@ -325,45 +377,39 @@ do_ifdown(int argc, char **argv)
return status;
}

static void
fill_state_string(char *buf, size_t len)
{
int state = 0;
buf[0] = '\0';
do {
const char *str = ni_ifworker_state_name(state);
if (str)
snprintf(buf + strlen(buf), len - strlen(buf), "%s ", str);
} while (++state < __NI_FSM_STATE_MAX);
}

int
do_ifcheck(int argc, char **argv)
{
enum { OPT_HELP, OPT_QUIET, OPT_IFCONFIG, OPT_STATE, OPT_CHANGED };
enum { OPT_HELP, OPT_QUIET, OPT_IFCONFIG, OPT_STATE, OPT_CHANGED, OPT_PERSISTENT };
static struct option ifcheck_options[] = {
{ "help", no_argument, NULL, OPT_HELP },
{ "quiet", no_argument, NULL, OPT_QUIET },
{ "ifconfig", required_argument, NULL, OPT_IFCONFIG },
{ "state", required_argument, NULL, OPT_STATE },
{ "changed", no_argument, NULL, OPT_CHANGED },
{ "persistent", no_argument, NULL, OPT_PERSISTENT },
{ NULL }
};
static ni_ifmatcher_t ifmatch;
ni_string_array_t opt_ifconfig = NI_STRING_ARRAY_INIT;
/* unsigned int nmarked; */
ni_bool_t opt_check_changed = FALSE;
ni_bool_t opt_quiet = FALSE;
ni_bool_t opt_persistent = FALSE;
const char *opt_state = NULL;
char state_string[256];
ni_stringbuf_t sb = NI_STRINGBUF_INIT_DYNAMIC;
unsigned int i;
ni_fsm_t *fsm;
int c, status = 0;
int c, status = NI_RETURN_CODE_OK;

fsm = ni_ifup_down_init();
fsm->readonly = TRUE;

/* Allow ifcheck on persistent, unconfigured interfaces */
memset(&ifmatch, 0, sizeof(ifmatch));
ifmatch.require_configured = FALSE;
ifmatch.allow_persistent = TRUE;
ifmatch.require_config = FALSE;

optind = 1;
while ((c = getopt_long(argc, argv, "", ifcheck_options, NULL)) != EOF) {
Expand All @@ -386,10 +432,14 @@ do_ifcheck(int argc, char **argv)
opt_quiet = TRUE;
break;

case OPT_PERSISTENT:
opt_persistent = TRUE;
break;

default:
case OPT_HELP:
usage:
fill_state_string(state_string, sizeof(state_string));
fill_state_string(&sb, NULL);
fprintf(stderr,
"wicked [options] ifcheck [ifcheck-options] all\n"
"wicked [options] ifcheck [ifcheck-options] <ifname> ...\n"
Expand All @@ -404,9 +454,12 @@ do_ifcheck(int argc, char **argv)
" --changed\n"
" Verify that the interface(s) use the current configuration\n"
" --quiet\n"
" Do not print out errors, but just signal the result through exit status\n",
state_string
" Do not print out errors, but just signal the result through exit status\n"
" --persistent\n"
" Show whether interface is in persistent mode\n",
sb.string
);
ni_stringbuf_destroy(&sb);
goto cleanup;
}
}
Expand Down Expand Up @@ -435,7 +488,7 @@ do_ifcheck(int argc, char **argv)
ifmatch.name = ifname;
if (ni_fsm_get_matching_workers(fsm, &ifmatch, &marked) == 0) {
ni_error("%s: no matching interfaces", ifname);
status = 1;
status = NI_RETURN_CODE_NO_INTERFACE;
continue;
}

Expand All @@ -445,9 +498,11 @@ do_ifcheck(int argc, char **argv)
ni_device_clientinfo_t *client_info;

if ((dev = w->device) == NULL) {
if (!opt_quiet)
ni_error("%s: device %s does not exist", ifname, w->object_path);
status = 2;
if (!opt_quiet) {
ni_error("%s: device from %s does not exist",
strcmp(ifname, "all") ? ifname : w->name, w->config.origin);
}
status = NI_RETURN_CODE_NO_DEVICE;
continue;
}

Expand All @@ -459,7 +514,7 @@ do_ifcheck(int argc, char **argv)
ni_debug_wicked("%s: config file uuid is %s", w->name, ni_uuid_print(&w->config.uuid));
ni_debug_wicked("%s: system dev. uuid is %s", w->name,
client_info? ni_uuid_print(&client_info->config_uuid) : "NOT SET");
status = 3;
status = NI_RETURN_CODE_CHANGED_CONFIG;
continue;
}
}
Expand All @@ -470,14 +525,24 @@ do_ifcheck(int argc, char **argv)
ni_error("%s: device has state %s, expected %s", w->name,
client_info? client_info->state : "NONE",
opt_state);
status = 4;
status = NI_RETURN_CODE_NOT_IN_STATE;
continue;
}
}

if (opt_persistent) {
if (w->client_state.persistent) {
if (!opt_quiet)
ni_error("%s: device configured in persistent mode", w->name);
status = NI_RETURN_CODE_PERSISTENT_ON;
continue;
}
}

printf("%s: exists%s%s\n", w->name,
printf("%s: exists%s%s%s\n", w->name,
opt_check_changed? ", configuration unchanged" : "",
opt_state? ", interface state as expected" : "");
opt_state? ", interface state as expected" : "",
opt_persistent? ", persistent mode is not set" : "");
}
}

Expand Down

0 comments on commit ace458c

Please sign in to comment.