On 09/17/2012 06:42 PM, Eric Blake wrote: > On 09/17/2012 03:48 AM, Laine Stump wrote: >> This patch adds a new public API virNetworkUpdate that will permit >> updating an existing network configuration without requiring that the >> network be destroyed/restarted for the changes to take effect. >> --- >> include/libvirt/libvirt.h.in | 50 +++++++++++++++++++++++++++++++++++++ >> src/driver.h | 7 ++++++ >> src/libvirt.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ >> src/libvirt_public.syms | 1 + >> 4 files changed, 117 insertions(+) > This one is the clincher - either we take this API as written for the > 0.10.2 freeze tomorrow (guaranteeing it will be in the .so, even if the > implementation is still baking), or we wait another release cycle to > come up with something better (and given the churn we have already been > through, I don't know that we'll have any breakthroughs for a nicer > API). Dan's already given a weak ACK to the API, and I will also throw > in my assent - this is better than any of the other 3 earlier designs we > tried (reusing the define XML to redefine, but no way to limit how much > was redefined; dealing with an explosion in new APIs; or exposing XPath > selections to the user); it is at least extensible, and your cover > letter demonstrated several valid use cases where this was sufficient > for the task. > > You may want to wait on DV's opinion before pushing (or DV may want to > push before cutting the rc1 release if he's online when you aren't - > that would also serve as consent). Also, although I'm agreeing to the > API, I have some review comments that might warrant a v2. > > As for the rest of the series, I'm okay if you wait for the review of > all of the patches as a unit before pushing any implementation, even if > that means missing the rc1 freeze. Once the API is in place, we can > then treat the rest of the series as a bug fix to an incomplete API as > justification for including it in rc2 if we miss rc1. Of course, the > sooner it is in, the more testing we can give it. Not to mention I > already noticed you posted a v2 on patch 6/10, so like me, you are in > the same boat of trying to get implementation to match the interface. > >> +++ b/include/libvirt/libvirt.h.in >> @@ -2328,6 +2328,56 @@ virNetworkPtr virNetworkDefineXML (virConnectPtr conn, >> int virNetworkUndefine (virNetworkPtr network); >> >> /* >> + * virNetworkUpdateSection: >> + * >> + * describes which section of a <network> definition the provided >> + * xml should be applied to. >> + * >> + */ >> +typedef enum { >> + VIR_NETWORK_SECTION_BRIDGE = 0, > I'm fine with this as-is, but maybe we want to start at 1, to ensure > that the user is always passing in a section number and not blindly > passing 0 without realizing how to use the API? I like that idea! I'll be posting a V2 in a bit, and that will be one of the changes. > >> +/* >> + * virNetworkUpdateFlags: >> + * >> + * Used to specify what type of operation to perform, and whether to >> + * affect live network, persistent config, or both. >> + */ >> +typedef enum { >> + VIR_NETWORK_UPDATE_AFFECT_CURRENT = 0, >> + VIR_NETWORK_UPDATE_AFFECT_LIVE = 1 << 0, >> + VIR_NETWORK_UPDATE_AFFECT_CONFIG = 1 << 1, >> + VIR_NETWORK_UPDATE_EXISTING = 1 << 2, >> + VIR_NETWORK_UPDATE_DELETE = 1 << 3, >> + VIR_NETWORK_UPDATE_ADD_LAST = 1 << 4, >> + VIR_NETWORK_UPDATE_ADD_FIRST = 1 << 5, > Am I correct that EXISTING, DELETE, ADD_LAST, and ADD_FIRST are mutually > exclusive, and that exactly one has to be provided? Yes. >> +++ b/src/libvirt.c >> @@ -10407,6 +10407,65 @@ error: >> } >> >> /** >> + * virNetworkUpdate: >> + * @network: pointer to a defined network >> + * @section: which section of the network to update >> + * (virNetworkUpdateSection) >> + * @parentIndex: which parent element, if there are multiples parents > s/multiples/multiple/ > >> + * of the same type (e.g. which <ip> element when modifying >> + * a <dhcp>/<host> element), or "-1" for "don't care" or >> + * "automatically find appropriate one". >> + * @xml: the XML description for the network, preferably in UTF-8 >> + * @flags: bitwise OR of virNetworkUpdateFlags. >> + * >> + * Update the definition of an existing network, either its live >> + * running state, its persistent configuration, or both. >> + * >> + * Returns 0 in case of success, -1 in case of error > Where do you document the four modes (existing, delete, add_first, > add_last)? I'll try to put in better documentation in the next round. > Since the modes are mutually exclusive, is it worth passing > them in as a separate argument (with values 0, 1, 2, 3), instead of as > bits within flags (with values 4, 8, 16, 32)? Actually, yes. It ended up the way it is just because the arguments grew organically from my virNetworkDefineFlags idea. But when you compare what's there now with an API that has a separate "command" arg, this version is no more compact in the source, and one more unsigned int arg is no big deal. So, before I move on to the virsh command (I finished the first backend section implementation a little while ago), I'll do another pass through git rebase -i, adding in the extra arg. > But adding a new argument > would cause you more rebase work, so I can live with them as flags for > now. Another possibility might be passing them as 2-bit combinations > within the flags parameter (that will automatically enforce the mutual > exclusion as well as necessarily supplying exactly one of the four > choices), by encoding: > > VIR_NETWORK_UPDATE_ACTION_MASK = 0xc, > VIR_NETWORK_UPDATE_EXISTING = 0x0, > VIR_NETWORK_UPDATE_DELETE = 0x4, > VIR_NETWORK_UPDATE_ADD_LAST = 0x8, > VIR_NETWORK_UPDATE_ADD_FIRST = 0xc, > >> + */ >> +int >> +virNetworkUpdate(virNetworkPtr network, >> + unsigned int section, /* virNetworkUpdateSection */ >> + int parentIndex, >> + const char *xml, >> + unsigned int flags) >> +{ >> + virConnectPtr conn; >> + VIR_DEBUG("network=%p, section=%d, parentIndex=%d, xml=%s, flags=0x%x", >> + network, section, parentIndex, xml, flags); >> + >> + virResetLastError(); >> + >> + if (!VIR_IS_CONNECTED_NETWORK(network)) { >> + virLibNetworkError(VIR_ERR_INVALID_NETWORK, __FUNCTION__); >> + virDispatchError(NULL); >> + return -1; >> + } >> + conn = network->conn; >> + if (conn->flags & VIR_CONNECT_RO) { >> + virLibNetworkError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); >> + goto error; >> + } >> + >> + virCheckNonNullArgGoto(xml, error); > If you _don't_ encode the four modes as a separate argument or as a > two-bit field within flags, then it might be worth enforcing here at the > API entry point that exactly one of the four flags is always specified, > as in: > > if ((!!(flags & _EXISTING) + > !!(flags & _DELETE) + > !!(flags & _ADD_FIRST) + > !!(flags & _ADD_LAST)) > != 1) > raise error; > > But this is bike-shedding - whether or not we error out on invalid mode > combinations can be viewed as implementation, not interface, and > therefore something we could add later if we want to take this commit > as-is for the interface. > >> +++ b/src/libvirt_public.syms >> @@ -565,6 +565,7 @@ LIBVIRT_0.10.2 { >> virNodeGetMemoryParameters; >> virNodeSetMemoryParameters; >> virStoragePoolListAllVolumes; >> + virNetworkUpdate; > You probably guessed I would catch this, but I'll say it anyways :) > Sorting :) > Actually, when I added that line, I was thinking more about the RPC numbers and how the latest one is always last, for some reason. I guess that's what happens when you're running on fumes... -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list