Subject: [netmod] Y45 wrap up

From: Martin Bjorklund <[email-masked]>
Date: Thu, 16 Apr 2015 21:38:15 +0200 (CEST)

Hi,

After the latest lengthy discussion on the list, I have updated the
issues list
(https://svn.tools.ietf.org/svn/wg/netmod/yang-1.1/issues.html) with
my proposal for the solution to the problem (Y45-03), and Lada's
refined version (Y45-04).

I think it would be useful if people could indicate their preferred
solution to this problem.

My preference is Y45-04.  It is flexible for module writers, and
straightforward to understand for module readers.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 17 Apr 2015 10:00:12 +0200

> On 16 Apr 2015, at 21:38, Martin Bjorklund <[email-masked]> wrote:
> 
> Hi,
> 

Same here.

Lada

> 
> 
> /martin
> 
> _______________________________________________
> netmod mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/netmod

--
Ladislav Lhotka, CZ.NIC Labs
PGP Key ID: E74E8C0C

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 17 Apr 2015 10:15:57 +0200

> straightforward to understand for module readers.

As a technical contributor, I support Martin's proposal to adopt
Y45-04. It seems to handle all the cases and it is consistent with the
old YANG design philosophy that readers are first priority, model
writers second priority, and tool writers third priority.

/js

-- 
Juergen Schoenwaelder           Jacobs University Bremen gGmbH
Phone: +49 421 200 3587         Campus Ring 1 | 28759 Bremen | Germany
Fax:   +49 421 200 3103         <http://www.jacobs-university.de/>

---

From: Andy Bierman <[email-masked]>
Date: Fri, 17 Apr 2015 05:38:15 -0700

Hi,

I don't see how Y45 solves any problems

module foo {
    import bar { prefix B; }
    import bar { prefix b; }
    import bar { prefix bar; }

    ...
}

This seems allowed -- what problem is solved by allowing the same
module to be used with different prefixes?

What if some have import-by-revision and others don't?
What revision is used for the imports without revision?
Don't they drift, just as before?

module foo {
    import bar { prefix B; revision-data 2015-01-01; }
    import bar { prefix b; revision-data 2015-02-01; }
    import bar { prefix bar; revision-data 2015-03-01; }

   augment /B:X { ... }

   augment /b:X { ... }

   augment /bar:X { ... }
    ...
}

How is the augment-multiple revisions problem solved?

IMO YANG 1.1 is getting way too complicated for humans to grok by
inspection.  This leads to over-reliance on tools to show the "real"
YANG module. The probability that the intended model and the
real model diverge is significantly increased.

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 17 Apr 2015 14:59:40 +0200

> On 17 Apr 2015, at 14:38, Andy Bierman <[email-masked]> wrote:
> 
> Hi,
> 

Multiple imports make sense only if different revisions are imported, and this gives the designer of the importing module the option to use stuff from different revisions of the imported module.

I’d suggest that one module can be imported once without revision and then every revision can be imported at most once. 

> What revision is used for the imports without revision?

For groupings and typedefs this is determined by the advertisement of the imported module with "conformance=no-protocol-accessible-nodes", see Y45-03. 

> How is the augment-multiple revisions problem solved?

For augments, the revisions specified for imports is completely ignored, what counts is the revision that the server implements.

> real model diverge is significantly increased.

I don’t think so. In most cases, one import per module should be all that’s needed, and it is up to the designer of the importing module whether the revision of a grouping or typedef will be fixed, or whether it is left to implementations which revision is chosen.

And a big benefit of this solution is that modules won’t be cluttered with different versions of the same typedef or grouping bearing different names.

Lada

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 17 Apr 2015 15:01:32 +0200 (CEST)

> I don't see how Y45 solves any problems

I assume you mean Y45-03 and Y45-04.

> This seems allowed

This can easily be made illegal.  It is actually not obvious that this
is illegal in YANG 1.0.

> -- what problem is solved by allowing the same

Importing the same module and same revision with different prefixes
does not seem very useful.  Ok to make illegal.

> What if some have import-by-revision and others don't?

I assume you mean a situation like:

   import bar {
     prefix b;
   }
   import bar {
     revision-date 2004-04-01;
     prefix b1;
   }

> Don't they drift, just as before?

When the prefix "b" is used, it works just as if the second import
wasn't there.   The import by revision doesn't affect the other
import.

To answer your question, this works just like today - the server
decides which version of bar to implement.

>From Y45-03:

    If a server implements a module A that imports B, and A augments B
    or has a leafref to a node in B, the server MUST implement *some
    version* of module B that has the nodes A references.  This is
    regardless of A imports B by revision or not.

> inspection.

I disagree.  Even in YANG 1.0 you can have different modules importing
a common module by different revisions.  In YANG 1.0 it is not clear
what this means.  With Y45-04 this is clarified.

I think it is failry obvious which types are used in:

    import ietf-inet-types {
      revision-date 2013-07-17;
      prefix inet;
    }
    import ietf-inet-types {
      revision-date 2010-09-24;
      prefix inet6021;
    }
    leaf foo {
      type inet:ip-address-no-zone;
    }
    leaf bar {
      type inet6021:ip-address;
    }

/martin

> This leads to over-reliance on tools to show the "real"

---

From: Andy Bierman <[email-masked]>
Date: Fri, 17 Apr 2015 07:01:34 -0700

> This can easily be made illegal.  It is actually not obvious that this

OK

>      revision-date 2004-04-01;

Yes -- I do not understand the edits for the YANG guidelines
for when to use an import with revision vs. without revision.

> wasn't there.   The import by revision doesn't affect the other

I did not realize Y45-4 combined Y45-03.
I missed the words "As Y45-03..."

> what this means.  With Y45-04 this is clarified.

IMO the rules for Y45-03 are not obvious and
readers will not intuitively guess all these rules.
That's what makes it complicated.

>       type inet6021:ip-address;

I agree Y45-04 syntax is better than the inline uses@date.
That was scary.

I am not as worried about abuse and confusion for
the IETF modules written by YANG experts. We can write
usage guidelines, and IETF modules change very slowly over time.

I am more concerned about the vendor modules that quickly get
really complicated, or create unintended results in the validation
or code generation.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 17 Apr 2015 16:28:14 +0200 (CEST)

> for when to use an import with revision vs. without revision.

I would say that for IETF models, we should be very conservative when
changing a typedef or grouping.  An exception is typedefs like
iana-physical-class, which is designed to be extended (in a controlled
fashion).  Taken together this means that IETF modules should in most
cases use import without revision.

> That's what makes it complicated.

I think the vast majority of modules will look like in YANG 1.0 - they
will have a single import of any particular module, mostly w/o
revision.  The difference is that with Y45-04 there are clear rules
that people can read if needed.  YANG 1.0 is more confusing, since
there are no clear rules.

It might be confusing if a imports b@2004-04-01, and a server
advertises a and b@2015-04-01.  One might question if that is valid or
not (it is valid).  But again, we have the same situation in YANG 1.0.

> really complicated, or create unintended results in the validation

The worst they can do is start to use import-by revison of different
revisions of the same module.  But this just means that they
cherry pick typedefs or groupings from specific revisions.  It is at
least clear what this means.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 17 Apr 2015 16:44:27 +0200

> On 17 Apr 2015, at 16:28, Martin Bjorklund <[email-masked]> wrote:
> 

It depends, in some cases it might be preferable to fix the revision because then the module author can guarantee that things won’t break.   

> not (it is valid).  But again, we have the same situation in YANG 1.0.

It could be valid if b both defines types/groupings and also has target(s) for augments.

Lada

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 17 Apr 2015 18:37:23 +0200

> least clear what this means.

I think this is a big improvement. While cherry picking will likely
not be needed when modules are well designed and maintained, I am
pretty sure it will be necessary to handle cases where this is not the
case (e.g., a maintainer did not forsee things correctly) or adoption
of a new version is something that is implemented gradually in a
couple of firmware releases. Being able to clearly say which grouping
or typedef is used where is a big win. Previous proposals assumed that
everything can be upgraded always in one go (in my view unrealistic)
or that definitions are simply copied and duplicated and then start a
life of their own (in my view to be avoided).

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 22 Apr 2015 15:52:23 +0200 (CEST)

Hi,

Does any one else have any input to this thread?  So far, we have
three people in favor of Y45-04.  Andy, what is your preferred
solution?

/martin

---

From: Andy Bierman <[email-masked]>
Date: Wed, 22 Apr 2015 08:58:43 -0700

> three people in favor of Y45-04.  Andy, what is your preferred

I still prefer Y45-02.

The arguments that the complexity in Y45-03+04 won't get used very often
apply equally to the duplicated typedefs and groupings in Y45-02,
so they mean nothing.  One has to assume that the full complexity
allowed by the solution will be used.

The really scary part is that a server just picks *some* revision to
implement, and other modules can cherry-pick from revisions released
after the supported one.  YANG constraints and update rules
do not actually support this "feature". They assume that if statement A
is added to revision Y, that the server will have to implement revision Y
in order to use statement A.

Now when designers add new statements, they will need to take into
consideration how they will behave if mixed with every possible
revision of every
cross-referenced statement.

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 22 Apr 2015 18:18:46 +0200

> On 22 Apr 2015, at 17:58, Andy Bierman <[email-masked]> wrote:
> 

It is different: updates to typedefs&groupings may be used relatively often, what I think will be rarely needed are different revisions of a module in the same importing module. Y45-02 would clutter modules even if almost everybody is fine with the most recent revisions. 

> cross-referenced statement.

They can use import by revision.

Lada

---

From: Andy Bierman <[email-masked]>
Date: Wed, 22 Apr 2015 10:16:42 -0700

> It is different: updates to typedefs&groupings may be used relatively often, what I think will be rarely needed are different revisions of a module in the same importing module. Y45-02 would clutte…

This is complete speculation on your part.
There is no evidence at all of typedefs and groupings
expanding from RFC to RFC.  IANA maintained modules
do not count.  I-D to I-D changes do not count.

> They can use import by revision.

Or they can choose not to use it.
We assume everybody will just know
when to choose one instead of the other.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 22 Apr 2015 20:13:56 +0200

> in order to use statement A.

We are primarily talking about typedefs and groupings and as a matter
of fact, you implement them in the module that is importing them. I
generally do not implement ietf-inet-types, modules that implement
something imported from ietf-inet-types implement stuff. Y45-04 makes
it clear what a module that imported from ietf-inet-types implements
and it allows gradual updates (instead of forcing everything to import
from a single revision of ietf-inet-types). The alternative, Y45-02,
requires that any semantic changes to typedefs or groupings requires
to define a new typedef/grouping with a new name. In particular, you
can't add an enum to an enumeration anymore. This breaks for example
RFC 6643 (since SMIv2 do allow to add enums).
 
/js

---

From: Andy Bierman <[email-masked]>
Date: Wed, 22 Apr 2015 11:20:01 -0700

Hi,

I am curious how the solution proposal deals with augments
for nodes that don't exist yet:

module base {
   ...
   revision 2014-01-01;

   leaf foo { type string; }

}

module base {
   ...
   revision 2015-01-01;

   typedef XXX { type int32; }

   leaf foo { type string; }

   container bar;

}

module aug1 {
  ...
  import base { prefix b; revision-date 2015-01-01; }
  revision 2015-03-03;

  leaf Y {
    must ../b:bar/aug1:baz;
    type b:XXX;
 }

 augment /b:bar {
    leaf baz { type int32; }
 }
}

Let's say the server implements base@2014-01-01,
and also implements aug1@2015-03-03?
This module augments container /bar, which does not exist in
the version supported by the server.  The designer of "aug1"
clearly intends to use base@2015-01-01 (hence import-by-revision).

Since the server picked the old version of 'base', the augment /b:bar
is invalid and the must-stmt for /Y will always be false.
Cherry-picking the XXX typedef does not really help.
That is allowed but the /Y leaf is still broken.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 22 Apr 2015 20:52:08 +0200 (CEST)

> and also implements aug1@2015-03-03?

This isn't allowed, since the augment implies a run-time dependency -
the server MUST implement a version of "base" where the node "/bar"
exists.

/martin

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 22 Apr 2015 20:55:00 +0200 (CEST)

> >>> three people in favor of Y45-04.  Andy, what is your preferred

Y45-02 is the biggest change compared with YANG 1.0.

> > It is different: updates to typedefs&groupings may be used
> relatively often, what I think will be rarely needed are different
> revisions of a module in the same importing module. Y45-02 would
> clutter modules even if almost everybody is fine with the most
> recent revisions.

+1

> do not count.

Why wouldn't IANA maintained modules count?  Are you proposing to have
different upgrade rules for modules maintained by IANA?

/martin

---

From: Andy Bierman <[email-masked]>
Date: Wed, 22 Apr 2015 11:58:27 -0700

> the server MUST implement a version of "base" where the node "/bar"

Where does it say this is not allowed?
So the server cannot just pick a revision of "base".
It must be aware of all the other modules that use "base"
and make sure all modules work together?

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 22 Apr 2015 21:05:04 +0200 (CEST)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The whole idea is to decouple the revision-date used in the import in
order to fix the typedef from the version needed for augment.

> and make sure all modules work together?

Right.  This is not different from how it works in YANG 1.0.

/martin

---

From: Andy Bierman <[email-masked]>
Date: Wed, 22 Apr 2015 16:06:12 -0700

....
>     version* of module B that has the nodes A references.  This is

This is the part that will really confuse users.
For augment-stmts, the revision-date is ignored
in import-by-revision.

IMO this will not work well because the designer will write
a module expecting the augmented module to be the
one specified by import-by-revision.

If 2 or more modules augment different versions of
the /bar container over time at least 1 of them will
be applied to the wrong version of the augmented module.
This will cause unpredictable results because YANG
statements can interact in complex ways (e.g., must/when).

> Right.  This is not different from how it works in YANG 1.0.

IMO importing multiple revisions at once and picking typedefs
and groupings from revisions ahead of the supported one
makes this problem much worse.

Andy

---

From: Andy Bierman <[email-masked]>
Date: Wed, 22 Apr 2015 16:25:06 -0700

Hi,

What is the use-case for allowing "some version" vs.
the "most recent" as the supported version, from the
set of versions in use by a given server.

I understand the need for existing modules to freeze their imports
to prevent typedef and grouping drift.  These modules can use
import-by-revision, and keep using older typedefs/groupings,
even as the exporter module is updated.

I don't think a vendor should be allowed to pick some statements
from a newer version, and not implement that version of the
module (i.e., all base module protocol-accessible objects).

When vendors or SDOs write YANG modules with import-by-revision,
these modules will be designed to integrate with the expected
version.   Results with vendor-selected back-revs will not be predictable.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 23 Apr 2015 08:24:20 +0200 (CEST)

> set of versions in use by a given server.

Just to make sure we mean the same thing, here's an example:

  a@2000-01-02 imports by-revision b@2000-01-02
    and uses a typedef from b@2000-01-02

You're asking about a server that implements and advertises:

A:

  a@2000-01-02
  b@2000-01-01   <-- NOTE: previous version of b

A server that implements and advertises:

B:

  a@2000-01-02
  b@2000-01-02

or maybe even

C:

  a@2000-01-02
  b@2000-01-03

are OK.

If it turns out that A is problematic, it is fine with me to make it
illegal.  (but currently I don't see how it would be problematic)

There might be one use case for A.  Suppose b is something
like ietf-interfaces and it gets widely implemented and deployed.  In
a few years from now we update that module, and add a typedef.  This
typedef is then used by some other module "a".  Assume that an
implementation that has the old version of ietf-interfaces wants to
add support for "a".  It is now forced to either implement the new
ietf-interfaces, or not implement "a".

This situation can be avoided with careful design of the modules; for
example, we can always put typedefs like this in separate modules
(just like was done with -TCs).  However, with Y45-04, such
conventions with separate modules are not needed.

> version.   Results with vendor-selected back-revs will not be predictable.

Do you have an example that shows how this can be problematic?

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 23 Apr 2015 09:01:00 +0200

> For augment-stmts, the revision-date is ignored

This is because the function of import is overloaded - augments really
have nothing in common with using groupings and typedefs from another
module.

In hindsight, it would probably have been better to decouple augments
from imports altogether by not using prefixes in schema node
identifiers. For example,

augment "/ietf-interfaces:interfaces/interface" {
   ...
}

would work just fine.

> one specified by import-by-revision.

Well, if the server implements another revision, it must be the revision
that gets augmented. I don't see any other option.

Lada

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 23 Apr 2015 09:34:29 +0200

> For augment-stmts, the revision-date is ignored

Not sure what 'ignored' means here. At module compile time, if a
module refers to /b:bar than this /b:bar must resolve to something
defined in the revision that is used by the compiler (and import by
revision nails this down to an exact version).

> one specified by import-by-revision.

Likely, but it can also be a newer revision of the module that you
implement, no?

> statements can interact in complex ways (e.g., must/when).

Sure, you can create something not implementable with must/when
statements - you do not even need imports for that and this is
part of YANG 1.0 as well.

> > Right.  This is not different from how it works in YANG 1.0.

I assume that modules that are not implementable (e.g., due to must
constraints that can never be true) will not be implemented. I also
assume that a server announcing a set of modules that can't be
compiled together will receive appropriate customer feedback.

What Y45-04 primarily fixes is any ambiguity at module compile time
concerning the typedefs and groupings being used. The other problem
space, namely what are meaningful combinations of modules, is not
addressed by Y45-04 and left for further study. (I personally believe
we need at some point in time something like packages but this
hopefully can be done as a language extension; fixing the typedef and
grouping drift is something we have to resolve in YANG 1.1 since it
impacts the semantics of imports.)

/js

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 23 Apr 2015 09:59:29 +0200

> On 23 Apr 2015, at 09:34, Juergen Schoenwaelder <[email-masked]> wrote:
> 

Y45-04 also gives module designers a chance to decide for each grouping or typedef to either fix the revision that’s used, or leave it to a server implementor to choose the revision. It is then of course the implementor’s responsibility to make sure that the revisions work together.

RFC6087bis can give some advice in this respect, for example that IANA-controlled types should in general be imported without revision.

+1

Lada

---

From: Andy Bierman <[email-masked]>
Date: Thu, 23 Apr 2015 10:48:54 -0700

> impacts the semantics of imports.)

You missed my point.

The authors of a module that imports a specific revision of
another module expect that the import-by-revision will
be honored.  It should not be up to the vendor to pick a
down-rev version. The vendor MUST implement the version specified
in the import-stmt or the API will not be exactly as specified in the
combined YANG modules, and will not be interoperable.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 23 Apr 2015 20:15:13 +0200

> combined YANG modules, and will not be interoperable.

There is confusion here, for sure. The problem is that implement is
used in two different meanings.

- By using import by revision, it is exactly defined what the typedefs
  and groupings are that must be implemented. There is no ambiguity
  here (no typedef or grouping drift).

- If a module augments something in another module, then this
  something must of course exist. Note that Y45-04 even with
  import-by-revision does not require that exactly the revision
  imported is implemented. In particular, it should be safe to
  implement any newer revision. To find out out which revisions have
  been implemented, you read the modules announcements.

In other words, the import makes it clear what is imported into a
specific module; it does not pose a strict requirement of which module
versions must combined in an implementation.

There might be additional module dependencies (e.g., embedded in must
of when statements) that may make some combinations impossible to
implement. An implementation that announces something impossible to
implement is broken or simply unfaithful.

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 23 Apr 2015 20:35:49 +0200 (CEST)

Andy Bierman <[email-masked]> wrote:
> in the import-stmt

But this can never work.  Two separate modules might import two
different version of a common module.  Then the server cannot
implement them.  The only reasonable conclusion from this statement is
to remove import-by revision from YANG 1.1.  (and then you really
didn't gain anything b/c the server can implement any version it
likes)

> or the API will not be exactly as specified in the

This is where your idea of packages come in.  Juergen has also pointed
this out.  In a package, we can define a set of revisions of modules
and features that a server must implement in order to claim
conformance to the package.

/martin

---

From: Andy Bierman <[email-masked]>
Date: Thu, 23 Apr 2015 11:48:14 -0700

> didn't gain anything b/c the server can implement any version it

Both foo and bar augment X.

If foo imports X@R1 and bar imports X@R2 then IMO the server
has to implement X@R2.  I agree it is OK for foo to augment X
and also bar to augment X.  The augment of X@R1 should
still work in X@R2.

But we cannot be very sure that the "bar" augment of X@R2
will work with X@R1.

IMO treating import-by-revision as "min-revision"
means that the server can only choose newer than
the specified import-by-revision, never lower than that.
Using the typedefs and groupings from the specified revision
may not mix well with augmented objects from a previous version.

> conformance to the package.

Well, we don't have conformance packages, just "inline complexity".

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 23 Apr 2015 21:04:26 +0200 (CEST)

> But we cannot be very sure that the "bar" augment of X@R2

Does this mean that your are ok with Y45-04, provided we change the
text about "any revision" to text about "any revision >= the imported
revision"?

/martin

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 23 Apr 2015 21:03:50 +0200

> But we cannot be very sure that the "bar" augment of X@R2

Yes, if module authors create something like this, it will not be
implemented. The same is true for must statements that will never be
true.

> may not mix well with augmented objects from a previous version.

This is not what Y45-04 says. The imported revision is important for
resolving typedefs and groupings. There might be older versions that
define something that gets augmented and which has never changed since
then and in such a situation there is no reason to not allow this.
The set module combinations that can work together is orthogonal to
the question how typedef and grouping drift is avoided.

> Well, we don't have conformance packages, just "inline complexity".

The assumption is that we can add conformance packages later via
extensions. Addressing typedef and grouping drift is something we have
to as part of YANG 1.1 because this import semantics can't be changed
with extensions.

/js

---

From: Andy Bierman <[email-masked]>
Date: Thu, 23 Apr 2015 12:20:43 -0700

> text about "any revision" to text about "any revision >= the imported

That would make Y45-04 better.
YANG 1.1 is still too complicated and the likelihood of "pilot error"
is way too high, but that will take care of itself somehow
(perhaps free tools will hide the complexity).

Andy

---

From: Andy Bierman <[email-masked]>
Date: Thu, 23 Apr 2015 12:28:13 -0700

> implemented. The same is true for must statements that will never be

Let me try to explain my concern again...

The authors of "bar" expect that module X rev 2 will be supported.
That is why they used import-by-revision.  Mixing typedefs and
groupings from R2 and protocol accessible objects from R1 is not what
they expect.  They cannot possibly write their module "bar"
for every possible combination of down-rev X modules the vendor may choose.

It is not the fault of the designers if bar does not work with X@R1.
They expect X@R2 to be used.

Andy

---

From: Xiang Li <[email-masked]>
Date: Thu, 23 Apr 2015 14:54:03 -0500

> text about "any revision" to text about "any revision >= the imported

I think this is an important point. This way we are not completely 
redefining
  the meaning of  "import" .

So is my understanding below correct after reading this thread?

If I want to use a particular typedef in an ancient version of foo , and 
also augment a
node A in a newer version of foo (the ancient version of foo does not 
have node A defined),
I must do:

1) Import foo with a revision-date that contains my particular typedef,
2) I must also at the same time,  either import a version of foo that 
has node A defined,
     or import foo without revision, with a different prefix.  (This way 
the reference to node A
     in my augment can only make sense)

