[PATCH 1/3] ncftool: Allow a one shot, non-interactive command
by Cole Robinson
Similar to how virsh works, one shot commands can be invoked as:
ncftool <cmd> <options>
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/ncftool.c | 119 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 81 insertions(+), 38 deletions(-)
diff --git a/src/ncftool.c b/src/ncftool.c
index 9b589f5..28f97ca 100644
--- a/src/ncftool.c
+++ b/src/ncftool.c
@@ -56,7 +56,8 @@ enum command_result {
CMD_RES_OK,
CMD_RES_ERR,
CMD_RES_ENOMEM,
- CMD_RES_QUIT
+ CMD_RES_QUIT,
+ CMD_RES_UNKNOWN
};
struct command {
@@ -669,7 +670,7 @@ static void parse_opts(int argc, char **argv) {
};
int idx;
- while ((opt = getopt_long(argc, argv, "hr:", options, &idx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+hr:", options, &idx)) != -1) {
switch(opt) {
case 'h':
usage();
@@ -695,53 +696,73 @@ static void print_netcf_error(void) {
}
}
-static int main_loop(void) {
+static int run_command_line(const char *line, int *cmdstatus)
+{
struct command cmd;
- char *line;
+ char *dup_line;
int ret = 0;
MEMZERO(&cmd, 1);
+
+ dup_line = strdup(line);
+ if (dup_line == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ return -1;
+ }
+
+ if (parseline(&cmd, dup_line) == 0) {
+ *cmdstatus = cmd.def->handler(&cmd);
+ switch (*cmdstatus) {
+ case CMD_RES_OK:
+ ret = 0;
+ break;
+ case CMD_RES_ERR:
+ print_netcf_error();
+ ret = -1;
+ break;
+ case CMD_RES_ENOMEM:
+ fprintf(stderr, "error: allocation failed\n");
+ ret = -1;
+ break;
+ case CMD_RES_QUIT:
+ ret = 0;
+ break;
+ }
+ } else {
+ ret = -1;
+ *cmdstatus = CMD_RES_UNKNOWN;
+ }
+
+ free(dup_line);
+ cmd.def = NULL;
+ while (cmd.opt != NULL) {
+ struct command_opt *del = cmd.opt;
+ cmd.opt = del->next;
+ free(del);
+ }
+
+ return ret;
+}
+
+static int main_loop(void) {
+ char *line;
+ int ret;
+
while(1) {
- char *dup_line;
+ int cmdret;
+ int cmdstatus = 0;
line = readline("ncftool> ");
if (line == NULL) {
- printf("\n");
return ret;
}
- dup_line = strdup(line);
- if (dup_line == NULL) {
- fprintf(stderr, "Out of memory\n");
- return -1;
- }
+ cmdret = run_command_line(line, &cmdstatus);
+ if (ret == 0 && cmdstatus == CMD_RES_QUIT)
+ return ret;
- if (parseline(&cmd, dup_line) == 0) {
- int r;
- r = cmd.def->handler(&cmd);
- switch (r) {
- case CMD_RES_OK:
- break;
- case CMD_RES_ERR:
- print_netcf_error();
- ret = -1;
- break;
- case CMD_RES_ENOMEM:
- fprintf(stderr, "error: allocation failed\n");
- ret = -1;
- break;
- case CMD_RES_QUIT:
- return ret;
- }
- add_history(line);
- }
- free(dup_line);
- cmd.def = NULL;
- while (cmd.opt != NULL) {
- struct command_opt *del = cmd.opt;
- cmd.opt = del->next;
- free(del);
- }
+ add_history(line);
+ ret = cmdret;
}
}
@@ -760,7 +781,29 @@ int main(int argc, char **argv) {
}
readline_init();
if (optind < argc) {
- fprintf(stderr, "warning: ignoring additional arguments\n");
+ /* Run a single command */
+ int i, ignore_status;
+ int cmdsize = 0;
+ char *cmd;
+
+ for (i = optind; i < argc; ++i) {
+ cmdsize += strlen(argv[i]) + 1;
+ }
+
+ cmd = malloc(cmdsize + 1);
+ if (!cmd) {
+ fprintf(stderr, "Out of memory\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = optind; i < argc; i++) {
+ strncat(cmd, argv[i], cmdsize);
+ cmdsize -= strlen(argv[i]);
+ strncat(cmd, " ", cmdsize--);
+ }
+
+ r = run_command_line(cmd, &ignore_status);
+ free(cmd);
} else {
r = main_loop();
}
--
1.6.5.2
14 years, 1 month
[PATCH 3/3] ncftool: Add a --debug option
by Cole Robinson
This makes ncftool set the (undocumented) NETCF_DEBUG variable
for us.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/ncftool.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/ncftool.c b/src/ncftool.c
index 66c590c..96276e9 100644
--- a/src/ncftool.c
+++ b/src/ncftool.c
@@ -663,6 +663,8 @@ static void usage(void) {
fprintf(stderr, "\nOptions:\n\n");
fprintf(stderr,
" -r, --root ROOT use ROOT as the root of the filesystem\n\n");
+ fprintf(stderr,
+ " -d, --debug Show debugging output\n\n");
print_all_cmds(stderr);
exit(EXIT_FAILURE);
@@ -673,12 +675,16 @@ static void parse_opts(int argc, char **argv) {
struct option options[] = {
{ "help", 0, 0, 'h' },
{ "root", 1, 0, 'r' },
+ { "debug", 0, 0, 'd' },
{ 0, 0, 0, 0}
};
int idx;
- while ((opt = getopt_long(argc, argv, "+hr:", options, &idx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+dhr:", options, &idx)) != -1) {
switch(opt) {
+ case 'd':
+ setenv("NETCF_DEBUG", "1", 1);
+ break;
case 'h':
usage();
break;
--
1.6.5.2
14 years, 1 month
Live interface config incomplete for empty bridge
by Cole Robinson
Hi,
Dumping the live config of an empty bridge seems a bit off:
$ sudo ncftool
ncftool> list
eth0
foobar
lo
ncftool> dumpxml foobar
<?xml version="1.0"?>
<interface type="bridge" name="foobar">
<start mode="onboot"/>
<bridge/>
</interface>
ncftool> dumpxml --live foobar
<?xml version="1.0"?>
<interface name="foobar" type="bridge"/>
The lack of a <bridge> section upsets libvirt here:
$ sudo virsh iface-dumpxml foobar
error: XML description for bridge interface misses the bridge element is not
well formed or invalid
Also, I think it would be nice if --live started with the inactive interface
config and added/updated info from there. For example, the <start> block is
only listed for the inactive config: this means an app would need query both
the inactive and live config to get a complete listing of the interface's
settings. Seems like this could easily be done at the netcf level, and is more
or less how libvirt works for active vs. inactive domain configs (obviously
netcf isn't tied to libvirt, just trying to point out some precedent).
Thanks,
Cole
14 years, 2 months
[PATCH 2/3] ncftool: Have 'ncftool --help' print command list
by Cole Robinson
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/ncftool.c | 25 ++++++++++++++++---------
1 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/src/ncftool.c b/src/ncftool.c
index 28f97ca..66c590c 100644
--- a/src/ncftool.c
+++ b/src/ncftool.c
@@ -412,15 +412,21 @@ static const struct command_def cmd_undefine_def = {
.help = "remove the configuration of an interface"
};
+static void print_all_cmds(FILE *stream) {
+ fprintf(stream, "Commands:\n\n");
+ for (int i=0; commands[i]->name != NULL; i++) {
+ const struct command_def *def = commands[i];
+ fprintf(stream, " %-10s - %s\n", def->name, def->synopsis);
+ }
+
+ fprintf(stream,
+ "\nType 'help <command>' for more information on a command\n\n");
+}
+
static int cmd_help(const struct command *cmd) {
const char *name = param_value(cmd, "command");
if (name == NULL) {
- printf("Commands:\n\n");
- for (int i=0; commands[i]->name != NULL; i++) {
- const struct command_def *def = commands[i];
- printf(" %-10s - %s\n", def->name, def->synopsis);
- }
- printf("\nType 'help <command>' for more information on a command\n\n");
+ print_all_cmds(stdout);
} else {
const struct command_def *def = lookup_cmd_def(name);
const struct command_opt_def *odef = NULL;
@@ -653,10 +659,11 @@ static void readline_init(void) {
__attribute__((noreturn))
static void usage(void) {
fprintf(stderr, "Usage: %s [OPTIONS]\n", progname);
- fprintf(stderr, "Interactive shell for netcf\n\n");
- fprintf(stderr, "Type 'help' at the prompt to get a list of commands\n");
+ fprintf(stderr, "Interactive shell for netcf\n");
fprintf(stderr, "\nOptions:\n\n");
- fprintf(stderr, " -r, --root ROOT use ROOT as the root of the filesystem\n");
+ fprintf(stderr,
+ " -r, --root ROOT use ROOT as the root of the filesystem\n\n");
+ print_all_cmds(stderr);
exit(EXIT_FAILURE);
}
--
1.6.5.2
14 years, 2 months