Adding initial test cases, include enumeration conversion, address review comments

Change-Id: I59a19f80289464c934ad16d2d2ce1c78a6ba6f2c
diff --git a/experiments/plugin/protobuf.py b/experiments/plugin/protobuf.py
index 433ae30..fc177b7 100644
--- a/experiments/plugin/protobuf.py
+++ b/experiments/plugin/protobuf.py
@@ -17,13 +17,24 @@
 
 """pyang plugin to convert a yang schema to a protobuf schema
 
-   - very basic support for leaf, leaf-list, containers, list
+   - basic support for leaf, leaf-list, containers, list
+
+   - this plugin requires pyang to be present and is run using pyang as
+   follows:
+
+   $ pyang --plugindir /voltha/experiments/plugin -f protobuf  -o
+   <protofile> -p /voltha/tests/utests/netconf/yang
+   /voltha/tests/utests/netconf/yang/<yang file>
+
+   - pyang validates the yanhg definition first and then invoke this plugin
+   to convert the yang model into protobuf.
    
 """
 
 from pyang import plugin, statements, error
 from pyang.util import unique_prefixes
 
+
 # Register the Protobuf plugin
 def pyang_plugin_init():
     plugin.register_plugin(ProtobufPlugin())
@@ -42,37 +53,54 @@
 
     def set_headers(self, module_name):
         self.headers.append('syntax = "proto3";')
-        self.headers.append('package {};'.format(module_name))
+        self.headers.append('package {};'.format(module_name.replace('-',
+                                                                     '_')))
 
     def _print_container(self, container, out, level=0):
         spaces = '    ' * level
         out.append(''.join([spaces, 'message {} '.format(container.name)]))
         out.append(''.join('{\n'))
-        for idx, l in enumerate(container.leafs):
-            leafspaces = ''.join([spaces, '    '])
-            out.append(''.join([leafspaces, '{}{} {} = {} ;\n'.format(
-                'repeated ' if l.leaf_list else '',
-                l.type,
-                l.name,
-                idx + 1)]))
+        self._print_leaf(container.leafs, out, spaces)
+
+        for l in container.ylist:
+            self._print_list(l, out, level)
 
         for inner in container.containers:
             self._print_container(inner, out, level + 1)
 
         out.append(''.join([spaces, '}\n']))
 
-    def _print_list(self, ylist, out):
+    def _print_list(self, ylist, out, level=0):
+        spaces = '    ' * level
         out.append('message {} '.format(ylist.name))
         out.append('{\n')
-        for idx, l in enumerate(ylist.leafs):
-            leafspaces = '    '
-            out.append(''.join([leafspaces, '{}{} {} = {} ;\n'.format(
-                'repeated ' if l.leaf_list else '',
-                l.type,
-                l.name,
-                idx + 1)]))
+        self._print_leaf(ylist.leafs, out, spaces)
+
+        for l in ylist.ylist:
+            self._print_list(l, out, level + 1)
+
         out.append('}\n')
 
+    def _print_leaf(self, leafs, out, spaces):
+        for idx, l in enumerate(leafs):
+            leafspaces = ''.join([spaces, '    '])
+            if l.type == "enum":
+                out.append(''.join([leafspaces, 'enum {}\n'.format(l.name)]))
+                out.append(''.join([leafspaces, '{\n']))
+                self._print_enumeration(l.enumeration, out, leafspaces)
+                out.append(''.join([leafspaces, '}\n']))
+            else:
+                out.append(''.join([leafspaces, '{}{} {} = {} ;\n'.format(
+                    'repeated ' if l.leaf_list else '',
+                    l.type,
+                    l.name,
+                    idx + 1)]))
+
+    def _print_enumeration(self, yang_enum, out, spaces):
+        enumspaces = ''.join([spaces, '    '])
+        for idx, e in enumerate(yang_enum):
+            out.append(''.join([enumspaces, '{}\n'.format(e)]))
+
     def print_proto(self):
         out = []
         for h in self.headers:
@@ -80,13 +108,16 @@
         out.append('\n')
         for m in self.messages:
             out.append('{}\n'.format(m))
-        out.append('\n')
+        if self.messages:
+            out.append('\n')
         for l in self.ylist:
             self._print_list(l, out)
-        out.append('\n')
+        if self.ylist:
+            out.append('\n')
         for c in self.containers:
             self._print_container(c, out)
-        out.append('\n')
+        if self.containers:
+            out.append('\n')
 
         return out
 
@@ -97,12 +128,15 @@
         self.containers = []
         self.enums = []
         self.leafs = []
+        self.ylist = []
 
 
 class YangList():
     def __init__(self):
         self.name = None
         self.leafs = []
+        self.containers = []
+        self.ylist = []
 
 
 class YangLeaf():
@@ -110,9 +144,15 @@
         self.name = None
         self.type = None
         self.leaf_list = False
+        self.enumeration = []
         self.description = None
 
 
+class YangEnumeration():
+    def __init__(self):
+        self.value = []
+
+
 class ProtobufPlugin(plugin.PyangPlugin):
     def add_output_format(self, fmts):
         self.multiple_modules = True
@@ -127,13 +167,43 @@
         self.real_prefix = unique_prefixes(ctx)
 
         for m in modules:
+            # m.pprint()
+            # statements.print_tree(m)
             proto = Protobuf()
             proto.set_headers(m.i_modulename)
+            self.process_substatements(m, proto, None)
             self.process_children(m, proto, None)
             out = proto.print_proto()
             for i in out:
                 fd.write(i)
 
+    def process_substatements(self, node, parent, pmod):
+        """Process all substmts.
+        """
+        for st in node.substmts:
+            if st.keyword in ["rpc", "notification"]: continue
+            if st.keyword in ["choice", "case"]:
+                self.process_substatements(st, parent, pmod)
+                continue
+
+            if st.i_module.i_modulename == pmod:
+                nmod = pmod
+            else:
+                nmod = st.i_module.i_modulename
+
+            if st.keyword in ["container", "grouping"]:
+                c = YangContainer()
+                c.name = st.arg
+                self.process_substatements(st, c, nmod)
+                parent.containers.append(c)
+            elif st.keyword == "list":
+                l = YangList()
+                l.name = st.arg
+                self.process_substatements(st, l, nmod)
+                parent.ylist.append(l)
+            elif st.keyword in ["leaf", "leaf-list"]:
+                self.process_leaf(st, parent, st.keyword == "leaf-list")
+
     def process_children(self, node, parent, pmod):
         """Process all children of `node`, except "rpc" and "notification".
         """
@@ -144,14 +214,9 @@
                 continue
             if ch.i_module.i_modulename == pmod:
                 nmod = pmod
-                nodename = ch.arg
-                print pmod, nodename
             else:
                 nmod = ch.i_module.i_modulename
-                nodename = "%s:%s" % (nmod, ch.arg)
-            ndata = [ch.keyword]
-            if ch.keyword == "container":
-                print ch.keyword
+            if ch.keyword in ["container", "grouping"]:
                 c = YangContainer()
                 c.name = ch.arg
                 self.process_children(ch, c, nmod)
@@ -170,33 +235,35 @@
         leaf = YangLeaf()
         leaf.name = node.arg
         leaf.type = self.get_protobuf_type(node.search_one("type"))
+        if leaf.type == "enum":
+            self.process_enumeration(node, leaf)
         # leaf.type = self.base_type(node.search_one("type"))
         leaf.description = node.search_one("description")
         leaf.leaf_list = leaf_list
         parent.leafs.append(leaf)
 
+    def process_enumeration(self, node, leaf):
+        enumeration_dict = {}
+        start_node = None
+        for child in node.substmts:
+            if child.keyword == "type":
+                start_node = child;
+                break
+
+        for enum in start_node.search('enum'):
+            val = enum.search_one('value')
+            if val is not None:
+                enumeration_dict[enum.arg] = int(val.arg)
+            else:
+                enumeration_dict[enum.arg] = '0'
+
+        for key, value in enumerate(enumeration_dict):
+            leaf.enumeration.append('{} = {} ;'.format(value, key))
+
     def get_protobuf_type(self, type):
-        protobuf_types_map = dict(
-            binary='Any',
-            bits='bytes',
-            boolean='bool',
-            decimal64='sint64',
-            empty='string',
-            int8='int32',
-            int16='int32',
-            int32='int32',
-            int64='int64',
-            string='string',
-            uint8='uint32',
-            uint16='uint32',
-            uint32='uint32',
-            uint64='uint64',
-            union='OneOf',
-            enumeration='enum'
-        )
         type = self.base_type(type)
-        if protobuf_types_map[type]:
-            return protobuf_types_map[type]
+        if type in self.protobuf_types_map.keys():
+            return self.protobuf_types_map[type]
         else:
             return type
 
@@ -213,7 +280,28 @@
         if type.arg == "decimal64":
             return [type.arg, int(type.search_one("fraction-digits").arg)]
         elif type.arg == "union":
-            return [type.arg,
-                    [self.base_type(x) for x in type.i_type_spec.types]]
+            # TODO convert union properly
+            return type.arg
+            # return [type.arg,
+            #         [self.base_type(x) for x in type.i_type_spec.types]]
         else:
             return type.arg
