Reviewer: Jan Lindblad Review result: Ready Finally the NMDA datastores draft has reached WGLC, and I have been assigned as YD reviewer; quite an honor ;-) Because of the pretty fundamental importance of this document, I performed what I consider myself a pretty thorough review. Since this work has been going on for a very long time and with high intensity at times, I have not even tried to keep up to date with all the discussions. So in order not to resurrect all the beaten zombies that this spec has seen, I decided to let the document shepherd and principal author Martin Björklund review my review. The end result of which is that I withdraw every one of my comments and proclaim review result Ready. For full transparency (and to show that I wasn't lazy after all), I have enclosed my initial review findings below. Note that I now feel that they are either discussed enough already, addressed in a different document (e.g. YANG library), or misunderstandings/proposals on my part that do not necessarily merit further discussion or clarification. Finally I will add that no blackmail or bribery ;-) was involved in me reaching this conclusion; merely a good discussion. /jan Topic #1: Loss of operational stringency According to RFC 6020 tradition, config false data returned from <get> operations MUST adhere to the constraints declared in the YANG modules; max-elements, must statements, unique keys, etc. This is obviously a high standard to live up to for server implementors. With NMDA, the situation reverses so that <get> operations will return data from <operational> where no semantic guarantees apply. This moves the burden of managing flux and inconsistency from the servers to the clients. Now each client has to be able to deal with potentially duplicate keys, violated constraints and generally that any YANG model semantic guarantee is a mere recommendation. Personally I find this rather shocking. One of the core values in NETCONF/YANG has always been that it sides with the "operator" or "client" view of the world. Decades ago we had SNMP (Simple ...) -- which in practice meant simple to *implement*, not simple to use. NC/Y is supposed to be the other way around. Hard to implement, but easy to use. If we feel strict adherence to the YANG declaration is a bar too high for operational data, maybe we could find some middle ground? Just giving up and saying that anything anywhere may be violated anytime is to make it too easy for implementors and too hard for clients, IMHO. If I'm beating on a dead horse here, I apologize ;-) I just want to ensure that if this is what we want, it should be an informed decision. Topic #2: Actions live in <operational> NMDA says actions are always invoked in context of the <operational> data store. In many cases I agree this makes good sense. But there are a couple of catches here. The first catch relates to timing. As the server is not obliged to make an element committed in <intended> immediately available in <operational>, a client that creates a bit of configuration and is interested to execute an action on it will not know when to fire the action. Should it poll for the object creation? Keep retrying? I sense the creation of Heisenbugs and interop issues. The second catch relates to structure translation between <running> and <intended>. If the configuration committed to <running> by the client has no direct counterpart in <intended> and <operational>, there is nothing to invoke the action on. Say I used a templating feature in <running> to define a bit of configuration, and now I want to execute a check-sync action on that piece of config to see that the config has propagated properly. There is no context to invoke the action on in <operational>. Similarly, for actions that update <running> (e.g. config wizards), executing in <running> would make sense. Maybe an ability to specify the context datastore in the rpc would be enough to fix this. Or better perhaps, the target datastore should be formally declared by the action/rpc? Such a declaration would solve another issue that exists today. A client needs to parse English to know if an action changes <running>. Any configuration data cached by the client would need to be invalidated iff so. With a formal mechanism to declare which datastores are (not) affected, clients could be a lot more efficient. This is a real issue. Topic #3: Datastore specific deviations How would I express a deviation that applies to one datastore but not another? Say, for example, that I have a deviate not-implemented on an object in <running> but I support it in <operational>. Topic #4: NMDA compliance declaration How would a client know that a server works according to NMDA principles? I suppose the intent is that there is no need to know because things are "backwards compatible", and that for a given server the answer may vary depending on which data model we're talking about. But as discussed in topic #1, #2, #3 above (and more below), significant semantic differences are introduced by NMDA. As client implementor, I would want to know what to expect from a server. Topic #5: Origin of unset values When the operational view is constructed, the draft describes situations where the operational value may be taken in some cases from or:intended and in other from or:learned. While it would be valuable for clients to understand what the precedence rule is, this may be a bit too complex to declare formally, since it is quite possible that the mechanics of which value shows up isn't always simple and may depend on other leaf values. In the example with a DHCP learned address trumping an intended address, it could be that the DHCP server specifies only an IPv6 address. In which case the device policy might be to override the IPv4 address in intended with no value. In this situation, there is no way for the server to communicate why there is no IPv4 address (it was or:learned), since the origin attribute cannot live on a non-existent XML element. So the origin mechanism does not work well for optional elements. Topic #6: Datastore and origin identity trees Why are there two trees with identities, one for datastores and one with origins? Most values seems to be the same, with the origins being a superset of the datastores. By organizing them into a single tree with all the datastores as one branch of the origins tree, we could get something simpler. moduel ietf-origin { identity origin; identity unknown { base origin; } identity system { base origin; } identity learned { base origin; } identity default { base origin; } identity datastore { base origin; } identity conventional { base datastore; } identity running { base conventional; } identity candidate { base conventional; } identity startup { base conventional; } identity intended { base conventional; } identity dynamic { base datastore; } identity operational { base datastore; } /* * Type definitions */ typedef origin-ref { type identityref { base origin; } } typedef datastore-ref { type identityref { base datastore; } } Topic #7: Editorial Below are a few details about the wording: On pages 3 and 4, it is said that "These datastores share a common datastore schema" and """datastore schema: The combined set of schema nodes for all modules supported by a particular datastore, taking into consideration any deviations and enabled features for that datastore.""" If we have a device that support macros/templates/services in <running>, which expands into concrete configuration in <intended>, I don't suppose the macro/template/service instances would be part of <intended>? If so, I guess the schemas are not exactly the same? Maybe we can say that <intended> is a subset of the <running> schemas (plus all the config false data)? p15: Maybe we could point out that learned values etc MUST NOT update <running>/<intended> to make this entirely clear. p24: Juergen Schoenwaelder's funding is mentioned, but not his participation p27: what's <get-data> ? p28: ds-ephemeral and or-ephemeral are not great names. Will be referred to as ds:ds-ephemeral and or:or-ephemeral. Would prefer ds:ephemeral and or:ephemeral. /jan