提交 fe787282 编写于 作者: L Laine Stump

virsh: new net-update command

This command uses the new virNetworkUpdate() API to modify an existing
network definition, and optionally have those modifications take
effect immediately without restarting the network.

An example usage:

  virsh net-update mynet add-last ip-dhcp-host \
   "<host mac='00:11:22:33:44:55' ip='192.168.122.45'/>" \
   --live --config

If you like, you can instead put the xml into a file, and call like
this:

  virsh net-update mynet add ip-dhcp-host /tmp/myxml.xml
   --live --config

virsh will autodetect whether the argument is itself an xml element,
or if it's a file, by looking at the first character - the first
character of an xml element is always "<", and the first character of
a file is almost always *not* "<" (in the rare case that it is, the
user could specify "./<filename...").

A --parent-index option is also available (to give the index within a
list of parent objects, e.g. the index of the parent <ip> element when
updating ip-dhcp-host elements), but is optional and at least for now
will probably be used rarely.

--live, --config, and --current options - if you specify --live, only
the live state of the network will be updated. If you also specify
--config, then the persistent configuration will also be updated;
these two commands can be given separately, or both together. If you
don't specify either (you can optionally specify "--current" for the
same effect), then the "current" config will be updated (i.e. if the
network is active, then only its live config is affected, but if the
network is inactive, only the persistent config is affected).
上级 cd4f01ea
......@@ -736,6 +736,160 @@ cmdNetworkUndefine(vshControl *ctl, const vshCmd *cmd)
return ret;
}
/*
* "net-update" command
*/
static const vshCmdInfo info_network_update[] = {
{"help", N_("update parts of an existing network's configuration")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_update[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
{"command", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("type of update (add-first, add-last (add), delete, or modify)")},
{"section", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("which section of network configuration to update")},
{"xml", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("name of file containing xml (or, if it starts with '<', the complete "
"xml element itself) to add/modify, or to be matched for search")},
{"parent-index", VSH_OT_INT, 0, N_("which parent object to search through")},
{"config", VSH_OT_BOOL, 0, N_("affect next boot")},
{"live", VSH_OT_BOOL, 0, N_("affect running domain")},
{"current", VSH_OT_BOOL, 0, N_("affect current domain")},
{NULL, 0, 0, NULL}
};
VIR_ENUM_DECL(virNetworkUpdateCommand)
VIR_ENUM_IMPL(virNetworkUpdateCommand, VIR_NETWORK_UPDATE_COMMAND_LAST,
"none", "modify", "delete", "add-last", "add-first");
VIR_ENUM_DECL(virNetworkSection)
VIR_ENUM_IMPL(virNetworkSection, VIR_NETWORK_SECTION_LAST,
"none", "bridge", "domain", "ip", "ip-dhcp-host",
"ip-dhcp-range", "forward", "forward-interface",
"forward-pf", "portgroup", "dns-host", "dns-txt",
"dns-srv");
static bool
cmdNetworkUpdate(vshControl *ctl, const vshCmd *cmd)
{
bool ret = false;
virNetworkPtr network;
const char *commandStr = NULL;
const char *sectionStr = NULL;
int command, section, parentIndex = -1;
const char *xml = NULL;
char *xmlFromFile = NULL;
bool current = vshCommandOptBool(cmd, "current");
bool config = vshCommandOptBool(cmd, "config");
bool live = vshCommandOptBool(cmd, "live");
unsigned int flags = 0;
const char *affected;
if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
goto cleanup;
if (vshCommandOptString(cmd, "command", &commandStr) < 0) {
vshError(ctl, "%s", _("missing or malformed command argument"));
goto cleanup;
}
if (STREQ(commandStr, "add")) {
/* "add" is a synonym for "add-last" */
command = VIR_NETWORK_UPDATE_COMMAND_ADD_LAST;
} else {
command = virNetworkUpdateCommandTypeFromString(commandStr);
if (command <= 0 || command >= VIR_NETWORK_UPDATE_COMMAND_LAST) {
vshError(ctl, _("unrecognized command name '%s'"), commandStr);
goto cleanup;
}
}
if (vshCommandOptString(cmd, "section", &sectionStr) < 0) {
vshError(ctl, "%s", _("missing or malformed section argument"));
goto cleanup;
}
section = virNetworkSectionTypeFromString(sectionStr);
if (section <= 0 || section >= VIR_NETWORK_SECTION_LAST) {
vshError(ctl, _("unrecognized section name '%s'"), sectionStr);
goto cleanup;
}
if (vshCommandOptInt(cmd, "parent-index", &parentIndex) < 0) {
vshError(ctl, "%s", _("malformed parent-index argument"));
goto cleanup;
}
/* The goal is to have a full xml element in the "xml"
* string. This is provided in the --xml option, either directly
* (detected by the first character being "<"), or indirectly by
* supplying a filename (first character isn't "<") that contains
* the desired xml.
*/
if (vshCommandOptString(cmd, "xml", &xml) < 0) {
vshError(ctl, "%s", _("malformed or missing xml argument"));
goto cleanup;
}
if (*xml != '<') {
/* contents of xmldata is actually the name of a file that
* contains the xml.
*/
if (virFileReadAll(xml, VSH_MAX_XML_FILE, &xmlFromFile) < 0)
goto cleanup;
/* NB: the original xml is just a const char * that points
* to a string owned by the vshCmd object, and will be freed
* by vshCommandFree, so it's safe to lose its pointer here.
*/
xml = xmlFromFile;
}
if (current) {
if (live || config) {
vshError(ctl, "%s", _("--current must be specified exclusively"));
return false;
}
flags |= VIR_NETWORK_UPDATE_AFFECT_CURRENT;
} else {
if (config)
flags |= VIR_NETWORK_UPDATE_AFFECT_CONFIG;
if (live)
flags |= VIR_NETWORK_UPDATE_AFFECT_LIVE;
}
if (virNetworkUpdate(network, command,
section, parentIndex, xml, flags) < 0) {
vshError(ctl, _("Failed to update network %s"),
virNetworkGetName(network));
goto cleanup;
}
if (config) {
if (live)
affected = _("persistent config and live state");
else
affected = _("persistent config");
} else if (live) {
affected = _("live state");
} else if (virNetworkIsActive(network)) {
affected = _("live state");
} else {
affected = _("persistent config");
}
vshPrint(ctl, _("Updated network %s %s"),
virNetworkGetName(network), affected);
ret = true;
cleanup:
vshReportError(ctl);
virNetworkFree(network);
VIR_FREE(xmlFromFile);
return ret;
}
/*
* "net-uuid" command
*/
......@@ -854,6 +1008,7 @@ const vshCmdDef networkCmds[] = {
{"net-start", cmdNetworkStart, opts_network_start, info_network_start, 0},
{"net-undefine", cmdNetworkUndefine, opts_network_undefine,
info_network_undefine, 0},
{"net-update", cmdNetworkUpdate, opts_network_update, info_network_update, 0},
{"net-uuid", cmdNetworkUuid, opts_network_uuid, info_network_uuid, 0},
{NULL, NULL, NULL, NULL, 0}
};
......@@ -2006,6 +2006,45 @@ Undefine the configuration for an inactive network.
Convert a network name to network UUID.
=item B<net-update> I<network> I<command> I<section> I<xml>
[I<--parent-index> I<index>] [[I<--live>] [I<--config>] | [I<--current>]]
Update the given section of an existing network definition, with the
changes optionally taking effect immediately, without needing to
destroy and re-start the network.
I<command> is one of "add-first", "add-last", "add" (a synonym for
add-last), "delete", or "modify".
I<section> is one of ""bridge", "domain", "ip", "ip-dhcp-host",
"ip-dhcp-range", "forward", "forward-interface", "forward-pf",
"portgroup", "dns-host", "dns-txt", or "dns-srv", each section being
named by a concatenation of the xml element hierarchy leading to the
element being changed. For example, "ip-dhcp-host" will change a
<host> element that is contained inside a <dhcp> element inside an
<ip> element of the network.
I<xml> is either the text of a complete xml element of the type being
changed (e.g. "<host mac="00:11:22:33:44:55' ip='1.2.3.4'/>", or the
name of a file that contains a complete xml element. Disambiguation is
done by looking at the first character of the provided text - if the
first character is "<", it is xml text, if the first character is not
"<", it is the name of a file that contains the xml text to be used.
The I<--parent-index> option is used to specify which of several
parent elements the requested element is in (0-based). For example, a
dhcp <host> element could be in any one of multiple <ip> elements in
the network; if a parent-index isn't provided, the "most appropriate"
<ip> element will be selected (usually the only one that already has a
<dhcp> element), but if I<--parent-index> is given, that particular
instance of <ip> will get the modification.
If I<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified, affect the current guest state.
Both I<--live> and I<--config> flags may be given, but I<--current> is
exclusive. Not specifying any flag is the same as specifying I<--current>.
=back
=head1 INTERFACE COMMANDS
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册