+
+    protobuf_types_map = dict(
+        binary='Any',
+        bits='bytes',
+        boolean='bool',
+        decimal64='sint64',
+        empty='string',
+        int8='int32',
+        int16='int32',
+        int32='int32',
+        int64='int64',
+        string='string',
+        uint8='uint32',
+        uint16='uint32',
+        uint32='uint32',
+        uint64='uint64',
+        union='string',  # TODO : not correct mapping
+        enumeration='enum'
+    )
diff --git a/tests/itests/__init__.py b/tests/itests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/itests/__init__.py
diff --git a/tests/utests/netconf/yang/basic.yang b/tests/utests/netconf/yang/basic.yang
new file mode 100644
index 0000000..7bba944
--- /dev/null
+++ b/tests/utests/netconf/yang/basic.yang
@@ -0,0 +1,17 @@
+module basic {
+    namespace "urn:acme:yang:basic";
+    prefix "basic";
+
+    grouping commonAttributes {
+        leaf my-id {
+            type uint8;
+        }
+        leaf my-name {
+            type string;
+        }
+        leaf my-status {
+            type boolean;
+            config false;
+        }
+    }
+}
diff --git a/tests/utests/netconf/yang/container.yang b/tests/utests/netconf/yang/container.yang
new file mode 100644
index 0000000..dbc5dfb
--- /dev/null
+++ b/tests/utests/netconf/yang/container.yang
@@ -0,0 +1,34 @@
+module container {
+    yang-version "1";
+    namespace "http://rob.sh/yang/test/base-test";
+    prefix "foo";
+    organization "BugReports Inc";
+    contact "A bug reporter";
+
+    description
+        "A test module that checks that the plugin works OK";
+    revision 2014-01-01 {
+        description "april-fools";
+        reference "fooled-you";
+    }
+
+    container int-container {
+        description
+            "A container";
+        choice name {
+             case me {
+                    leaf eight {
+                        type int8;
+                        description
+                        "A test leaf for uint8";
+                    }
+             }
+             case myself {
+                     leaf nine {
+                       type int16;
+                       description "i am nine";
+                    }
+             }
+        }
+    }
+}
diff --git a/tests/utests/netconf/yang/cord-tenant.yang b/tests/utests/netconf/yang/cord-tenant.yang
new file mode 100644
index 0000000..c858094
--- /dev/null
+++ b/tests/utests/netconf/yang/cord-tenant.yang
@@ -0,0 +1,90 @@
+module cord-tenant {
+  namespace "urn:ietf:params:xml:ns:yang:cord-tenant";
+  prefix cord;
+  yang-version 1.1;
+
+  import xos-controller  { prefix xos; }
+
+  organization
+    "Open Networking Lab (CORD) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+
+  description
+    "This module contains a collection of core models for CORD.
+
+     Copyright (c) 2016 ON.LAB and the persons identified as authors
+     of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject to
+     the license terms of the Apache License, Version 2.0 which
+     accompanies this distribution, and is available at
+     (http://www.apache.org/licenses/LICENSE-2.0).";
+
+  revision 2016-09-29 {
+    description "Combine CORD subscriber and augment XOS.";
+  }
+  revision 2016-07-22 {
+    description "Initial revision.";
+  }
+
+  identity cord-subscriber {
+    base xos:xos-subscriber;
+  }
+  /*
+   * Groupings
+   */
+  grouping subscriber {
+  /*
+    uses xos:subscriber {
+      refine kind { default cord-subscriber; }
+    }
+   */
+    leaf label {
+      config false;
+      type string {
+        pattern '^cordSubscriber-\w+$';
+      }
+    }
+    leaf status {
+      type enumeration {
+        enum "enabled" {
+          description "Enabled";
+          value 1;
+        }
+        enum "suspended" {
+          description "Suspended";
+        }
+        enum "delinquent" {
+          description "Delinquent";
+        }
+        enum "violation" {
+          description "Copyright Violation";
+        }
+      }
+      default enabled;
+    }
+    leaf demo {
+      type boolean;
+      default false;
+    }
+  }
+  /*
+   * Augmentations to XOS
+
+  augment "/xos:tenant" {
+    container cord {
+      description "Register cord as a tenant into XOS";
+      list subscriber {
+        key id;
+        description
+          "Each entry represents a unique CORD subscriber.";
+        uses cord:subscriber;
+      }
+    }
+  }
+  */
+}
diff --git a/tests/utests/netconf/yang/cord-volt-service.yang b/tests/utests/netconf/yang/cord-volt-service.yang
new file mode 100644
index 0000000..111421e
--- /dev/null
+++ b/tests/utests/netconf/yang/cord-volt-service.yang
@@ -0,0 +1,195 @@
+module cord-volt-service {
+  namespace "urn:ietf:params:xml:ns:yang:cord-volt-service";
+  prefix volt;
+  yang-version 1.1;
+
+  import cord-tenant     { prefix cord; }
+  import xos-controller  { prefix xos; }
+  import xos-types       { prefix xtype; }
+  
+  organization
+   "Open Networking Lab (CORD) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+
+  revision 2016-09-09 {
+    description "Initial revision.";
+  }
+
+  identity virtual-olt { base xos:xos-service; }
+
+  feature onos-app-olt {
+    description "System facility to configure VLAN tags on the OLT.";
+  }
+  feature onos-app-aaa {
+    description "System facility to broker authentication between CPE and Radius server.";
+  }
+  /*
+   * Type definitions
+   */
+  typedef bandwidth {
+    type xtype:bandwidth;
+    default 1000000000; // VOLT bandwidth default is 1Gbps
+  }
+  typedef subscriber-outflow {
+    type leafref {
+      path "/volt:controller/volt:port/volt:id";
+    }
+  }
+  /*
+   * Groupings
+   */ 
+  grouping devices-list {
+    grouping olt-device {
+      description
+        "This grouping describes an OLT device which contains ODN link attachments.";
+    
+      leaf name {
+        description "name of OLT device";
+        type string {
+          length 1..254;
+        }
+      }
+      leaf mac { type xtype:mac-address; mandatory true; }
+
+      container uplink {
+        description "Uplink description of the OLT device.";
+        leaf network { type xtype:network-identifier; }
+        leaf tag {
+          type xtype:vlan;
+          description
+            "Represents S-Tag for instructing OLT to associate a VLAN tag for
+             traffic originating from OLT device.";
+        }
+      }
+      list link {
+        description
+          "Each link represents an ONU/ONT (Optical Network Termination) endpoint
+           connection.";
+
+        key serial;
+        unique tag;
+      
+        leaf mac    { type xtype:mac-address; mandatory true; }
+        leaf serial { type string; mandatory true; }
+        leaf active { type boolean; default false; }
+        leaf tag {
+          type xtype:vlan;
+          description
+            "Represents C-Tag for instructing ONT to add/remove vlan tag for
+             traffic within OLT device.";
+        }
+      }
+    }
+    list device {
+      description
+        "Each entry represents an OLT device.";
+      key mac;
+      //unique 'uplink/tag';
+      uses olt-device;
+    }
+  }
+  grouping subscriber {
+    description
+      "This grouping represents a VOLT service subscriber along with
+       references to ONU/ONT access endpoints used by the subscriber.";
+    
+    container tags {
+      description
+        "Each entry represents a unique combination of the OLT uplink VLAN
+         (outer tag) and the ONU/ONT link VLAN (inner tag) connecting
+         into the fabric for the subscriber.";
+      
+      leaf outer {
+        type leafref {
+          path "/volt:controller/volt:device/volt:uplink/volt:tag";
+        }
+      }
+      leaf inner {
+        type leafref {
+          path "/volt:controller/volt:device/volt:link/volt:tag";
+        }
+      }
+    }
+    leaf outflow {
+      description
+        "Each entry represents a unique openflow port ID that the subscriber
+         uses to connect into the fabric from the VOLT service.";
+      config false;
+      type subscriber-outflow;
+    }
+  }
+
+  /*
+   * Configuration data nodes
+   */
+  container controller {
+    description
+      "The controller configuration block represents a VOLT agent/controller
+       which manages multiple OLT devices. The VOLT agent provides
+       aggregate abstraction of the entire PON as a sigle switch to
+       the controller. Each port entry of the agent represents each
+       ONU/ONT endpoint as a separate openflow port.";
+    
+    uses xos:service {
+      refine kind  {
+        default virtual-olt;
+      }
+      augment "subscriber" { uses volt:subscriber; }
+    }
+    // additional service specific configurations
+    uses devices-list;
+    list port {
+      description
+        "Each entry represents an ONU/ONT endpoint connected across OLT devices.";
+      key id;
+      leaf id {
+        description "OpenFlow Port ID";
+        type xtype:flow-identifier;
+        mandatory true;
+      }
+      leaf link {
+        type leafref {
+          path '/volt:controller/device/link/serial';
+        }
+        mandatory true;
+      }
+    }
+    container radius {
+      if-feature onos-app-aaa;
+      // configuration for how to broker authentication requests
+    }
+  }
+  /*
+   * Augmentations to CORD Tenant in XOS
+   */
+  augment "/xos:tenant/cord:cord/cord:subscriber" {
+    container service {
+      leaf id {
+        type leafref {
+          path "/volt:controller/subscriber/id";
+        }
+      }
+      leaf c-tag {
+        config false;
+        type leafref {
+          path "/volt:controller/subscriber/tags/outer";
+        }
+      }
+      leaf s-tag {
+        config false;
+        type leafref {
+          path "/volt:controller/subscriber/tags/inner";
+        }
+      }
+      leaf uplink-speed {
+        type volt:bandwidth;
+      }
+      leaf downlink-speed {
+        type volt:bandwidth;
+      }
+    }
+  }
+}
diff --git a/tests/utests/netconf/yang/corenova-node.yang b/tests/utests/netconf/yang/corenova-node.yang
new file mode 100644
index 0000000..e0873e0
--- /dev/null
+++ b/tests/utests/netconf/yang/corenova-node.yang
@@ -0,0 +1,41 @@
+module corenova-node {
+  namespace "urn:corenova:node";
+  prefix node;
+
+  organization
+    "Corenova Technologies, Inc.";
+
+  contact
+    "Peter K. Lee <peter@corenova.com>";
+
+  description
+    "This module defines extensions to dynamically control schema node
+     display and access overlay controls";
+
+  feature corenova-node {
+    description
+      "this is to indicate the agent supports dynamic schema node
+       link and view constraints.";
+  }
+    
+  extension link {
+    description
+      "Links a new 'link-name' element to an alternate data node element in
+       the schema data tree referenced by the 'path' sub statement. It
+       can be used within 'container' or 'list' type data element to
+       hold one or more such 'links' as part of its configuration data
+       tree.  The new link element becomes a 'mirror' instance of the
+       target node found in the path expression.";
+    argument link-name {
+      yin-element true;
+    }
+  }
+
+  extension view {
+    description
+      "Informs the interface layers that only the data nodes referenced
+       within the value argument should be made visible to the
+       consumer.";
+    argument value;
+  }
+}
diff --git a/tests/utests/netconf/yang/mix_simple_types.yang b/tests/utests/netconf/yang/mix_simple_types.yang
new file mode 100644
index 0000000..c73b6cf
--- /dev/null
+++ b/tests/utests/netconf/yang/mix_simple_types.yang
@@ -0,0 +1,91 @@
+module mix-simple-types {
+    yang-version "1";
+    namespace "http://rob.sh/yang/test/base-test";
+    prefix "foo";
+    organization "BugReports Inc";
+    contact "A bug reporter";
+
+    description
+        "A test module that checks that the plugin works OK";
+    revision 2014-01-01 {
+        description "april-fools";
+        reference "fooled-you";
+    }
+
+    container int-container {
+        description
+            "A container";
+        choice name {
+             case me {
+                    leaf eight {
+                        type int8;
+                        description
+                        "A test leaf for uint8";
+                    }
+             }
+             case myself {
+                     leaf nine {
+                       type int16;
+                       description "i am nine";
+                    }
+             }
+        }
+        leaf ten {
+             type int16;
+             description "i am ten";
+        }
+    }
+
+    list user {
+       key "name";
+       leaf name {
+         type string;
+       }
+       leaf full-name {
+         type string;
+       }
+       leaf class {
+         type string;
+       }
+     }
+
+    container container1 {
+        description
+            "A container";
+        choice name {
+             case acase {
+                    leaf a {
+                        type boolean;
+                        description
+                        "A test leaf for uint8";
+                    }
+             }
+             case bcase {
+                     leaf b {
+                       type binary;
+                       description "i am nine";
+                    }
+             }
+        }
+        leaf mleaf {
+             type string;
+             description "i am string";
+        }
+        leaf-list mleaf_list {
+             type string;
+             description "i am repeated string";
+        }
+        container inner-container {
+            description
+                "A container";
+            leaf mleaf1 {
+                 type string;
+                 description "i am leaf1";
+            }
+            leaf mleaf2 {
+                 type string;
+                 description "i am leaf2";
+            }
+        }
+    }
+}
diff --git a/tests/utests/netconf/yang/openconfig-extensions.yang b/tests/utests/netconf/yang/openconfig-extensions.yang
new file mode 100644
index 0000000..d5e9442
--- /dev/null
+++ b/tests/utests/netconf/yang/openconfig-extensions.yang
@@ -0,0 +1,69 @@
+module openconfig-extensions {
+
+  yang-version "1";
+
+  // namespace
+  namespace "http://openconfig.net/yang/openconfig-ext";
+
+  prefix "ocext";
+
+  // meta
+  organization "OpenConfig working group";
+
+  contact
+    "OpenConfig working group
+    www.openconfig.net";
+
+  description
+    "This module provides extensions to the YANG language to allow
+    OpenConfig specific functionality and meta-data to be defined.";
+
+  revision "2015-10-09" {
+    description
+      "Initial OpenConfig public release";
+  }
+
+  revision "2015-10-05" {
+    description
+      "Initial revision";
+    reference "TBD";
+  }
+
+  // extension statements
+  extension openconfig-version {
+    argument "semver" {
+      yin-element false;
+    }
+    description
+      "The OpenConfig version number for the module. This is
+      expressed as a semantic version number of the form:
+        x.y.z
+      where:
+        * x corresponds to the major version,
+        * y corresponds to a minor version,
+        * z corresponds to a patch version.
+      This version corresponds to the model file within which it is
+      defined, and does not cover the whole set of OpenConfig models.
+      Where several modules are used to build up a single block of
+      functionality, the same module version is specified across each
+      file that makes up the module.
+
+      A major version number of 0 indicates that this model is still
+      in development (whether within OpenConfig or with industry
+      partners), and is potentially subject to change.
+
+      Following a release of major version 1, all modules will
+      increment major revision number where backwards incompatible
+      changes to the model are made.
+
+      The minor version is changed when features are added to the
+      model that do not impact current clients use of the model.
+
+      The patch-level version is incremented when non-feature changes
+      (such as bugfixes or clarifications to human-readable
+      descriptions that do not impact model functionality) are made
+      that maintain backwards compatibility.
+
+      The version number is stored in the module meta-data.";
+  }
+}
\ No newline at end of file
diff --git a/tests/utests/netconf/yang/openconfig-interfaces.yang b/tests/utests/netconf/yang/openconfig-interfaces.yang
new file mode 100644
index 0000000..332f7e1
--- /dev/null
+++ b/tests/utests/netconf/yang/openconfig-interfaces.yang
@@ -0,0 +1,933 @@
+module openconfig-interfaces {
+
+  yang-version "1";
+
+  // namespace
+  namespace "http://openconfig.net/yang/interfaces";
+
+  prefix "oc-if";
+
+  // import some basic types
+  import ietf-interfaces { prefix ietf-if; }
+  import ietf-yang-types { prefix yang; }
+  import openconfig-extensions { prefix oc-ext; }
+
+  // meta
+  organization "OpenConfig working group";
+
+  contact
+    "OpenConfig working group
+    netopenconfig@googlegroups.com";
+
+  description
+    "Model for managing network interfaces and subinterfaces.  This
+    module also defines convenience types / groupings for other
+    models to create references to interfaces:
+
+      base-interface-ref (type) -  reference to a base interface
+      interface-ref (grouping) -  container for reference to a
+        interface + subinterface
+      interface-ref-state (grouping) - container for read-only
+        (opstate) reference to interface + subinterface
+
+    This model reuses data items defined in the IETF YANG model for
+    interfaces described by RFC 7223 with an alternate structure
+    (particularly for operational state data) and and with
+    additional configuration items.";
+
+  oc-ext:openconfig-version "1.0.2";
+
+  revision "2016-05-26" {
+    description
+      "OpenConfig public release";
+    reference "1.0.2";
+  }
+
+
+  // typedef statements
+
+  typedef base-interface-ref {
+    type leafref {
+      path "/oc-if:interfaces/oc-if:interface/oc-if:name";
+    }
+    description
+      "Reusable type for by-name reference to a base interface.
+      This type may be used in cases where ability to reference
+      a subinterface is not required.";
+  }
+
+  typedef interface-id {
+    type string;
+    description
+      "User-defined identifier for an interface, generally used to
+      name a interface reference.  The id can be arbitrary but a
+      useful convention is to use a combination of base interface
+      name and subinterface index.";
+  }
+
+  // grouping statements
+
+  grouping interface-ref-common {
+    description
+      "Reference leafrefs to interface / subinterface";
+
+    leaf interface {
+      type leafref {
+        path "/oc-if:interfaces/oc-if:interface/oc-if:name";
+      }
+      description
+        "Reference to a base interface.  If a reference to a
+        subinterface is required, this leaf must be specified
+        to indicate the base interface.";
+    }
+
+    leaf subinterface {
+      type leafref {
+        path "/oc-if:interfaces/" +
+          "oc-if:interface[oc-if:name=current()/../interface]/" +
+          "oc-if:subinterfaces/oc-if:subinterface/oc-if:index";
+      }
+      description
+        "Reference to a subinterface -- this requires the base
+        interface to be specified using the interface leaf in
+        this container.  If only a reference to a base interface
+        is requuired, this leaf should not be set.";
+    }
+  }
+
+  grouping interface-ref-state-container {
+    description
+      "Reusable opstate w/container for a reference to an
+      interface or subinterface";
+
+    container state {
+      config false;
+      description
+        "Operational state for interface-ref";
+
+      uses interface-ref-common;
+    }
+  }
+
+  grouping interface-ref {
+    description
+      "Reusable definition for a reference to an interface or
+      subinterface";
+
+    container interface-ref {
+      description
+        "Reference to an interface or subinterface";
+
+      container config {
+        description
+          "Configured reference to interface / subinterface";
+
+        uses interface-ref-common;
+      }
+
+      uses interface-ref-state-container;
+    }
+  }
+
+  grouping interface-ref-state {
+    description
+      "Reusable opstate w/container for a reference to an
+      interface or subinterface";
+
+    container interface-ref {
+      description
+        "Reference to an interface or subinterface";
+
+      uses interface-ref-state-container;
+    }
+  }
+
+
+  grouping interface-common-config {
+    description
+      "Configuration data data nodes common to physical interfaces
+      and subinterfaces";
+
+    leaf name {
+      type string;
+      description
+        "[adapted from IETF interfaces model (RFC 7223)]
+
+        The name of the interface.
+
+        A device MAY restrict the allowed values for this leaf,
+        possibly depending on the type of the interface.
+        For system-controlled interfaces, this leaf is the
+        device-specific name of the interface.  The 'config false'
+        list interfaces/interface[name]/state contains the currently
+        existing interfaces on the device.
+
+        If a client tries to create configuration for a
+        system-controlled interface that is not present in the
+        corresponding state list, the server MAY reject
+        the request if the implementation does not support
+        pre-provisioning of interfaces or if the name refers to
+        an interface that can never exist in the system.  A
+        NETCONF server MUST reply with an rpc-error with the
+        error-tag 'invalid-value' in this case.
+
+        The IETF model in RFC 7223 provides YANG features for the
+        following (i.e., pre-provisioning and arbitrary-names),
+        however they are omitted here:
+
+          If the device supports pre-provisioning of interface
+          configuration, the 'pre-provisioning' feature is
+          advertised.
+
+          If the device allows arbitrarily named user-controlled
+          interfaces, the 'arbitrary-names' feature is advertised.
+
+        When a configured user-controlled interface is created by
+        the system, it is instantiated with the same name in the
+        /interfaces/interface[name]/state list.";
+      reference
+        "RFC 7223: A YANG Data Model for Interface Management";
+    }
+
+    leaf description {
+      type string;
+      description
+        "[adapted from IETF interfaces model (RFC 7223)]
+
+        A textual description of the interface.
+
+        A server implementation MAY map this leaf to the ifAlias
+        MIB object.  Such an implementation needs to use some
+        mechanism to handle the differences in size and characters
+        allowed between this leaf and ifAlias.  The definition of
+        such a mechanism is outside the scope of this document.
+
+        Since ifAlias is defined to be stored in non-volatile
+        storage, the MIB implementation MUST map ifAlias to the
+        value of 'description' in the persistently stored
+        datastore.
+
+        Specifically, if the device supports ':startup', when
+        ifAlias is read the device MUST return the value of
+        'description' in the 'startup' datastore, and when it is
+        written, it MUST be written to the 'running' and 'startup'
+        datastores.  Note that it is up to the implementation to
+
+        decide whether to modify this single leaf in 'startup' or
+        perform an implicit copy-config from 'running' to
+        'startup'.
+
+        If the device does not support ':startup', ifAlias MUST
+        be mapped to the 'description' leaf in the 'running'
+        datastore.";
+      reference
+        "RFC 2863: The Interfaces Group MIB - ifAlias";
+    }
+
+    leaf enabled {
+      type boolean;
+      default "true";
+      description
+        "[adapted from IETF interfaces model (RFC 7223)]
+
+        This leaf contains the configured, desired state of the
+        interface.
+
+        Systems that implement the IF-MIB use the value of this
+        leaf in the 'running' datastore to set
+        IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
+        has been initialized, as described in RFC 2863.
+
+        Changes in this leaf in the 'running' datastore are
+        reflected in ifAdminStatus, but if ifAdminStatus is
+        changed over SNMP, this leaf is not affected.";
+      reference
+        "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+    }
+
+  }
+
+  grouping interface-phys-config {
+    description
+      "Configuration data for physical interfaces";
+
+    leaf type {
+      type identityref {
+        base ietf-if:interface-type;
+      }
+      mandatory true;
+      description
+        "[adapted from IETF interfaces model (RFC 7223)]
+
+        The type of the interface.
+
+        When an interface entry is created, a server MAY
+        initialize the type leaf with a valid value, e.g., if it
+        is possible to derive the type from the name of the
+        interface.
+
+        If a client tries to set the type of an interface to a
+        value that can never be used by the system, e.g., if the
+        type is not supported or if the type does not match the
+        name of the interface, the server MUST reject the request.
+        A NETCONF server MUST reply with an rpc-error with the
+        error-tag 'invalid-value' in this case.";
+      reference
+        "RFC 2863: The Interfaces Group MIB - ifType";
+    }
+
+    leaf mtu {
+      type uint16;
+      description
+        "Set the max transmission unit size in octets
+        for the physical interface.  If this is not set, the mtu is
+        set to the operational default -- e.g., 1514 bytes on an
+        Ethernet interface.";
+    }
+
+    uses interface-common-config;
+  }
+
+  grouping interface-phys-holdtime-config {
+    description
+      "Configuration data for interface hold-time settings --
+      applies to physical interfaces.";
+
+    leaf up {
+      type uint32;
+      units milliseconds;
+      default 0;
+      description
+        "Dampens advertisement when the interface
+        transitions from down to up.  A zero value means dampening
+        is turned off, i.e., immediate notification.";
+    }
+
+    leaf down {
+      type uint32;
+      units milliseconds;
+      default 0;
+      description
+        "Dampens advertisement when the interface transitions from
+        up to down.  A zero value means dampening is turned off,
+        i.e., immediate notification.";
+    }
+  }
+
+  grouping interface-phys-holdtime-state {
+    description
+      "Operational state data for interface hold-time.";
+  }
+
+  grouping interface-phys-holdtime-top {
+    description
+      "Top-level grouping for setting link transition
+      dampening on physical and other types of interfaces.";
+
+    container hold-time {
+      description
+        "Top-level container for hold-time settings to enable
+        dampening advertisements of interface transitions.";
+
+      container config {
+        description
+          "Configuration data for interface hold-time settings.";
+
+        uses interface-phys-holdtime-config;
+      }
+
+      container state {
+
+        config false;
+
+        description
+          "Operational state data for interface hold-time.";
+
+        uses interface-phys-holdtime-config;
+        uses interface-phys-holdtime-state;
+      }
+    }
+  }
+
+  grouping interface-common-state {
+    description
+      "Operational state data (in addition to intended configuration)
+      at the global level for this interface";
+
+    leaf ifindex {
+      type uint32;
+      description
+        "System assigned number for each interface.  Corresponds to
+        ifIndex object in SNMP Interface MIB";
+      reference
+        "RFC 2863 - The Interfaces Group MIB";
+    }
+
+    leaf admin-status {
+      type enumeration {
+        enum UP {
+          description
+            "Ready to pass packets.";
+        }
+        enum DOWN {
+          description
+            "Not ready to pass packets and not in some test mode.";
+        }
+        enum TESTING {
+          //TODO: This is generally not supported as a configured
+          //admin state, though it's in the standard interfaces MIB.
+          //Consider removing it.
+          description
+            "In some test mode.";
+        }
+      }
+      //TODO:consider converting to an identity to have the
+      //flexibility to remove some values defined by RFC 7223 that
+      //are not used or not implemented consistently.
+      mandatory true;
+      description
+        "[adapted from IETF interfaces model (RFC 7223)]
+
+        The desired state of the interface.  In RFC 7223 this leaf
+        has the same read semantics as ifAdminStatus.  Here, it
+        reflects the administrative state as set by enabling or
+        disabling the interface.";
+      reference
+        "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+    }
+
+    leaf oper-status {
+      type enumeration {
+        enum UP {
+          value 1;
+          description
+            "Ready to pass packets.";
+        }
+        enum DOWN {
+          value 2;
+          description
+            "The interface does not pass any packets.";
+        }
+        enum TESTING {
+          value 3;
+          description
+            "In some test mode.  No operational packets can
+             be passed.";
+        }
+        enum UNKNOWN {
+          value 4;
+          description
+            "Status cannot be determined for some reason.";
+        }
+        enum DORMANT {
+          value 5;
+          description
+            "Waiting for some external event.";
+        }
+        enum NOT_PRESENT {
+          value 6;
+          description
+            "Some component (typically hardware) is missing.";
+        }
+        enum LOWER_LAYER_DOWN {
+          value 7;
+          description
+            "Down due to state of lower-layer interface(s).";
+        }
+      }
+      //TODO:consider converting to an identity to have the
+      //flexibility to remove some values defined by RFC 7223 that
+      //are not used or not implemented consistently.
+      mandatory true;
+      description
+        "[adapted from IETF interfaces model (RFC 7223)]
+
+        The current operational state of the interface.
+
+         This leaf has the same semantics as ifOperStatus.";
+      reference
+        "RFC 2863: The Interfaces Group MIB - ifOperStatus";
+    }
+
+    leaf last-change {
+      type yang:timeticks;
+      description
+        "Date and time of the last state change of the interface
+        (e.g., up-to-down transition).   This corresponds to the
+        ifLastChange object in the standard interface MIB.";
+      reference
+        "RFC 2863: The Interfaces Group MIB - ifLastChange";
+    }
+
+  }
+
+
+  grouping interface-counters-state {
+    description
+      "Operational state representing interface counters
+      and statistics.  Some of these are adapted from RFC 7223";
+
+      //TODO: we may need to break this list of counters into those
+      //that would appear for physical vs. subinterface or logical
+      //interfaces.  For now, just replicating the full stats
+      //grouping to both interface and subinterface.
+
+    container counters {
+      description
+        "A collection of interface-related statistics objects.";
+
+      reference
+        "RFC 7223 - A YANG Data Model for Interface
+        Management";
+
+      leaf in-octets {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+
+          The total number of octets received on the interface,
+          including framing characters.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+      }
+
+      leaf in-unicast-pkts {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+
+          The number of packets, delivered by this sub-layer to a
+          higher (sub-)layer, that were not addressed to a
+          multicast or broadcast address at this sub-layer.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+      }
+
+      leaf in-broadcast-pkts {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+
+          The number of packets, delivered by this sub-layer to a
+          higher (sub-)layer, that were addressed to a broadcast
+          address at this sub-layer.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifHCInBroadcastPkts";
+      }
+
+      leaf in-multicast-pkts {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+
+
+          The number of packets, delivered by this sub-layer to a
+          higher (sub-)layer, that were addressed to a multicast
+          address at this sub-layer.  For a MAC-layer protocol,
+          this includes both Group and Functional addresses.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifHCInMulticastPkts";
+      }
+
+      leaf in-discards {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          The number of inbound packets that were chosen to be
+          discarded even though no errors had been detected to
+          prevent their being deliverable to a higher-layer
+          protocol.  One possible reason for discarding such a
+          packet could be to free up buffer space.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+
+
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+      }
+
+      leaf in-errors {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          For packet-oriented interfaces, the number of inbound
+          packets that contained errors preventing them from being
+          deliverable to a higher-layer protocol.  For character-
+          oriented or fixed-length interfaces, the number of
+          inbound transmission units that contained errors
+          preventing them from being deliverable to a higher-layer
+          protocol.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifInErrors";
+      }
+
+      leaf in-unknown-protos {
+        type yang:counter32;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          For packet-oriented interfaces, the number of packets
+          received via the interface that were discarded because
+          of an unknown or unsupported protocol.  For
+          character-oriented or fixed-length interfaces that
+          support protocol multiplexing, the number of
+          transmission units received via the interface that were
+          discarded because of an unknown or unsupported protocol.
+          For any interface that does not support protocol
+          multiplexing, this counter is not present.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+      }
+
+      leaf out-octets {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          The total number of octets transmitted out of the
+          interface, including framing characters.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+      }
+
+      leaf out-unicast-pkts {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+
+          The total number of packets that higher-level protocols
+          requested be transmitted, and that were not addressed
+          to a multicast or broadcast address at this sub-layer,
+          including those that were discarded or not sent.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+      }
+
+      leaf out-broadcast-pkts {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+
+          The total number of packets that higher-level protocols
+          requested be transmitted, and that were addressed to a
+          broadcast address at this sub-layer, including those
+          that were discarded or not sent.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifHCOutBroadcastPkts";
+      }
+
+
+      leaf out-multicast-pkts {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          The total number of packets that higher-level protocols
+          requested be transmitted, and that were addressed to a
+          multicast address at this sub-layer, including those
+          that were discarded or not sent.  For a MAC-layer
+          protocol, this includes both Group and Functional
+          addresses.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifHCOutMulticastPkts";
+      }
+
+      leaf out-discards {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          The number of outbound packets that were chosen to be
+          discarded even though no errors had been detected to
+          prevent their being transmitted.  One possible reason
+          for discarding such a packet could be to free up buffer
+          space.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+      }
+
+      leaf out-errors {
+        type yang:counter64;
+        description
+          "[adapted from IETF interfaces model (RFC 7223)]
+          Changed the counter type to counter64.
+
+          For packet-oriented interfaces, the number of outbound
+          packets that could not be transmitted because of errors.
+          For character-oriented or fixed-length interfaces, the
+          number of outbound transmission units that could not be
+          transmitted because of errors.
+
+          Discontinuities in the value of this counter can occur
+          at re-initialization of the management system, and at
+          other times as indicated by the value of
+          'discontinuity-time'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+      }
+
+      leaf last-clear {
+        type yang:date-and-time;
+        description
+          "Indicates the last time the interface counters were
+          cleared.";
+      }
+    }
+  }
+
+  // data definition statements
+
+  grouping sub-unnumbered-config {
+    description
+      "Configuration data for unnumbered subinterfaces";
+
+    leaf enabled {
+      type boolean;
+      default false;
+      description
+        "Indicates that the subinterface is unnumbered.  By default
+        the subinterface is numbered, i.e., expected to have an
+        IP address configuration.";
+    }
+  }
+
+  grouping sub-unnumbered-state {
+    description
+      "Operational state data unnumbered subinterfaces";
+  }
+
+  grouping sub-unnumbered-top {
+    description
+      "Top-level grouping unnumbered subinterfaces";
+
+    container unnumbered {
+      description
+        "Top-level container for setting unnumbered interfaces.
+        Includes reference the interface that provides the
+        address information";
+
+      container config {
+        description
+          "Configuration data for unnumbered interface";
+
+        uses sub-unnumbered-config;
+      }
+
+      container state {
+
+        config false;
+
+        description
+          "Operational state data for unnumbered interfaces";
+
+        uses sub-unnumbered-config;
+        uses sub-unnumbered-state;
+      }
+
+      uses oc-if:interface-ref;
+    }
+  }
+
+  grouping subinterfaces-config {
+    description
+      "Configuration data for subinterfaces";
+
+    leaf index {
+      type uint32;
+      default 0;
+      description
+        "The index of the subinterface, or logical interface number.
+        On systems with no support for subinterfaces, or not using
+        subinterfaces, this value should default to 0, i.e., the
+        default subinterface.";
+    }
+
+    uses interface-common-config;
+
+  }
+
+  grouping subinterfaces-state {
+    description
+      "Operational state data for subinterfaces";
+
+    uses interface-common-state;
+    uses interface-counters-state;
+  }
+
+  grouping subinterfaces-top {
+    description
+      "Subinterface data for logical interfaces associated with a
+      given interface";
+
+    container subinterfaces {
+      description
+        "Enclosing container for the list of subinterfaces associated
+        with a physical interface";
+
+      list subinterface {
+        key "index";
+
+        description
+          "The list of subinterfaces (logical interfaces) associated
+          with a physical interface";
+
+        leaf index {
+          type leafref {
+            path "../config/index";
+          }
+          description
+            "The index number of the subinterface -- used to address
+            the logical interface";
+        }
+
+        container config {
+          description
+            "Configurable items at the subinterface level";
+
+          uses subinterfaces-config;
+        }
+
+        container state {
+
+          config false;
+          description
+            "Operational state data for logical interfaces";
+
+          uses subinterfaces-config;
+          uses subinterfaces-state;
+        }
+      }
+    }
+  }
+
+  grouping interfaces-top {
+    description
+      "Top-level grouping for interface configuration and
+      operational state data";
+
+    container interfaces {
+      description
+        "Top level container for interfaces, including configuration
+        and state data.";
+
+
+      list interface {
+        key "name";
+
+        description
+          "The list of named interfaces on the device.";
+
+        leaf name {
+          type leafref {
+            path "../config/name";
+          }
+          description
+            "References the configured name of the interface";
+            //TODO: need to consider whether this should actually
+            //reference the name in the state subtree, which
+            //presumably would be the system-assigned name, or the
+            //configured name.  Points to the config/name now
+            //because of YANG 1.0 limitation that the list
+            //key must have the same "config" as the list, and
+            //also can't point to a non-config node.
+        }
+
+        container config {
+          description
+            "Configurable items at the global, physical interface
+            level";
+
+          uses interface-phys-config;
+        }
+
+        container state {
+
+          config false;
+          description
+            "Operational state data at the global interface level";
+
+          uses interface-phys-config;
+          uses interface-common-state;
+          uses interface-counters-state;
+        }
+
+        uses interface-phys-holdtime-top;
+        uses subinterfaces-top;
+      }
+    }
+  }
+
+  uses interfaces-top;
+
+
+}
diff --git a/tests/utests/netconf/yang/openconfig-local-routing.yang b/tests/utests/netconf/yang/openconfig-local-routing.yang
new file mode 100644
index 0000000..556bbee
--- /dev/null
+++ b/tests/utests/netconf/yang/openconfig-local-routing.yang
@@ -0,0 +1,402 @@
+module openconfig-local-routing {
+
+  yang-version "1";
+
+  // namespace
+  namespace "http://openconfig.net/yang/local-routing";
+
+  prefix "oc-loc-rt";
+
+  // import some basic types
+  import ietf-inet-types { prefix inet; }
+  import openconfig-policy-types { prefix oc-pt; }
+  import openconfig-extensions { prefix oc-ext; }
+  import openconfig-interfaces { prefix oc-if; }
+
+  // meta
+  organization "OpenConfig working group";
+
+  contact
+    "OpenConfig working group
+    www.openconfig.net";
+
+  description
+    "This module describes configuration and operational state data
+    for routes that are locally generated, i.e., not created by
+    dynamic routing protocols.  These include static routes, locally
+    created aggregate routes for reducing the number of constituent
+    routes that must be advertised, summary routes for IGPs, etc.
+
+    This model expresses locally generated routes as generically as
+    possible, avoiding configuration of protocol-specific attributes
+    at the time of route creation.  This is primarily to avoid
+    assumptions about how underlying router implementations handle
+    route attributes in various routing table data structures they
+    maintain.  Hence, the definition of locally generated routes
+    essentially creates 'bare' routes that do not have any protocol-
+    specific attributes.
+
+    When protocol-specific attributes must be attached to a route
+    (e.g., communities on a locally defined route meant to be
+    advertised via BGP), the attributes should be attached via a
+    protocol-specific policy after importing the route into the
+    protocol for distribution (again via routing policy).";
+
+  oc-ext:openconfig-version "1.0.0";
+
+  revision "2016-05-11" {
+    description
+      "OpenConfig public release";
+    reference "1.0.0";
+  }
+
+
+  // identity statements
+
+  identity LOCAL_DEFINED_NEXT_HOP {
+    description
+      "A base identity type of local defined next-hops";
+  }
+
+  identity DROP {
+    base LOCAL_DEFINED_NEXT_HOP;
+    description
+      "Discard traffic for the corresponding destination";
+  }
+
+  identity LOCAL_LINK {
+    base LOCAL_DEFINED_NEXT_HOP;
+    description
+      "Treat traffic towards addresses within the specified
+      next-hop prefix as though they are connected to a local
+      link. When the LOCAL_LINK next-hop type is specified,
+      an interface must also be specified such that
+      the local system can determine which link to trigger
+      link-layer address discovery against";
+  }
+
+  // typedef statements
+
+  typedef local-defined-next-hop {
+    type identityref {
+      base LOCAL_DEFINED_NEXT_HOP;
+    }
+    description
+      "Pre-defined next-hop designation for locally generated
+      routes";
+  }
+
+  // grouping statements
+
+  grouping local-generic-settings {
+    description
+      "Generic options that can be set on local routes When
+      they are defined";
+
+    leaf set-tag {
+      type oc-pt:tag-type;
+      description
+        "Set a generic tag value on the route. This tag can be
+        used for filtering routes that are distributed to other
+        routing protocols.";
+    }
+  }
+
+  grouping local-static-config {
+    description
+      "Configuration data for static routes.";
+
+    leaf prefix {
+      type inet:ip-prefix;
+      description
+        "Destination prefix for the static route, either IPv4 or
+        IPv6.";
+    }
+
+    uses local-generic-settings;
+  }
+
+  grouping local-static-state {
+    description
+      "Operational state data for static routes";
+  }
+
+
+  grouping local-static-nexthop-config {
+    description
+      "Configuration parameters related to each next-hop entry
+      specified for a static route";
+
+    leaf index {
+      type string;
+      description
+        "An user-specified identifier utilised to uniquely reference
+        the next-hop entry in the next-hop list. The value of this
+        index has no semantic meaning other than for referencing
+        the entry.";
+    }
+
+    leaf next-hop {
+      type union {
+        type inet:ip-address-no-zone;
+        type local-defined-next-hop;
+      }
+      description
+        "The next-hop that is to be used for the static route
+        - this may be specified as an IP address, an interface
+        or a pre-defined next-hop type - for instance, DROP or
+        LOCAL_LINK. When this leaf is not set, and the interface-ref
+        value is specified for the next-hop, then the system should
+        treat the prefix as though it is directly connected to the
+        interface.";
+    }
+
+    leaf metric {
+      type uint32;
+      description
+        "A metric which is utilised to specify the preference of
+        the next-hop entry when it is injected into the RIB. The
+        lower the metric, the more preferable the prefix is. When
+        this value is not specified the metric is inherited from
+        the default metric utilised for static routes within the
+        network instance that the static routes are being
+        instantiated. When multiple next-hops are specified for a
+        static route, the metric is utilised to determine which of
+        the next-hops is to be installed in the RIB. When multiple
+        next-hops have the same metric (be it specified, or simply
+        the default) then these next-hops should all be installed
+        in the RIB";
+    }
+
+    leaf recurse {
+      type boolean;
+      default false;
+      description
+        "Determines whether the next-hop should be allowed to
+        be looked up recursively - i.e., via a RIB entry which has
+        been installed by a routing protocol, or another static route
+        - rather than needing to be connected directly to an
+        interface of the local system within the current network
+        instance. When the interface reference specified within the
+        next-hop entry is set (i.e., is not null) then forwarding is
+        restricted to being via the interface specified - and
+        recursion is hence disabled.";
+    }
+  }
+
+  grouping local-static-nexthop-state {
+    description
+      "Operational state parameters relating to a next-hop entry
+      for a static route";
+  }
+
+
+  grouping local-static-top {
+    description
+      "Top-level grouping for the list of static route definitions";
+
+    container static-routes {
+      description
+        "Enclosing container for the list of static routes";
+
+      list static {
+        key prefix;
+        description
+          "List of locally configured static routes";
+
+        leaf prefix {
+          type leafref {
+            path "../config/prefix";
+          }
+          description
+            "Reference to the destination prefix list key.";
+        }
+
+        container config {
+          description
+            "Configuration data for static routes";
+
+          uses local-static-config;
+        }
+
+        container state {
+
+          config false;
+
+          description
+            "Operational state data for static routes";
+
+          uses local-static-config;
+          uses local-static-state;
+        }
+
+        container next-hops {
+          description
+            "Configuration and state parameters relating to the
+            next-hops that are to be utilised for the static
+            route being specified";
+
+          list next-hop {
+            key index;
+
+            description
+              "A list of next-hops to be utilised for the static
+              route being specified.";
+
+            leaf index {
+              type leafref {
+                path "../config/index";
+              }
+              description
+                "A reference to the index of the current next-hop.
+                The index is intended to be a user-specified value
+                which can be used to reference the next-hop in
+                question, without any other semantics being
+                assigned to it.";
+            }
+
+            container config {
+              description
+                "Configuration parameters relating to the next-hop
+                entry";
+
+              uses local-static-nexthop-config;
+            }
+
+            container state {
+              config false;
+              description
+                "Operational state parameters relating to the
+                next-hop entry";
+
+              uses local-static-nexthop-config;
+              uses local-static-nexthop-state;
+            }
+
+            uses oc-if:interface-ref;
+          }
+        }
+      }
+    }
+  }
+
+  grouping local-aggregate-config {
+    description
+      "Configuration data for aggregate routes";
+
+    leaf prefix {
+      type inet:ip-prefix;
+      description
+        "Aggregate prefix to be advertised";
+    }
+
+    leaf discard {
+      type boolean;
+      default false;
+      description
+        "When true, install the aggregate route with a discard
+        next-hop -- traffic destined to the aggregate will be
+        discarded with no ICMP message generated.  When false,
+        traffic destined to an aggregate address when no
+        constituent routes are present will generate an ICMP
+        unreachable message.";
+    }
+
+    uses local-generic-settings;
+
+  }
+
+  grouping local-aggregate-state {
+    description
+      "Operational state data for local aggregate advertisement
+      definitions";
+  }
+
+  grouping local-aggregate-top {
+    description
+      "Top-level grouping for local aggregates";
+
+    container local-aggregates {
+      description
+        "Enclosing container for locally-defined aggregate
+        routes";
+
+      list aggregate {
+        key prefix;
+        description
+          "List of aggregates";
+
+        leaf prefix {
+          type leafref {
+            path "../config/prefix";
+          }
+          description
+            "Reference to the configured prefix for this aggregate";
+        }
+
+        container config {
+          description
+            "Configuration data for aggregate advertisements";
+
+          uses local-aggregate-config;
+        }
+
+        container state {
+
+          config false;
+
+          description
+            "Operational state data for aggregate
+            advertisements";
+
+          uses local-aggregate-config;
+          uses local-aggregate-state;
+        }
+      }
+    }
+  }
+
+  grouping local-routes-config {
+    description
+      "Configuration data for locally defined routes";
+  }
+
+  grouping local-routes-state {
+    description
+      "Operational state data for locally defined routes";
+  }
+
+  grouping local-routes-top {
+    description
+      "Top-level grouping for local routes";
+
+    container local-routes {
+      description
+        "Top-level container for local routes";
+
+      container config {
+        description
+          "Configuration data for locally defined routes";
+
+        uses local-routes-config;
+      }
+
+      container state {
+
+        config false;
+
+        description
+          "Operational state data for locally defined routes";
+
+        uses local-routes-config;
+        uses local-routes-state;
+      }
+
+      uses local-static-top;
+      uses local-aggregate-top;
+    }
+  }
+
+  uses local-routes-top;
+
+}
diff --git a/tests/utests/netconf/yang/openconfig-policy-types.yang b/tests/utests/netconf/yang/openconfig-policy-types.yang
new file mode 100644
index 0000000..8e1fe36
--- /dev/null
+++ b/tests/utests/netconf/yang/openconfig-policy-types.yang
@@ -0,0 +1,178 @@
+module openconfig-policy-types {
+
+  yang-version "1";
+
+  // namespace
+  namespace "http://openconfig.net/yang/policy-types";
+
+  prefix "oc-pol-types";
+
+  // import some basic types
+  import ietf-yang-types { prefix yang; }
+  import openconfig-extensions { prefix oc-ext; }
+
+  // meta
+  organization
+    "OpenConfig working group";
+
+  contact
+    "OpenConfig working group
+    netopenconfig@googlegroups.com";
+
+  description
+    "This module contains general data definitions for use in routing
+    policy.  It can be imported by modules that contain protocol-
+    specific policy conditions and actions.";
+
+  oc-ext:openconfig-version "2.0.1";
+
+  revision "2016-05-12" {
+    description
+      "OpenConfig public release";
+    reference "2.0.1";
+  }
+
+  // identity statements
+
+  identity ATTRIBUTE_COMPARISON {
+    description
+      "base type for supported comparison operators on route
+      attributes";
+  }
+
+  identity ATTRIBUTE_EQ {
+    base ATTRIBUTE_COMPARISON;
+    description "== comparison";
+  }
+
+  identity ATTRIBUTE_GE {
+    base ATTRIBUTE_COMPARISON;
+    description ">= comparison";
+  }
+
+  identity ATTRIBUTE_LE {
+    base ATTRIBUTE_COMPARISON;
+    description "<= comparison";
+  }
+
+  typedef match-set-options-type {
+    type enumeration {
+      enum ANY {
+        description "match is true if given value matches any member
+        of the defined set";
+      }
+      enum ALL {
+        description "match is true if given value matches all
+        members of the defined set";
+      }
+      enum INVERT {
+        description "match is true if given value does not match any
+        member of the defined set";
+      }
+    }
+    default ANY;
+    description
+      "Options that govern the behavior of a match statement.  The
+      default behavior is ANY, i.e., the given value matches any
+      of the members of the defined set";
+  }
+
+  typedef match-set-options-restricted-type {
+    type enumeration {
+      enum ANY {
+        description "match is true if given value matches any member
+        of the defined set";
+      }
+      enum INVERT {
+        description "match is true if given value does not match any
+        member of the defined set";
+      }
+    }
+    default ANY;
+    description
+      "Options that govern the behavior of a match statement.  The
+      default behavior is ANY, i.e., the given value matches any
+      of the members of the defined set.  Note this type is a
+      restricted version of the match-set-options-type.";
+      //TODO: restriction on enumerated types is only allowed in
+      //YANG 1.1.  Until then, we will require this additional type
+  }
+
+  grouping attribute-compare-operators {
+    description "common definitions for comparison operations in
+    condition statements";
+
+    leaf operator {
+        type identityref {
+          base ATTRIBUTE_COMPARISON;
+        }
+        description
+          "type of comparison to be performed";
+      }
+
+    leaf value {
+      type uint32;
+      description
+        "value to compare with the community count";
+    }
+  }
+
+  typedef tag-type {
+    type union {
+      type uint32;
+      type yang:hex-string;
+    }
+    description "type for expressing route tags on a local system,
+    including IS-IS and OSPF; may be expressed as either decimal or
+    hexidecimal integer";
+    reference
+      "RFC 2178 OSPF Version 2
+      RFC 5130 A Policy Control Mechanism in IS-IS Using
+      Administrative Tags";
+  }
+
+  identity INSTALL_PROTOCOL_TYPE {
+    description
+      "Base type for protocols which can install prefixes into the
+      RIB";
+  }
+
+  identity BGP {
+    base INSTALL_PROTOCOL_TYPE;
+    description "BGP";
+    reference "RFC 4271";
+  }
+
+  identity ISIS {
+    base INSTALL_PROTOCOL_TYPE;
+    description "IS-IS";
+    reference "ISO/IEC 10589";
+  }
+
+  identity OSPF {
+    base INSTALL_PROTOCOL_TYPE;
+    description "OSPFv2";
+    reference "RFC 2328";
+  }
+
+  identity OSPF3 {
+    base INSTALL_PROTOCOL_TYPE;
+    description "OSPFv3";
+    reference "RFC 5340";
+  }
+
+  identity STATIC {
+    base INSTALL_PROTOCOL_TYPE;
+    description "Locally-installed static route";
+  }
+
+  identity DIRECTLY_CONNECTED {
+    base INSTALL_PROTOCOL_TYPE;
+    description "A directly connected route";
+  }
+
+  identity LOCAL_AGGREGATE {
+    base INSTALL_PROTOCOL_TYPE;
+    description "Locally defined aggregate route";
+  }
+}
diff --git a/tests/utests/netconf/yang/xos-accessibility.yang b/tests/utests/netconf/yang/xos-accessibility.yang
new file mode 100644
index 0000000..9cebf1b
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-accessibility.yang
@@ -0,0 +1,462 @@
+module xos-unreconciled-models {
+  namespace "urn:ietf:params:xml:ns:yang:xos-incomplete";
+  prefix xacc;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import xos-types       { prefix xtype; }
+
+  organization
+    "Open Networking Lab (XOS) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+    "This module contains a collection of core models for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-13 {
+    description "Initial revision.";
+  }
+
+  /* Future Consideration
+  typedef image {
+    type unique-identifier;
+  }
+  typedef controller-network {
+    type unique-identifier;
+  }
+  typedef site {
+    type unique-identifier;
+  }
+  typedef tenant-root-role {
+    type unique-identifier;
+  }
+  typedef slice-role {
+    type unique-identifier;
+  }
+  typedef site-deployment {
+    type unique-identifier;
+  }
+  typedef tenant-privilege {
+    type unique-identifier;
+  }
+  typedef tag {
+    type unique-identifier;
+  }
+  typedef user-credential {
+    type unique-identifier;
+  }
+  typedef invoice {
+    type unique-identifier;
+  }
+  typedef slice-privilege {
+    type unique-identifier;
+  }
+  typedef flavor {
+    type unique-identifier;
+  }
+  typedef port {
+    type unique-identifier;
+  }
+  typedef service-role {
+    type unique-identifier;
+  }
+  typedef controller-site {
+    type unique-identifier;
+  }
+  typedef controller-slice {
+    type unique-identifier;
+  }
+  typedef tenant-role {
+    type unique-identifier;
+  }
+  typedef slice {
+    type unique-identifier;
+  }
+  typedef network {
+    type unique-identifier;
+  }
+  typedef controller-role {
+    type unique-identifier;
+  }
+  typedef diag {
+    type unique-identifier;
+  }
+  typedef service-class {
+    type unique-identifier;
+  }
+  typedef tenant-attribute {
+    type unique-identifier;
+  }
+  typedef site-role {
+    type unique-identifier;
+  }
+  typedef subscriber {
+    type unique-identifier;
+  }
+  typedef instance {
+    type unique-identifier;
+  }
+  typedef charge {
+    type unique-identifier;
+  }
+  typedef program {
+    type unique-identifier;
+  }
+  typedef role {
+    type unique-identifier;
+  }
+  typedef usable-object {
+    type unique-identifier;
+  }
+  typedef node-label {
+    type unique-identifier;
+  }
+  typedef slice-credential {
+    type unique-identifier;
+  }
+  typedef node {
+    type unique-identifier;
+  }
+  typedef address-pool {
+    type unique-identifier;
+  }
+  typedef dashboard-view {
+    type unique-identifier;
+  }
+  typedef network-parameter {
+    type unique-identifier;
+  }
+  typedef image-deployments {
+    type unique-identifier;
+  }
+  typedef controller-user {
+    type unique-identifier;
+  }
+  typedef reserved-resource {
+    type unique-identifier;
+  }
+  typedef network-template {
+    type unique-identifier;
+  }
+  typedef controller-dashboard-view {
+    type unique-identifier;
+  }
+  typedef user-dashboard-view {
+    type unique-identifier;
+  }
+  typedef controller {
+    type unique-identifier;
+  }
+  typedef user {
+    type unique-identifier;
+  }
+  typedef deployment {
+    type unique-identifier;
+  }
+  typedef reservation {
+    type unique-identifier;
+  }
+  typedef site-privilege {
+    type unique-identifier;
+  }
+  typedef payment {
+    type unique-identifier;
+  }
+  typedef tenant {
+    type unique-identifier;
+  }
+  typedef network-slice {
+    type unique-identifier;
+  }
+  typedef account {
+    type unique-identifier;
+  }
+  typedef tenant-root {
+    type unique-identifier;
+  }
+  typedef service {
+    type unique-identifier;
+  }
+  typedef controller-slice-privilege {
+    type unique-identifier;
+  }
+  typedef site-credential {
+    type unique-identifier;
+  }
+  typedef deployment-privilege {
+    type unique-identifier;
+  }
+  typedef network-parameter-type {
+    type unique-identifier;
+  }
+  typedef provider {
+    type unique-identifier;
+  }
+  typedef tenant-with-container {
+    type unique-identifier;
+  }
+  typedef deployment-role {
+    type unique-identifier;
+  }
+  typedef project {
+    type unique-identifier;
+  }
+  typedef tenant-root-privilege {
+    type unique-identifier;
+  }
+  typedef slice-tag {
+    type unique-identifier;
+  }
+  typedef coarse-tenant {
+    type unique-identifier;
+  }
+  typedef router {
+    type unique-identifier;
+  }
+  typedef service-resource {
+    type unique-identifier;
+  }
+  typedef service-privilege {
+    type unique-identifier;
+  }
+  */
+  grouping service-class {
+    uses xos-base;
+    
+    leaf description { 
+      type string;
+    }
+    leaf commitment { 
+      type uint32;
+    }
+    leaf membership-fee { 
+      type uint32;
+    }
+    leaf membership-fee-months { 
+      type uint32;
+    }
+    leaf upgrade-requires-approval { 
+      type boolean;
+    }
+  }
+  grouping invoice {
+    uses xos-base;
+    leaf date { 
+      type xtype:datetime;
+    }
+    leaf account { 
+      type xtype:account; 
+    }
+  }
+
+  grouping charge {
+    uses xos-base;
+    leaf account { 
+      type xtype:account; 
+    }
+    leaf slice { 
+      type xtype:slice; 
+    }
+    leaf kind { 
+      type string;
+    }
+    leaf state { 
+      type string;
+    }
+    leaf date { 
+      type xtype:datetime;
+    }
+    leaf object { 
+      type xtype:object; 
+    }
+    leaf amount { 
+      type decimal64;
+    }
+    leaf core-hours { 
+      type decimal64;
+    }
+    leaf invoice { 
+      type xtype:invoice; 
+    }
+  }
+
+  grouping role {
+    uses xos-base;
+    leaf role-type { 
+      type string;
+    }
+    leaf role { 
+      type string;
+    }
+    leaf description { 
+      type string;
+    }
+    leaf content-type { 
+      type xtype:content-type; 
+    }
+  }
+
+  grouping dashboard-view {
+    uses xos-base;
+    leaf url { 
+      type string;
+    }
+    leaf enabled { 
+      type boolean;
+    }
+  }
+
+  grouping controller-dashboard-view {
+    uses xos-base;
+    leaf controller { 
+      type xtype:controller; 
+    }
+    leaf dashboardView { 
+      type xtype:dashboardView; 
+    }
+    leaf enabled { 
+      type boolean;
+    }
+    leaf url { 
+      type string;
+    }
+  }
+
+  grouping user-dashboard-view {
+    uses xos-base;
+    leaf user { 
+      type xtype:user; 
+    }
+    leaf dashboardView { 
+      type xtype:dashboardView; 
+    }
+    leaf order { 
+      type uint32;
+    }
+  }
+  grouping service-privilege {
+    uses xos-base;
+    leaf user { 
+      type xtype:user; 
+    }
+    leaf service { 
+      type xtype:service; 
+    }
+    leaf role { 
+      type xtype:role; 
+    }
+  }
+
+  grouping payment {
+    uses xos-base;
+    leaf account { 
+      type xtype:account; 
+    }
+    leaf amount { 
+      type decimal64;
+    }
+    leaf date { 
+      type xtype:datetime;
+    }
+  }
+  
+  grouping account {
+    uses xos-base;
+    leaf site { 
+      type xtype:site; 
+    }
+  }
+
+  grouping service-resource {
+    uses xos-base;
+    leaf service-class { 
+      type xtype:service-class; 
+    }
+    
+    leaf max-units-deployment { 
+      type uint32;
+    }
+
+    leaf max-units-node { 
+      type uint32;
+    }
+
+    leaf max-duration { 
+      type uint32;
+    }
+
+    leaf bucket-in-rate { 
+      type uint32;
+    }
+
+    leaf bucket-max-size { 
+      type uint32;
+    }
+
+    leaf cost { 
+      type uint32;
+    }
+
+    leaf calendar-reservable { 
+      type boolean;
+    }
+  }
+
+  grouping diag {
+    uses xos-base;
+    
+  }
+
+  grouping program {
+    uses xos-base;
+    leaf description { 
+      type string;
+    }
+
+    leaf kind { 
+      type string;
+    }
+
+    leaf command { 
+      type string;
+    }
+
+    leaf owner { 
+      type xtype:owner; 
+    }
+
+    leaf contents { 
+      type string;
+    }
+
+    leaf output { 
+      type string;
+    }
+
+    leaf messages { 
+      type string;
+    }
+
+    leaf status { 
+      type string;
+    }
+  }
+
+  grouping usable-object {
+    uses xos-base;
+  }
+
+}
diff --git a/tests/utests/netconf/yang/xos-controller.yang b/tests/utests/netconf/yang/xos-controller.yang
new file mode 100644
index 0000000..40ce8a6
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-controller.yang
@@ -0,0 +1,225 @@
+module xos-controller {
+  namespace "urn:ietf:params:xml:ns:yang:xos-controller";
+  prefix xos;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import iana-crypt-hash { prefix ianach; }
+  import yang-meta-types { prefix meta; }
+  import xos-types       { prefix xtype; }
+
+  organization
+   "Open Networking Lab / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+   "This module contains a collection of core models for XOS.  The core
+    models represent primary first-order entities such as Tenant,
+    Subscriber, Provider, and Service.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-07-14 {
+    description "Initial revision.";
+  }
+
+  identity xos-tenant {
+    description "Describes the type of tenant within XOS";
+  }
+  identity xos-subscriber {
+    base xos-tenant;
+  }
+  identity xos-provider {
+    base xos-tenant;
+  }
+  identity xos-service {
+    base xos-provider;
+  }
+  
+  feature synchronizer {
+    description
+      "Enables configuration synchronization to the distributed store.";
+  }
+  /*
+   * Groupings
+   */
+  grouping record {
+    description "Synchronizer-specific properties for model entities";
+    
+    leaf created { type yang:date-and-time; }
+    leaf updated { type yang:date-and-time; }
+    leaf enacted { type yang:date-and-time; }
+    leaf policed { type yang:date-and-time; }
+        
+    leaf writable { type boolean; default true; }
+    leaf locked   { type boolean; default false; }
+    leaf deleted  { type boolean; default false; }
+      
+    leaf dirty {
+      config false;
+      type boolean;
+      default false;
+    }
+      
+    container sync {
+      anydata register {
+        description "scratchpad used by the Observer";
+      }
+      leaf progress {
+        type enumeration {
+          enum provisioning {
+            value 0;
+            description "Provisioning in progress";
+          }
+        }
+      }
+      leaf disabled { type boolean; default false; }
+      leaf enforced { type boolean; default true; }
+
+      list policy {
+        // TODO: how are policy defined/enforced?
+      }
+    }
+    action diff {
+      description "retrieve diff of model state if dirty";
+    }
+    action save {
+      description "trigger save into data store via synchronizer";
+    }
+  }
+  grouping credentials-list {
+    list credential {
+      key token;
+      leaf token {
+        type string;
+      }
+      leaf password {
+        type meta:password;
+      }
+      leaf user {
+        type xtype:unique-identifier;
+      }
+      leaf role {
+        type xtype:access-role;
+      }
+    }
+  }
+  grouping parameter {
+    leaf name { type yang:yang-identifier; }
+    leaf value { type string; }
+    leaf content-type { type string; }
+    leaf object-id { type uint32; }
+  }
+  grouping tenant {
+    leaf id {
+      type xtype:unique-identifier;
+      mandatory true;
+    }
+    leaf name { type string { length 0..255; } }
+    leaf kind {
+      config false;
+      type identityref {
+        base xos-tenant;
+      }
+    }
+    leaf description { type meta:description; }
+    leaf enabled { type boolean; default true; }
+    container record {
+      if-feature synchronizer;
+      uses xos:record;
+    }
+  }
+  grouping subscriber {
+    uses xos:tenant {
+      refine kind { default xos-subscriber; }
+    }
+    leaf connectivity {
+      type enumeration {
+        enum public { description "Public"; }
+        enum private { description "Private"; }
+        enum private-unidirectional { description "Private Uni-directional"; }
+        enum na { description "Not Applicable"; }
+      }
+      default na;
+    }
+  }
+  grouping provider {
+    uses xos:tenant {
+      refine kind { default xos-provider; }
+    }
+    uses xos:credentials-list;
+  }
+  grouping service {
+    uses xos:provider {
+      refine 'name' {
+        description "Name of the Service";
+      }
+    }
+    leaf view-url {
+      type inet:uri;
+    }
+    leaf icon-url {
+      type inet:uri;
+    }
+    leaf published {
+      type boolean;
+      default true;
+    }
+    list keypair {
+      description "collection of public/private key pair(s)";
+      // should be a specific typedef for storing this content
+      leaf public  { type string { length 0..1024; } }
+      leaf private { type string { length 0..1024; } }
+    }
+    list attribute {
+      key name;
+      leaf name  { type string { length 0..128; } }
+      leaf value { type string; }
+      status deprecated;
+      reference "XOS: service-specific-attribute";
+      description "backwards-compatible attribute association";
+    }
+    leaf service-specific-id {
+      type xtype:unique-identifier;
+      status deprecated;
+    }
+    list subscriber {
+      description
+        "Each entry represents a subscriber of the service. Each unique service
+         provider should augment this block with service specific
+         attributes.";
+      key id;
+      uses xos:subscriber;
+      notification subscriber-added;
+      notification subscriber-deleted;
+    }
+    // TODO: need to better understand relationship between Service and VTN
+  }
+  /*
+   * Configuration data nodes (main configuration tree for XOS)
+   */
+  container core {
+    description
+      "Primary endpoint for additional core entities to augment";
+    uses xos:provider;
+  }
+  container service {
+    description
+      "Primary endpoint for services to augment";
+  }
+  container tenant {
+    description
+      "Primary endpoint for tenants to augment";
+  }
+}
diff --git a/tests/utests/netconf/yang/xos-core-service.yang b/tests/utests/netconf/yang/xos-core-service.yang
new file mode 100644
index 0000000..3923221
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-core-service.yang
@@ -0,0 +1,120 @@
+module xos-core-service {
+  namespace "urn:xos:core:service";
+  prefix xos-cs;
+
+  import complex-types { prefix ct; }
+
+  revision 2015-10-01 {
+    description "Initial revision.";
+  }
+
+  grouping service-attribute {
+    leaf name { type string { length 128; } }
+    leaf value { type string { length 1024; } }
+    leaf service {
+      type instance-identifier { ct:instance-type Service; require-instance true; }
+    }
+  }
+
+  grouping service-role {
+    leaf role {
+      type enumeration {
+        enum "admin";
+        //enum "Admin";
+      }
+    }
+  }
+
+  grouping common-model-attr {
+    leaf kind {
+      type string { length 30; }
+      default "generic";
+    }
+    leaf name { type string { length 255; } }
+  }
+
+  ct:complex-type ServiceElement {
+    ct:abstract true;
+    leaf enabled { type boolean; default true; }
+  }
+  
+  ct:complex-type Service {
+    ct:extends ServiceElement;
+    
+    leaf description {
+      type string { length 255; }
+      description "Description of Service";
+    }
+    leaf published { type boolean; default true; }
+
+    uses common-model-attr {
+      refine kind {
+        description "Kind of Service";
+      }
+      refine name {
+        description "Service Name";
+      }
+    }
+  }
+
+  ct:complex-type User {
+    ct:extends ServiceElement;
+    // TBD - should go to a separate xos-core-user module or such
+  }
+  
+  ct:complex-type ServicePrivilege {
+    key "user-service-role";
+    
+    leaf user {
+      type instance-identifier { ct:instance-type User; require-instance true; }
+    }
+    leaf service {
+      type instance-identifier { ct:instance-type Service; }
+    }
+    uses service-role;
+  }
+
+  ct:complex-type TenantRoot {
+    ct:extends ServiceElement;
+    
+    description
+      "A tenantRoot is one of the things that can sit at the root of a chain
+        of tenancy. This object represents a node.";
+    uses common-model-attr;
+  }
+
+  ct:complex-type ContainerImage {
+    // TBD
+  }
+  
+  ct:complex-type Tenancy {
+    ct:extends ServiceElement;
+    
+    description
+      "A Tenancy describes relationship between a subscriber and a provider";
+    
+    uses common-model-attr;
+
+    leaf provider { type instance-identifer { ct:instance-type Service; } }
+    leaf subscriber {
+      type instance-identifier {
+        ct:instance-type ServiceElement;
+      }
+    }
+
+    // adding stuff from TenantWithContainer here...
+    leaf creator { type instance-identifier { ct:instance-type User; } }
+    leaf image { type instance-identifier { ct:instance-type ContainerImage; } }
+  }
+
+  ct:complex-type Subscriber {
+    ct:extends TenantRoot;
+    refine kind { default "Subscriber"; }
+  }
+
+  ct:complex-type Provider {
+    ct:extends TenantRoot;
+    refine kind { default "Provider"; }
+  }
+  
+}
diff --git a/tests/utests/netconf/yang/xos-openstack.yang b/tests/utests/netconf/yang/xos-openstack.yang
new file mode 100644
index 0000000..3f79fe0
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-openstack.yang
@@ -0,0 +1,190 @@
+module xos-controller {
+  namespace "urn:ietf:params:xml:ns:yang:xos-controller";
+  prefix xcontrol;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import xos-core        { prefix xos; }
+  import xos-types       { prefix xtype; }
+
+  organization
+    "Open Networking Lab (XOS) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+    "This module contains a collection of Controller models for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-23 {
+    description "Initial revision.";
+  }
+
+  grouping controller {
+    uses xos:provider;
+    leaf backend-type { 
+      type string;
+    }
+    leaf version { 
+      type string;
+    }
+    leaf auth-url { 
+      type string;
+    }
+    leaf admin-user { 
+      type string;
+    }
+    leaf admin-password { 
+      type string;
+    }
+    leaf admin-tenant { 
+      type string;
+    }
+    leaf domain { 
+      type string;
+    }
+    container message-queue {
+      leaf rabbit-host { 
+        type string;
+      }
+      leaf rabbit-user { 
+        type string;
+      }
+      leaf rabbit-password { 
+        type string;
+      }
+    }
+    leaf deployment { 
+      type xtype:deployment; 
+    }
+  }
+  grouping controller-site-privilege {
+    uses xos:tenant;
+
+    leaf controller { 
+      type xtype:controller; 
+    }
+
+    leaf site-privilege { 
+      type xtype:site-privilege; 
+    }
+    
+    container synchronizer {
+      if-feature xos:synchronizer;
+      leaf role-id { 
+        type string;
+      }
+    }
+  }
+  grouping controller-network {
+    uses xos:tenant;
+    leaf network { 
+      type xtype:network; 
+    }
+    leaf controller { 
+      type xtype:controller; 
+    }
+    leaf subnet { 
+      type string;
+    }
+    container synchronizer {
+      if-feature synchronizer;
+      leaf net-id { 
+        type string;
+      }
+      leaf router-id { 
+        type string;
+      }
+      leaf subnet-id { 
+        type string;
+      }
+    }
+  }
+  grouping controller-site {
+    uses xos:tenant;
+    leaf site { 
+      type xtype:site; 
+    }
+
+    leaf controller { 
+      type xtype:controller; 
+    }
+
+    container synchronizer {
+      if-feature synchronizer;
+      leaf tenant-id { 
+        type string;
+      }
+    }
+  }
+  grouping controller-slice {
+    uses xos:tenant;
+    leaf controller { 
+      type xtype:controller; 
+    }
+    leaf slice { 
+      type xtype:slice; 
+    }
+    
+    container synchronizer {
+      if-feature synchronizer;
+      leaf tenant-id { 
+        type string;
+      }
+    }
+  }
+  grouping controller-role {
+    uses xos:tenant;
+    leaf role { 
+      type string;
+    }
+  }
+  grouping controller-user {
+    uses xos:tenant;
+    leaf user { 
+      type xtype:user; 
+    }
+
+    leaf controller { 
+      type xtype:controller; 
+    }
+    
+    container synchronizer {
+      if-feature synchronizer {
+        leaf kuser-id { 
+          type string;
+        }
+      }
+    }
+  }
+  grouping controller-slice-privilege {
+    uses xos:tenant;
+    leaf controller { 
+      type xtype:controller; 
+    }
+
+    leaf slice-privilege { 
+      type xtype:slice-privilege; 
+    }
+    
+    container synchronizer {
+      if-feature synchronizer {
+        leaf role-id { 
+          type string;
+        }
+      }
+    }
+  }
+  
+}
diff --git a/tests/utests/netconf/yang/xos-package.yang b/tests/utests/netconf/yang/xos-package.yang
new file mode 100644
index 0000000..e6a0537
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-package.yang
@@ -0,0 +1,84 @@
+module xos-package {
+  namespace "urn:ietf:params:xml:ns:yang:xos-package";
+  prefix xpkg;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import yang-meta-types { prefix meta; }
+  import xos-controller  { prefix xos; }
+  import xos-types       { prefix xtype; }
+
+  organization
+    "Open Networking Lab (XOS) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+    "This module contains a collection of Package models for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-29 {
+    description "Initial revision.";
+  }
+  typedef package-identifier {
+    type yang:yang-identifier;
+  }
+
+  identity xos-package {
+    base xos:xos-tenant;
+  }
+  /*
+   * Groupings
+   */
+  grouping package-info {
+    uses meta:yang-package-info {
+      refine version {
+        description "Version of Service Definition";
+      }
+      refine description {
+        description "Description of the Service Package";
+      }
+    }
+    container controller {
+      leaf model {
+        type leafref {
+          path "../../model/name";
+        }
+        mandatory true;
+      }
+      leaf initializer {
+        type meta:filename;
+      }
+      leaf synchronizer {
+        type meta:filename;
+      }
+      leaf public-key {
+        type meta:filename;
+      }
+      leaf private-key {
+        type meta:filename;
+      }
+    }
+  }
+  /*
+   * Augmentations to XOS
+   */
+  augment "/xos:core" {
+    list package {
+      key id;
+      uses package-info;
+    }
+  }
+}
+
diff --git a/tests/utests/netconf/yang/xos-slice.yang b/tests/utests/netconf/yang/xos-slice.yang
new file mode 100644
index 0000000..1878575
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-slice.yang
@@ -0,0 +1,263 @@
+module xos-slice {
+  namespace "urn:ietf:params:xml:ns:yang:xos-slice";
+  prefix xslice;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import xos-controller  { prefix xos; }
+  import xos-types       { prefix xtype; }
+  import opnfv-infrastructure { prefix nfvi; }
+
+  organization
+    "Open Networking Lab (XOS) / Corenova Technologies, Inc.";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+    "This module contains a collection of Slice and related models for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-13 {
+    description "Initial revision.";
+  }
+
+  grouping slice {
+    description 
+      "A slice is a logically centralized container for network and compute resources";
+
+    uses xos:provider {
+      refine "name" { description "Name of the slice"; }
+    }
+    leaf slice-url {
+      description "A URL describing the purpose of this slice";
+      type inet:uri;
+      // blank true;
+    }
+    leaf-list instances {
+      type leafref {
+        path "/nfvi:controller/compute/server/id";
+      }
+    }
+    leaf-list networks {
+      type leafref {
+        path "/nfvi:controller/fabric/network/id";
+      }
+    }
+    container policy {
+      leaf max-instances {
+        description "The maximum number of VMs that this slice is allowed to allocate";
+        type uint16;
+      }
+      leaf default-flavor {
+        type leafref {
+          path "/nfvi:controller/compute/flavor/id";
+        }
+      }
+      leaf default-image {
+        type leafref {
+          path "/nfvi:controller/compute/image/id";
+        }
+      }
+      leaf default-node {
+        type leafref {
+          path "/nfvi:controller/compute/host/id";
+        }
+      } 
+      leaf mount-data-sets {
+        type string {
+          length 0..256; 
+        }
+        default "GenBank";
+      } 
+      leaf default-isolation {
+        type xtype:isolation;
+      } 
+    }
+    leaf network {
+      description
+        "The network that the slice uses to connect to other slices and to the Internet.";
+      type enumeration {
+        enum none;
+        enum host;
+        enum bridged;
+        enum noauto;
+      }
+      default none;
+    }
+    leaf-list ports {
+      description
+        "The ports to be exposed for other slices to connect to";
+      type uint16;
+    }
+    leaf creator {
+      type leafref {
+        path "/xos:core/user/id";
+      }
+    }
+    leaf-list tags {
+      type string;
+    }
+    // below are deprecated and should not be used
+    leaf service {
+      description "The service that runs in this slice";
+      status deprecated;
+    }
+    // TOOD: need to better understand relationship between Service and Slice
+    action scale {
+      description "Adjust scale for slice(s)";
+    }
+  }
+
+  /*
+   * Augmentations to XOS core and NFVI modules
+   */
+  augment "/xos:core" {
+    list slice {
+      key id;
+      uses xslice:slice;
+    }
+  }
+  
+  augment "/nfvi:controller/nfvi:compute/nfvi:server" {
+    leaf slice {
+      // do we need this circular reference?
+    }
+    leaf deployment {
+      type leafref {
+        path "/xos:core/deployment/id";
+      }
+    }
+    leaf isolation {
+      type xtype:isolation;
+    }
+    leaf-list volumes {
+      type string; // should be leafref
+    }
+    // leaf parent {
+    //   type xtype:parent;
+    // }
+    container synchronizer {
+      if-feature synchronizer;
+      leaf instance-id { 
+        type string;
+      }
+      leaf instance-uuid { 
+        type string;
+      }
+      leaf instance-name { 
+        type string;
+      }
+      leaf ip { 
+        type inet:ip-address;
+      }
+    }
+  }
+  augment "/nfvi:controller/nfvi:compute/nfvi:image" {
+    leaf template {
+      type leafref {
+        path "/xos:core/template/id";
+      }
+    }
+    leaf-list deployments {
+      type leafref {
+        path "/xos:core/deployment/id";
+      }
+    }
+    container synchronizer {
+      if-feature xos:synchronizer;
+      leaf glance-image-id { 
+        type string;
+      }
+    }
+  }
+  augment "/nfvi:controller/nfvi:fabric/nfvi:network" {
+    leaf autoconnect {
+      type boolean;
+      default true;
+    }
+    leaf-list labels {
+      type string;
+    }
+    container policy {
+      leaf guaranteed-bandwidth { 
+        type uint32;
+      }
+      leaf permit-all-slices { 
+        type boolean;
+        default true;
+      }
+      container parameters {
+        list topology {
+          key name;
+          uses xos:parameter;
+        }
+        list controller {
+          key name;
+          uses xos:parameter;
+        }
+        list network {
+          key name;
+          uses xos:parameter;
+        }
+      }
+    }
+    container synchronizer {
+      if-feature synchronizer;
+      leaf network-id { 
+        type string;
+      }
+      leaf router-id { 
+        type string;
+      }
+      leaf subnet-id { 
+        type string;
+      }
+    }
+  }
+  augment "/nfvi:controller/nfvi:fabric/nfvi:network/nfvi:subnet/nfvi:port" {
+    leaf instance {
+      type instance-identifier;
+    }
+    leaf xos-created {
+      type boolean;
+      status deprecated;
+    }
+    container synchronizer {
+      if-feature xos:synchronizer;
+      leaf ip { 
+        type inet:ip-address;
+      }
+      leaf port-id { 
+        type yang:uuid;
+      }
+      leaf mac { 
+        type yang:mac-address;
+      }
+    }
+  }
+  augment "/nfvi:controller/nfvi:fabric/nfvi:network/nfvi:subnet/nfvi:dhcp/nfvi:pool" {
+    leaf gateway-ip {
+      type inet:ip-address;
+    }
+    leaf gateway-mac {
+      type yang:mac-address;
+    }
+    leaf cidr {
+      type string;
+    }
+    leaf inuse {
+      type boolean;
+    }
+  }
+}
diff --git a/tests/utests/netconf/yang/xos-topology.yang b/tests/utests/netconf/yang/xos-topology.yang
new file mode 100644
index 0000000..469cb84
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-topology.yang
@@ -0,0 +1,224 @@
+module xos-topology {
+  namespace "urn:ietf:params:xml:ns:yang:xos-topology";
+  prefix xtop;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import yang-meta-types { prefix meta; }
+  import xos-controller  { prefix xos; }
+  import xos-types       { prefix xtype; }
+
+  organization
+    "Open Networking Lab (XOS) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+    "This module contains a collection of Topology models for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-13 {
+    description "Initial revision.";
+  }
+
+  grouping deployment {
+    uses xos:provider {
+      refine "name" { description "Name of the deployment"; }
+    }
+    leaf-list sites {
+      config false;
+      type leafref {
+        path "/xos:core/site/id";
+      }
+    }
+    leaf-list templates {
+      type leafref {
+        path "/xos:core/template/id";
+      }
+    }
+  }
+  grouping site {
+    uses xos:provider {
+      refine "name" { description "Name of the site"; }
+    }
+    leaf site-url { 
+      description "A URL describing the purpose of this site";
+      type inet:uri;
+    }
+    container location {
+      leaf geoposition {
+        type string; // what is this data format?
+      }
+      leaf longitude { 
+        type decimal64;
+      }
+      leaf latitude { 
+        type decimal64;
+      }
+    }
+    leaf is-public { 
+      type boolean;
+    }
+    leaf login-base { 
+      type string;
+    }
+    leaf deployment {
+      type leafref {
+        path "/xos:core/deployment/id";
+      }
+    }
+    leaf-list nodes {
+      config false;
+      type leafref {
+        path "/xos:core/node/id";
+      }
+    }
+    leaf-list users {
+      config false;
+      type leafref {
+        path "/xos:core/user/id";
+      }
+    }
+    leaf hosts-nodes {
+      config false;
+      type boolean;
+    }
+    leaf hosts-users {
+      config false;
+      type boolean;
+    }
+    container synchronizer {
+      if-feature xos:synchronizer;
+      leaf availability-zone { 
+        type string;
+      }
+    }
+  }
+  grouping node {
+    uses xos:tenant;
+    leaf site { 
+      type leafref {
+        path "/xos:core/site/id";
+      }
+    }
+    leaf deployment {
+      config false;
+      type leafref {
+        path "/xos:core/deployment/id";
+      }
+    }
+  }
+  grouping user {
+    uses xos:tenant {
+      refine 'name' {
+        config false;
+        description "Name of the user";
+      }
+    }
+    leaf firstname {
+      type meta:person-name;
+    }
+    leaf lastname {
+      type meta:person-name;
+    }
+    leaf email {
+      type meta:email-address;
+    }
+    leaf phone {
+      type meta:phone-number;
+    }
+    leaf timezone {
+      type meta:timezone;
+    }
+    leaf site {
+      type leafref {
+        path "/xos:core/site/id";
+      }
+    }
+    container credential {
+      leaf username {
+        type yang:yang-identifier;
+      }
+      leaf password {
+        type meta:password;
+      }
+      leaf role {
+        type xtype:access-role;
+      }
+      leaf public-key {
+        type string;
+      }
+      leaf login-page {
+        type inet:uri;
+      }
+      leaf last-login {
+        config false;
+        type yang:date-and-time;
+      }
+    }
+  }
+  grouping network-template {
+    uses xos:tenant;
+    leaf guaranteed-bandwidth { 
+      type uint32;
+    }
+    leaf visibility { 
+      type string;
+    }
+    leaf translation { 
+      type string;
+    }
+    leaf access { 
+      type string;
+    }
+    leaf shared-network-name { 
+      type string;
+    }
+    leaf shared-network-id { 
+      type string;
+    }
+    leaf topology-kind { 
+      type string;
+    }
+    leaf controller-kind { 
+      type string;
+    }
+  }
+
+  /*
+   * Augmentations to XOS core
+   */
+  augment "/xos:core" {
+    list template {
+      key id;
+      uses xtop:network-template;
+    }
+    list deployment {
+      key id;
+      uses xtop:deployment;
+    }
+    list site {
+      key id;
+      uses xtop:site;
+    }
+    list node {
+      key id;
+      uses xtop:node;
+    }
+    list user {
+      key id;
+      uses xtop:user;
+    }
+  }
+}
diff --git a/tests/utests/netconf/yang/xos-types.yang b/tests/utests/netconf/yang/xos-types.yang
new file mode 100644
index 0000000..289587a
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-types.yang
@@ -0,0 +1,87 @@
+module xos-types {
+  namespace "urn:ietf:params:xml:ns:yang:xos-types";
+  prefix xtype;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  
+  organization
+   "Open Networking Lab (CORD) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+   "This module contains a collection of common models and types for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-12 {
+    description "Initial revision.";
+  }
+
+  /*
+   * Typedefs
+   */
+  typedef unique-identifier {
+    description "defines valid formats for external reference id";
+    type union {
+      type uint32 { range 1..max; }
+      type yang:uuid;
+      type inet:uri;
+    }
+  }
+  typedef flow-identifier {
+    description "defines valid format for identifying a flow";
+    type yang:uuid;
+  }
+  typedef network-identifier {
+    description "defines valid format for identifying a network";
+    type yang:uuid;
+  }
+  typedef mac-address {
+    description "defines valid format for mac-address";
+    type yang:mac-address;
+  }
+  typedef bandwidth {
+    type uint32 {
+      range 1000000..max; // should be at least 1 Mbps?  
+    }
+    units 'bps';
+  }
+  typedef vlan {
+    type uint16 { range 0..4095; }
+  }
+  typedef isolation {
+    type enumeration {
+      enum vm     { description 'Virtual Machine'; }
+      enum lxc    { description 'Container'; }
+      enum hybrid { description 'Container in Virtual Machine'; }
+    }
+    default 'vm';
+  }
+  typedef access-role {
+    type enumeration {
+      enum admin;
+      enum staff;
+      enum user;
+    }
+    default 'user';
+  }
+  typedef certificate {
+    description
+      "Captures a security certificate, should be improved for better validation";
+    type string {
+      length 0..1024;
+    }
+  }
+}
diff --git a/tests/utests/netconf/yang/xos-unreconciled-models.yang b/tests/utests/netconf/yang/xos-unreconciled-models.yang
new file mode 100644
index 0000000..491a153
--- /dev/null
+++ b/tests/utests/netconf/yang/xos-unreconciled-models.yang
@@ -0,0 +1,462 @@
+module xos-accessibility {
+  namespace "urn:ietf:params:xml:ns:yang:xos-accessibility";
+  prefix xacc;
+  yang-version 1.1;
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import xos-types       { prefix xtype; }
+
+  organization
+    "Open Networking Lab (XOS) / Corenova Technologies";
+
+  contact
+    "Larry Peterson <llp@onlab.us>
+     Peter K. Lee <peter@corenova.com>";
+  
+  description
+    "This module contains a collection of core models for XOS.
+
+    Copyright (c) 2016 ON.LAB and the persons identified as authors of
+    the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms of the Apache License, Version 2.0 which accompanies this
+    distribution, and is available at
+    (http://www.apache.org/licenses/LICENSE-2.0).";
+  
+  revision 2016-09-13 {
+    description "Initial revision.";
+  }
+
+  /* Future Consideration
+  typedef image {
+    type unique-identifier;
+  }
+  typedef controller-network {
+    type unique-identifier;
+  }
+  typedef site {
+    type unique-identifier;
+  }
+  typedef tenant-root-role {
+    type unique-identifier;
+  }
+  typedef slice-role {
+    type unique-identifier;
+  }
+  typedef site-deployment {
+    type unique-identifier;
+  }
+  typedef tenant-privilege {
+    type unique-identifier;
+  }
+  typedef tag {
+    type unique-identifier;
+  }
+  typedef user-credential {
+    type unique-identifier;
+  }
+  typedef invoice {
+    type unique-identifier;
+  }
+  typedef slice-privilege {
+    type unique-identifier;
+  }
+  typedef flavor {
+    type unique-identifier;
+  }
+  typedef port {
+    type unique-identifier;
+  }
+  typedef service-role {
+    type unique-identifier;
+  }
+  typedef controller-site {
+    type unique-identifier;
+  }
+  typedef controller-slice {
+    type unique-identifier;
+  }
+  typedef tenant-role {
+    type unique-identifier;
+  }
+  typedef slice {
+    type unique-identifier;
+  }
+  typedef network {
+    type unique-identifier;
+  }
+  typedef controller-role {
+    type unique-identifier;
+  }
+  typedef diag {
+    type unique-identifier;
+  }
+  typedef service-class {
+    type unique-identifier;
+  }
+  typedef tenant-attribute {
+    type unique-identifier;
+  }
+  typedef site-role {
+    type unique-identifier;
+  }
+  typedef subscriber {
+    type unique-identifier;
+  }
+  typedef instance {
+    type unique-identifier;
+  }
+  typedef charge {
+    type unique-identifier;
+  }
+  typedef program {
+    type unique-identifier;
+  }
+  typedef role {
+    type unique-identifier;
+  }
+  typedef usable-object {
+    type unique-identifier;
+  }
+  typedef node-label {
+    type unique-identifier;
+  }
+  typedef slice-credential {
+    type unique-identifier;
+  }
+  typedef node {
+    type unique-identifier;
+  }
+  typedef address-pool {
+    type unique-identifier;
+  }
+  typedef dashboard-view {
+    type unique-identifier;
+  }
+  typedef network-parameter {
+    type unique-identifier;
+  }
+  typedef image-deployments {
+    type unique-identifier;
+  }
+  typedef controller-user {
+    type unique-identifier;
+  }
+  typedef reserved-resource {
+    type unique-identifier;
+  }
+  typedef network-template {
+    type unique-identifier;
+  }
+  typedef controller-dashboard-view {
+    type unique-identifier;
+  }
+  typedef user-dashboard-view {
+    type unique-identifier;
+  }
+  typedef controller {
+    type unique-identifier;
+  }
+  typedef user {
+    type unique-identifier;
+  }
+  typedef deployment {
+    type unique-identifier;
+  }
+  typedef reservation {
+    type unique-identifier;
+  }
+  typedef site-privilege {
+    type unique-identifier;
+  }
+  typedef payment {
+    type unique-identifier;
+  }
+  typedef tenant {
+    type unique-identifier;
+  }
+  typedef network-slice {
+    type unique-identifier;
+  }
+  typedef account {
+    type unique-identifier;
+  }
+  typedef tenant-root {
+    type unique-identifier;
+  }
+  typedef service {
+    type unique-identifier;
+  }
+  typedef controller-slice-privilege {
+    type unique-identifier;
+  }
+  typedef site-credential {
+    type unique-identifier;
+  }
+  typedef deployment-privilege {
+    type unique-identifier;
+  }
+  typedef network-parameter-type {
+    type unique-identifier;
+  }
+  typedef provider {
+    type unique-identifier;
+  }
+  typedef tenant-with-container {
+    type unique-identifier;
+  }
+  typedef deployment-role {
+    type unique-identifier;
+  }
+  typedef project {
+    type unique-identifier;
+  }
+  typedef tenant-root-privilege {
+    type unique-identifier;
+  }
+  typedef slice-tag {
+    type unique-identifier;
+  }
+  typedef coarse-tenant {
+    type unique-identifier;
+  }
+  typedef router {
+    type unique-identifier;
+  }
+  typedef service-resource {
+    type unique-identifier;
+  }
+  typedef service-privilege {
+    type unique-identifier;
+  }
+  */
+  grouping service-class {
+    uses xos-base;
+    
+    leaf description { 
+      type string;
+    }
+    leaf commitment { 
+      type uint32;
+    }
+    leaf membership-fee { 
+      type uint32;
+    }
+    leaf membership-fee-months { 
+      type uint32;
+    }
+    leaf upgrade-requires-approval { 
+      type boolean;
+    }
+  }
+  grouping invoice {
+    uses xos-base;
+    leaf date { 
+      type xtype:datetime;
+    }
+    leaf account { 
+      type xtype:account; 
+    }
+  }
+
+  grouping charge {
+    uses xos-base;
+    leaf account { 
+      type xtype:account; 
+    }
+    leaf slice { 
+      type xtype:slice; 
+    }
+    leaf kind { 
+      type string;
+    }
+    leaf state { 
+      type string;
+    }
+    leaf date { 
+      type xtype:datetime;
+    }
+    leaf object { 
+      type xtype:object; 
+    }
+    leaf amount { 
+      type decimal64;
+    }
+    leaf core-hours { 
+      type decimal64;
+    }
+    leaf invoice { 
+      type xtype:invoice; 
+    }
+  }
+
+  grouping role {
+    uses xos-base;
+    leaf role-type { 
+      type string;
+    }
+    leaf role { 
+      type string;
+    }
+    leaf description { 
+      type string;
+    }
+    leaf content-type { 
+      type xtype:content-type; 
+    }
+  }
+
+  grouping dashboard-view {
+    uses xos-base;
+    leaf url { 
+      type string;
+    }
+    leaf enabled { 
+      type boolean;
+    }
+  }
+
+  grouping controller-dashboard-view {
+    uses xos-base;
+    leaf controller { 
+      type xtype:controller; 
+    }
+    leaf dashboardView { 
+      type xtype:dashboardView; 
+    }
+    leaf enabled { 
+      type boolean;
+    }
+    leaf url { 
+      type string;
+    }
+  }
+
+  grouping user-dashboard-view {
+    uses xos-base;
+    leaf user { 
+      type xtype:user; 
+    }
+    leaf dashboardView { 
+      type xtype:dashboardView; 
+    }
+    leaf order { 
+      type uint32;
+    }
+  }
+  grouping service-privilege {
+    uses xos-base;
+    leaf user { 
+      type xtype:user; 
+    }
+    leaf service { 
+      type xtype:service; 
+    }
+    leaf role { 
+      type xtype:role; 
+    }
+  }
+
+  grouping payment {
+    uses xos-base;
+    leaf account { 
+      type xtype:account; 
+    }
+    leaf amount { 
+      type decimal64;
+    }
+    leaf date { 
+      type xtype:datetime;
+    }
+  }
+  
+  grouping account {
+    uses xos-base;
+    leaf site { 
+      type xtype:site; 
+    }
+  }
+
+  grouping service-resource {
+    uses xos-base;
+    leaf service-class { 
+      type xtype:service-class; 
+    }
+    
+    leaf max-units-deployment { 
+      type uint32;
+    }
+
+    leaf max-units-node { 
+      type uint32;
+    }
+
+    leaf max-duration { 
+      type uint32;
+    }
+
+    leaf bucket-in-rate { 
+      type uint32;
+    }
+
+    leaf bucket-max-size { 
+      type uint32;
+    }
+
+    leaf cost { 
+      type uint32;
+    }
+
+    leaf calendar-reservable { 
+      type boolean;
+    }
+  }
+
+  grouping diag {
+    uses xos-base;
+    
+  }
+
+  grouping program {
+    uses xos-base;
+    leaf description { 
+      type string;
+    }
+
+    leaf kind { 
+      type string;
+    }
+
+    leaf command { 
+      type string;
+    }
+
+    leaf owner { 
+      type xtype:owner; 
+    }
+
+    leaf contents { 
+      type string;
+    }
+
+    leaf output { 
+      type string;
+    }
+
+    leaf messages { 
+      type string;
+    }
+
+    leaf status { 
+      type string;
+    }
+  }
+
+  grouping usable-object {
+    uses xos-base;
+  }
+
+}
diff --git a/tests/utests/netconf/yang/yang_to_protobuf_test.py b/tests/utests/netconf/yang/yang_to_protobuf_test.py
new file mode 100644
index 0000000..cd142fd
--- /dev/null
+++ b/tests/utests/netconf/yang/yang_to_protobuf_test.py
@@ -0,0 +1,198 @@
+#
+# Copyright 2016 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import json
+import os
+from unittest import TestCase
+import time
+from tests.itests.docutests.test_utils import run_command_to_completion_with_raw_stdout
+from tests.utests.chameleon.protoc_plugins.test_utils import load_file
+
+
+pyang_cmd = "pyang --plugindir /voltha/experiments/plugin -f protobuf " \
+            "-p /voltha/tests/utests/netconf/yang " \
+            "/voltha/tests/utests/netconf/yang/{}"
+
+class YangToProtoBufTests(TestCase):
+
+    def _compare_file(self, response, expected_response):
+        # compare two files and strip empty lines, blanks, etc
+        def _filter(x):
+            x.strip()
+            return x is not None
+
+        response = filter(_filter,response.split())
+        expected_response = filter(_filter,expected_response.split())
+        self.assertEqual(set(response), set(expected_response))
+
+
+    def test_01_basic_def(self):
+        print "Test_01_basic_def_Start:------------------"
+        t0 = time.time()
+
+        # input file: /voltha/tests/utests/netconf/yang/basic.yang
+
+        expected_response = """
+            syntax = "proto3";
+            package basic;
+
+            message commonAttributes {
+                uint32 my-id = 1 ;
+                string my-name = 2 ;
+                bool my-status = 3 ;
+            }
+            """
+
+        try:
+            cmd = pyang_cmd.format('basic.yang')
+            print 'running command: {}'.format(cmd)
+            response, err, rc = run_command_to_completion_with_raw_stdout(cmd)
+            self.assertEqual(rc, 0)
+
+            self._compare_file(response, expected_response)
+        finally:
+            print "Test_01_basic_def_End:------------------ took {} " \
+                  "secs\n\n".format(time.time() - t0)
+
+
+    def test_02_container_def(self):
+        print "Test_02_container_def_Start:------------------"
+        t0 = time.time()
+
+        # input file: /voltha/tests/utests/netconf/yang/container.yang
+
+        expected_response = """
+            syntax = "proto3";
+            package container;
+
+            message int-container {
+                int32 eight = 1 ;
+                int32 nine = 2 ;
+            }
+            message int-container {
+                int32 eight = 1 ;
+                int32 nine = 2 ;
+            }
+            """
+
+        try:
+            cmd = pyang_cmd.format('container.yang')
+            print 'running command: {}'.format(cmd)
+            response, err, rc = run_command_to_completion_with_raw_stdout(cmd)
+            self.assertEqual(rc, 0)
+
+            self._compare_file(response, expected_response)
+        finally:
+            print "Test_02_container_def_End:------------------ took {} " \
+                  "secs\n\n".format(time.time() - t0)
+
+
+    def test_03_mix_simple_types(self):
+        print "Test_03_mix_simple_types_Start:------------------"
+        t0 = time.time()
+
+        # input file: /voltha/tests/utests/netconf/yang/mix_simple_types.yang
+
+        expected_response = """
+            syntax = "proto3";
+            package mix_simple_types;
+
+            message user {
+                string name = 1 ;
+                string full-name = 2 ;
+                string class = 3 ;
+            }
+            message user {
+                string name = 1 ;
+                string full-name = 2 ;
+                string class = 3 ;
+            }
+
+            message int-container {
+                int32 eight = 1 ;
+                int32 nine = 2 ;
+                int32 ten = 3 ;
+            }
+            message container1 {
+                bool a = 1 ;
+                Any b = 2 ;
+                string mleaf = 3 ;
+                repeated string mleaf_list = 4 ;
+                message inner-container {
+                    string mleaf1 = 1 ;
+                    string mleaf2 = 2 ;
+                }
+            }
+            message int-container {
+                int32 eight = 1 ;
+                int32 nine = 2 ;
+                int32 ten = 3 ;
+            }
+            message container1 {
+                bool a = 1 ;
+                Any b = 2 ;
+                string mleaf = 3 ;
+                repeated string mleaf_list = 4 ;
+                message inner-container {
+                    string mleaf1 = 1 ;
+                    string mleaf2 = 2 ;
+                }
+            }
+            """
+
+        try:
+            cmd = pyang_cmd.format('mix_simple_types.yang')
+            print 'running command: {}'.format(cmd)
+            response, err, rc = run_command_to_completion_with_raw_stdout(cmd)
+            self.assertEqual(rc, 0)
+
+            self._compare_file(response, expected_response)
+        finally:
+            print "Test_03_mix_simple_types_End:------------------ took {} " \
+                  "secs\n\n".format(time.time() - t0)
+
+
+    def test_04_cord_tenant(self):
+        print "Test_04_cord_tenant_Start:------------------"
+        t0 = time.time()
+
+        # input file: /voltha/tests/utests/netconf/yang/cord-tenant.yang
+
+        expected_response = """
+            syntax = "proto3";
+            package cord_tenant;
+
+            message subscriber {
+                string label = 1 ;
+                enum status
+                {
+                    violation = 0 ;
+                    enabled = 1 ;
+                    delinquent = 2 ;
+                    suspended = 3 ;
+                }
+                bool demo = 3 ;
+            }
+            """
+        try:
+            cmd = pyang_cmd.format('cord-tenant.yang')
+            print 'running command: {}'.format(cmd)
+            response, err, rc = run_command_to_completion_with_raw_stdout(cmd)
+            self.assertEqual(rc, 0)
+
+            self._compare_file(response, expected_response)
+        finally:
+            print "Test_04_cord_tenant_End:------------------ took {} " \
+                  "secs\n\n".format(time.time() - t0)