Thanks
--Xiang

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 24 Apr 2015 09:26:01 +0200

>     in my augment can only make sense)

Yes.

/js

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 24 Apr 2015 09:37:38 +0200

> They expect X@R2 to be used.

I can easily construct cases where this may not be true nor
problematic. If we make the interpretation min-revision, I am sure we
will regret it at some point in time since we will have a hard time to
ever retire an RFC because there is an incentive to always refer to
the initial definition for the /interfaces container defined in
ietf-interfaces.yang unless there is a specific need to require a
newer revision. This is in particular a concern if
ietf-interfaces.yang is updated with additions that do not at all
affect the /interfaces container.

The assumption that the set of imports used by all modules determines
the version of modules a server implements does not work with the goal
that a server implements exactly one version of every module. This
only works if you have full control over the module revision process.

Anyway, if the consensus is to make the semantics min-revision, I will
go along with it. But I am convinced we will regret it at some point
in time or we declare that we all moved to a newer version of a module
but implementations will cheat.

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 24 Apr 2015 10:06:44 +0200 (CEST)

Juergen Schoenwaelder <[email-masked]> wrote:
> will regret it at some point in time

I agree.  The min-revision rule would be an unnecessary CLR.

I asked before for an example of where the proposed solution is
problematic, and where the min-revision would solve that.

