[netmod] Yangdoctors early review of draft-ietf-netmod-revised-datastores-09

Jan Lindblad <janl@tail-f.com> Tue, 09 January 2018 15:43 UTC

Return-Path: <janl@tail-f.com>
X-Original-To: netmod@ietf.org
Delivered-To: netmod@ietfa.amsl.com
Received: from ietfa.amsl.com (localhost [IPv6:::1]) by ietfa.amsl.com (Postfix) with ESMTP id C820B12D879; Tue, 9 Jan 2018 07:43:31 -0800 (PST)
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
From: Jan Lindblad <janl@tail-f.com>
To: <yang-doctors@ietf.org>
Cc: netmod@ietf.org, ietf@ietf.org, draft-ietf-netmod-revised-datastores.all@ietf.org
X-Test-IDTracker: no
X-IETF-IDTracker: 6.68.3
Auto-Submitted: auto-generated
Precedence: bulk
Message-ID: <151551261178.1806.130953175040927039@ietfa.amsl.com>
Date: Tue, 09 Jan 2018 07:43:31 -0800
Archived-At: <https://mailarchive.ietf.org/arch/msg/netmod/21R5WJrjnw6LcOQSbaIsAwQEyCk>
Subject: [netmod] Yangdoctors early review of draft-ietf-netmod-revised-datastores-09
X-BeenThere: netmod@ietf.org
X-Mailman-Version: 2.1.22
List-Id: NETMOD WG list <netmod.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netmod>, <mailto:netmod-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netmod/>
List-Post: <mailto:netmod@ietf.org>
List-Help: <mailto:netmod-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netmod>, <mailto:netmod-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 09 Jan 2018 15:43:32 -0000

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