> since we will have a hard time to

I have updated the issues list with this solution, Y45-05.

Maybe the chairs can do another poll for consensus on this issue?

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Fri, 24 Apr 2015 11:02:46 +0200

> combined YANG modules, and will not be interoperable.

If import-by-revision already implies the server must implement that
revision of the imported module, one can then ask why the server needs
to advertise this module again.

In fact, the semantics of import is often confusing for new users, see
e.g. a recent pyang issue:

https://github.com/mbj4668/pyang/issues/131

And for augments it's even weirder because an augment in fact *exports*
stuff into the imported module.

Lada

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 24 Apr 2015 14:42:51 +0200

> stuff into the imported module.

Whether this is a bug or feature of pyang can be debated but at the
end it not so relevant.

The key here is to recognize that resolution of references at module
compile time is one thing and module versions implemented on a server
is another thing. This is almost like in C: the compiler (or
pre-processor) cares about the definitions (or headers) you import,
the linker cares of resolving symbol dependencies. The libraries that
make up your program are not determined by the #include, they are at
best implied by the #includes but even then ultimately it is the
symbol references in your object files that matter.

The import statement must take care of determining which definitions
are used when a module is compiled. The module announcement says which
module versions have been 'linked' together in an implementation. And
in the future, we may define packages of modules (and their versions)
that serve certain use cases. But the idea is that this can be
detached from the YANG 1.1 work where we have to clarify how we deal
with typedef and grouping drift.

/js

---

From: Andy Bierman <[email-masked]>
Date: Fri, 24 Apr 2015 08:00:05 -0700

Hi,

>From a conformance POV, letting the vendor choose among
many obsolete revisions and still claim conformance
it totally broken.  The data model writers are supposed
to specify conformance at module-write-time,
The vendor should not be specifying conformance at
module-load-time.

The goal of conformance is to specify what the client and server
are supposed to implement.  The goal of server capability discovery
is to specify what the server actually implements.  I think the WG is
confused (or ignoring) the difference.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 24 Apr 2015 17:13:38 +0200

> confused (or ignoring) the difference.

Sure, I may be confused. But let me try to explain again how I look at
this:

a) With Y45-04, we are fixing the typedef drift and grouping drift
   problem. This is an important module compile time issue. Fixing
   this makes it unambiguous at module compile time what the
   definitions resolve to.

b) A server announces the modules and the revisions it implements via
   the yang library data model. This covers the 'server capability
   discovery' you mention above. (Note: Once I have the modules at
   their specific revisions, I can can compile them without any
   typedef drift and grouping drift issues.)

c) The part that we do not cover is the 'specification of conformance
   that a server has to implement' (to support certain use cases).
   This is what we assume to be able to cover in the future using
   language extensions (and you wrote a pretty decent proposal for
   this a while ago).

I think I learned during the many discussions that the idea to derive
c) out of the imports is not workable.

/js

---

From: Andy Bierman <[email-masked]>
Date: Fri, 24 Apr 2015 08:54:08 -0700

> c) out of the imports is not workable.

But the current solution is even worse than no solution.
The client developer needs to be able to code to the model
and have that code with servers that conform to the model.

The problem is that for conformance purposes, the contents of the model
cannot be determined at run-time.  A client will need to code to
specific server implementations or code to work with every possible
combination of module revisions the server vendor may choose.

Andy

---

From: Xiang Li <[email-masked]>
Date: Fri, 24 Apr 2015 12:36:25 -0500

Hi Juergen,

> symbol references in your object files that matter.

True. But because we have "augment",  the meaning of 
"import-by-revision" is
now overloaded.

When augmenting,  the seemly logic behind "augmenting the imported module
with the specific revision" does imply the server is required to support the
revision that is being imported. The "min-revision-rule" helps
guarantee this.

The question to me now is this:  is a module designer allowed to call out
the minimum revision for the augmented module that a server must
support? To me it appears allowing that is reasonable, probably because the
module designer may expect some capabilities must be available first before
starting to design the augmenting module. However I don't have a concrete
use-case example so I am not entirely sure about this feature.

If the answer to this question is "Yes" then I think it may not be entirely
possible to restrain "importing-by-revision" to only mean to incorporate
typdef and other declarations, and we need this "min-revision-rule".
Otherwise I agree this "min-revision-rule" is not needed and 
"revision-date"
must be completely ignored for augmenting purpose.

--Xiang

---

From: Andy Bierman <[email-masked]>
Date: Fri, 24 Apr 2015 21:24:43 -0700

> problematic, and where the min-revision would solve that.

Here is a simple example that I find problematic.
This is what I mean by coding to the model.
The client developer adds code to augment a base node
if the port-knob-type is 'fastest'

  module base {
     ...
     revision 2014-01-01;
     typedef port-knob-type {
         type enumeration {
           enum fast;
           enum faster;
        }
     }
     list port-knob {
       key name;
       leaf name { type string; }
       leaf knob-type { type port-knob-type; }
     }
  }

 module base {
     ...
     revision 2015-01-01;
     typedef port-knob-type {
         type enumeration {
           enum fast;
           enum faster;
           enum fastest'      // added new enum
        }
     }
     list port-knob {
       key name;
       leaf name { type string; }
       leaf knob-type {
          type port-knob-type;
          default fast;

     }
  }

  module aug1 {
     ...
     import base {
        prefix b;
        revision-date "2015-01-01";
     }

     augment b:/port-knob {
          when "b:knob-type = 'faster'";
           leaf alt-knob-type {
                type b:port-knob-type;
           }
      }

    augment b:/port-knob {
          when "b:knob-type = 'fastest'";
           leaf boost-factor { type uint32; }
      }

  }

The 'aug1' developer clearly intends for the server to
support base@2015-01-01.

But the vendor decides to advertise base@2014-01-01.

The 'port-knob' list is augmented with the new version
of the port-knob-type (if 'faster') even though the server implements
the old version.

The ''boost-factor'' leaf will never augment the port-knob list
because server does not support the 'fastest' enum.

This is more than just confusing, especially if the server
advertises that it conforms to the "aug1" module.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Sun, 26 Apr 2015 14:57:27 +0200

> and have that code with servers that conform to the model.

I believe Y45-04 allows that.

/js

---

From: Andy Bierman <[email-masked]>
Date: Sun, 26 Apr 2015 09:08:11 -0700

> I believe Y45-04 allows that.

I don't think more than 1 revision of a module needs to be imported.
Cherry-picking from all available revisions is a bad precedent.

The 'port-knob-type' example is the most common use-case --
adding a new enum to a typedef.  The WG already agreed (I think)
that the server MUST support the base module augmented
from another module.  The example shows the server MUST implement
the same (or more recent) version that is used by any module that
augments the module, in order to claim conformance for both the
augmented and augmenting modules.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Sun, 26 Apr 2015 19:18:05 +0200

> Cherry-picking from all available revisions is a bad precedent.

What are the alternatives? Move definitions into many very small
modules so that all-or-nothing updates are workable? Require that all
semantically changed definitions get a new name? The later is the at
the end the same except that you maintain all revisions inside the
module. In other words, cherry-picking by itself is not a bad
precedent, we have been doing that before - the question is just how
we maintain the different versions.

> augmented and augmenting modules.

I do not think that the WG agreed on something yet.

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Sun, 26 Apr 2015 19:32:11 +0200 (CEST)

> But the vendor decides to advertise base@2014-01-01.

Well, boost-factor is only relevant if b:knob-type is 'fastest'.  So
if the vendor advertises base@2014-01-01, b:knob-type can never be
'fastest'.  I don't see any problem with this.

> advertises that it conforms to the "aug1" module.

It advertises that it *implements* aug1.

I think Juergen has tried to say several times that what we're trying
to do is really to let the server advertise what it implements, and
then add possibly more useful conformance functions later (maybe
something like your packages).

/martin

---

From: Andy Bierman <[email-masked]>
Date: Sun, 26 Apr 2015 11:04:43 -0700

> we maintain the different versions.

I don't think the YANG module packaging and imports used is a good
way to document the conformance requirements for meaningful
sets of protocol accessible objects.  That's why I proposed
conformance packages in the YANG Conformance draft.

The only way the using import without revision is really safe
is if all definitions used from the importing module were available
from the very first revision.  Since we are on the first revision
of everything, the need for a "min-revision" is not apparent yet.
If we ever change a definition to obsolete, then the need for
a "max-revision" will become apparent.  (These parameters were
in the original conformance draft).

Andy

---

From: Andy Bierman <[email-masked]>
Date: Sun, 26 Apr 2015 11:11:29 -0700

> It advertises that it *implements* aug1.

This is the problem.
If it does advertise "aug1", then it MUST advertise "not-supported" deviations
for both leafs, because they both rely on the new revision of the typedef,
and the server does not implement the new typedef.

> something like your packages).

This proposal does not let the client developer know what the server is
supposed to implement. The conformance requirements are not very
precise.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Sun, 26 Apr 2015 20:50:33 +0200 (CEST)

> and the server does not implement the new typedef.

No, the definition of the augment for boost-factor does not strictly
rely on the new revision of the typedef.  It's just that the when
expression will never evaluate to true if the newer version isn't
implemented.

> supposed to implement. The conformance requirements are not very

Agreed.  This is why we want to address the conformance problem
separately.  Right now we try focus on what the different constructs
really imply in terms of implementing other modules.

/martin

---

From: Xiang Li <[email-masked]>
Date: Thu, 30 Apr 2015 09:19:01 -0500

> expression will never evaluate to true if the newer version isn't

But if a server advertises "aug1" the it is claiming that "aug1" is 
fully supported. Since 'aug1'
augments "base 2015-01-01", I would think  that I must be able to set 
the leaf "b:knob-type"
to the value "fastest" and then expect to be able to play with the 
augmented "boost-factor"
leaf.  If the server advertises only "base 2014-01-01", this would not 
be possible. Is this an
invalid scenario?

Anyway, as I said earlier  I agree with Y45-04 if no valid use-case 
exists for 'min-revision-rule"
since that seems to be cleanest way to address the question we are 
trying to address.
It is just different from what I thought originally that augmenting a 
module via "import-by-revision"
implies the imported module version is the base of the augmenting and 
hence it must be
supported first.

--Xiang

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 30 Apr 2015 18:15:42 +0200

> On 30 Apr 2015, at 16:19, Xiang Li <[email-masked]> wrote:
> 
> 
> 
> But if a server advertises "aug1" the it is claiming that "aug1" is fully supported. Since ‘aug1'

This is not sufficient, in order to decide whether “aug1” is fully supported, “base” must be advertised, too, and the supported features as well.

Lada

> augments "base 2015-01-01", I would think  that I must be able to set the leaf "b:knob-type"
> to the value "fastest" and then expect to be able to play with the augmented "boost-factor"
> leaf.  If the server advertises only "base 2014-01-01", this would not be possible. Is this an
> invalid scenario?
> 
> Anyway, as I said earlier  I agree with Y45-04 if no valid use-case exists for 'min-revision-rule"
> since that seems to be cleanest way to address the question we are trying to address.
> It is just different from what I thought originally that augmenting a module via "import-by-revision"
> implies the imported module version is the base of the augmenting and hence it must be
> supported first.
> 
> --Xiang
> 
> 
>

---

From: Xiang Li <[email-masked]>
Date: Thu, 30 Apr 2015 12:32:12 -0500

> This is not sufficient, in order to decide whether “aug1” is fully supported, “base” must be advertised, too, and the supported features as well.

Of course.  "base" must be advertised. Though I don't think any 
"features" must be advertised.
By definition a feature is optional.

The question is whether a server should be allowed to advertise 
base@2014-01-01 and "aug1" at the same time.

If we let a server  implementation decide what "base" version that 
"aug1" is augmenting then a module
designer has no say about which "base" that his/her "aug1" must be based 
on.  If so the module designer may have to design "aug1" in a way that 
is base-version-agnostic. I am fine with that if that is
intention of the working group.

-Xiang

---

From: Andy Bierman <[email-masked]>
Date: Thu, 30 Apr 2015 10:45:27 -0700

On Thu, Apr 30, 2015 at 10:32 AM, Xiang Li <[email-masked]> wrote:
>> This is not sufficient, in order to decide whether “aug1” is fully
>> supported, “base” must be advertised, too, and the supported features as
>> well.
>
>
> Of course.  "base" must be advertised. Though I don't think any "features"
> must be advertised.
> If we let a server  implementation decide what "base" version that "aug1" is
> augmenting then a module
> designer has no say about which "base" that his/her "aug1" must be based on.
> If so the module designer may have to design "aug1" in a way that is
> base-version-agnostic. I am fine with that if that is

I strongly object to this new interpretation of YANG conformance.
The designer should pick the modules and revisions of those modules
that are required in order to claim compliance with the standard.
If the designer says import base@2015-01-01 then that is
what is required for compliance to module "aug1".

Andy

---

From: Xiang Li <[email-masked]>
Date: Thu, 30 Apr 2015 14:20:22 -0500

> I strongly object to this new interpretation of YANG conformance.

My understanding is that this is not about "YANG conformance" anymore.

> what is required for compliance to module "aug1".

Not if the implication of any compliance meaning is stripped away from 
"import-by-revision".

In this case if a server advertises "aug1" then it does mean "aug1" is 
supported. But what's
really available in "aug1"? You have to examine the  "base" version 
advertised and any "features",
(as shown in Lada's example) as well.

In other words,  the author of "aug1" will now have extra work to do 
since he/she can't
assume which (minimum) base version implementation is available. I 
imagine lots
of nodes in "aug1" will have to be made optional, using 
when/must/if-feature to determine
the start point of an augment.

--Xiang

---

From: Andy Bierman <[email-masked]>
Date: Thu, 30 Apr 2015 12:33:49 -0700

On Thu, Apr 30, 2015 at 12:20 PM, Xiang Li <[email-masked]> wrote:
>>>>>>>>>>> problematic. If we make the interpretation min-revision, I am
>>>>>>>>>>> sure
>>>>>>>>>>> we
>>>>> fully
>>>>> supported. Since ‘aug1'
>>> on.

Sure it is.
There are no other YANG conformance mechanisms other than
the YANG language itself.

If it is unclear which version of any module
is required for implementation, then YANG is a failure.
Import without revision says "any possible revision of this module
that you can find is OK to use".

If that is not the case, then an import-by-revision says
"use this specific revision".

If module "aug1" says use base@2015-01-01 and the
server has to use that revision (or a newer version).

> In other words,  the author of "aug1" will now have extra work to do since
> he/she can't
> assume which (minimum) base version implementation is available. I imagine
> lots
> of nodes in "aug1" will have to be made optional, using when/must/if-feature
> to determine

I don't want to design "aug1" to work with every possible back-revision
of the base module.  What is the point of all this extra complexity?
I need to be able to define API features that rely of specific data model
functionality.  The implementation requirements must be clear
at module compile-time, not decided at server run-time.

Andy

---

From: Xiang Li <[email-masked]>
Date: Thu, 30 Apr 2015 17:09:10 -0500

> the YANG language itself.

True. But as I understand it is going to to addressed further separately
and (possibly) use something like "package" you proposed?

> server has to use that revision (or a newer version).

Sure... and for the purpose of augment, I agree and prefer that we use 
"augment by the min-revision-policy" .

But this assigns overloaded meanings for "import-by-revision". For 
typedefs the data nodes in the
imported module are not required to be implemented. For augment, they are.

It is my understanding that this double meaning is potentially very 
confusing to people and have
some side-effects so Juregen/Lada/Martin want to avoid it.

> of the base module.  What is the point of all this extra complexity?

While I don't think you have to design "aug1" to work with every 
possible back-revision of
the  base module, and also not sure how much extra complexity it can 
add,  I do agree this
may put more burden on the developer of "aug1".

> The implementation requirements must be clear
I tend to agree. That's why I prefer augment-min-revision-policy you 
proposed:

1) For typedefs,  "import by revision" does not mean a server to support 
imported module
    (implement its data nodes) at all

2) For augment, "import by revision" does require the base revision (or 
a newer revision) of an
     imported module to be supported.

--Xiang