cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
3407
Views
0
Helpful
8
Replies

Juniper openconfig-bgp failure

horseinthesky
Level 1
Level 1

I'm trying to configure BGP on Juniper vMX 19.2R1.8 using one of the examples in YDK repo:

import logging

from ydk.services import CodecService, CRUDService
from ydk.providers import CodecServiceProvider, NetconfServiceProvider
from ydk.models.openconfig import openconfig_bgp as oc_bgp
from ydk.models.openconfig import openconfig_bgp_types as oc_bgp_types
from ydk.filters import YFilter

logger = logging.getLogger('ydk')
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter(("%(asctime)s - %(name)s - "
                               "%(levelname)s - %(message)s"))
handler.setFormatter(formatter)
logger.addHandler(handler)

DEVICES = {
    'junos': {
        'ip': '10.10.30.4',
        'pass': 'Juniper'
    },
    'xr': {
        'ip': '10.10.30.5',
        'pass': 'admin'
    },
    'xe': {
        'ip': '10.10.30.6',
        'pass': 'admin'
    }
}


def config_bgp(bgp):
    """Add config data to bgp object."""
    # global configuration
    bgp.global_.config.as_ = 65001
    afi_safi = bgp.global_.afi_safis.AfiSafi()
    afi_safi.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.enabled = True
    bgp.global_.afi_safis.afi_safi.append(afi_safi)

    # configure IBGP peer group
    peer_group = bgp.peer_groups.PeerGroup()
    peer_group.peer_group_name = "EBGP"
    peer_group.config.peer_group_name = "EBGP"
    peer_group.config.peer_as = 65002
    peer_group.transport.config.local_address = "Loopback0"
    afi_safi = peer_group.afi_safis.AfiSafi()
    afi_safi.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.enabled = True
    # afi_safi.apply_policy.config.import_policy.append("POLICY3")
    # afi_safi.apply_policy.config.export_policy.append("POLICY1")
    peer_group.afi_safis.afi_safi.append(afi_safi)
    bgp.peer_groups.peer_group.append(peer_group)

    # configure IBGP neighbor
    neighbor = bgp.neighbors.Neighbor()
    neighbor.neighbor_address = '2001:db8:e:1::1'
    neighbor.config.neighbor_address = '2001:db8:e:1::1'
    neighbor.config.peer_group = "EBGP"
    bgp.neighbors.neighbor.append(neighbor)


if __name__ == '__main__':
    # provider = CodecServiceProvider(type='xml')
    # codec = CodecService()

    bgp = oc_bgp.Bgp()
    # bgp.yfilter = YFilter.replace
    config_bgp(bgp)

    # print(codec.encode(provider, bgp))

    device = DEVICES['junos']

    provider = NetconfServiceProvider(
        address=device['ip'],
        port=830,
        username='admin',
        password=device['pass'],
        protocol='ssh'
    )
    crud = CRUDService()
    crud.create(provider, bgp)

But it fails with the following exception:

2019-12-11 14:45:18,263 - ydk - ERROR - Path 'openconfig-bgp:bgp' is invalid
Traceback (most recent call last):
  File "openconfig_bgp.py", line 86, in <module>
    crud.create(provider, bgp)
  File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 112, in helper
    return func(self, provider, entity, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/ydk/services/crud_service.py", line 49, in create
    return _crud_update(provider, entity, self._crud.create)
  File "/usr/local/lib/python3.6/dist-packages/ydk/services/crud_service.py", line 70, in _crud_update
    return crud_call(provider, entity)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 82, in handle_runtime_error
    _raise(_exc)
  File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 54, in _raise
    exec("raise exc from None")
  File "<string>", line 1, in <module>
ydk.errors.YInvalidArgumentError:  Path is invalid: openconfig-bgp:bgp

Full DEBUG is in the attachments.

1 Accepted Solution

Accepted Solutions

Here is the error:

2019-12-24 16:07:22,933 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Invalid keyword "[1-9][0-9]{1,2}|[1-9])|\*)"".

This is the same as this. It appears because Juniper incorrectly used escape character '\*' when modified the pattern string from original standard openconfig model. The correct use of escape character would be '\\*' or put the pattern string in single quotes. Although it is not YDK issue, I have added escape of this combination in our fork of Libyang. Please recompile the core YDK library and python package to get corrected version of Libyang and then repeat your script.

cd ydk-gen
python3 generate.py --core --cpp -is
python3 generate.py --core --python -is

 

Yan Gorelik
YDK Solutions

View solution in original post

8 Replies 8

yangorelik
Spotlight
Spotlight

The analysis of debug log showed that YDK (libyang) failed to parse openconfig-yang-types.yang module.

2019-12-11 14:45:18,261 - ydk - DEBUG - Path found with revision: /home/horseinthesky/.ydk/10.10.30.4/openconfig-yang-types.yang
2019-12-11 14:45:18,261 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Invalid keyword "[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}"".
2019-12-11 14:45:18,261 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Module "openconfig-yang-types" parsing failed.

That is actually the libyang defect, which I opened and then resolved in the fork specific for YDK.

Please recompile the libydk and try to run the script again:

cd ydk-gen
./generate.py --core --cpp -is
./generate.py --core -is

 

Yan Gorelik
YDK Solutions

Now it is some kind of validation error I suppose

It is device configuration error:

2019-12-15 16:22:17,926 - ydk - DEBUG - Netconf SSH Client: processing reply
2019-12-15 16:22:17,926 - ydk - INFO - ============= Received RPC from device =============
<?xml version="1.0"?>
<nc:rpc-reply xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/19.2R0/junos" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2">
<nc:rpc-error>
<nc:error-type>protocol</nc:error-type>
<nc:error-tag>operation-failed</nc:error-tag>
<nc:error-severity>error</nc:error-severity>
<nc:error-message>
No type match found for union for node neighbor-address
</nc:error-message>
</nc:rpc-error>
<nc:rpc-error>
<nc:error-type>protocol</nc:error-type>
<nc:error-tag>operation-failed</nc:error-tag>
<nc:error-severity>error</nc:error-severity>
<nc:error-message>neighbor-address: '2001:db8:e:1::1': invalid value</nc:error-message>
<nc:error-info>
<nc:bad-element>2001:db8:e:1::1</nc:bad-element>
</nc:error-info>
</nc:rpc-error>
<load-error-count>1</load-error-count>
</nc:rpc-reply>

Seems like Netconf did not understand IPv6 address.

The YDK worked perfectly well.

Yan Gorelik
YDK Solutions

JTAC answered to me:

I  have discussed this issue with Engineering team. The recommandation is to start using openconfig-network-instances here because starting from 18.4R1 there have been certain changes.
Network instance based BGP neighbor PATH should be used. This helps identify whgich VRF or global instance BGP neighbor belongs, which older version of OCST model was premature and did not provide this capability.

"I tried this XML-RPC and it worked fine on latest Junos.

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
<edit-config>
<target>
<candidate></candidate>
</target>
<config>
<network-instances xmlns="http://openconfig.net/yang/network-instance">
<network-instance>
<name>d</name>
<protocols>
<protocol>
<identifier>bgp</identifier>
<name>bgp</name>
<bgp>
<neighbors>
<neighbor>
<neighbor-address>10.10.30.6</neighbor-address>
</neighbor>
</neighbors>
</bgp>
</protocol>
</protocols>
</network-instance>
</network-instances>
</config>
</edit-config>
</rpc>

I tried to do it like this:

import logging

from ydk.services import CodecService, CRUDService
from ydk.providers import CodecServiceProvider, NetconfServiceProvider
from ydk.models.openconfig import openconfig_bgp as oc_bgp
from ydk.models.openconfig import openconfig_network_instance as oc_ni
from ydk.models.openconfig import openconfig_bgp_types as oc_bgp_types
from ydk.filters import YFilter

from devices import DEVICES

logger = logging.getLogger('ydk')
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter(("%(asctime)s - %(name)s - "
                               "%(levelname)s - %(message)s"))
handler.setFormatter(formatter)
logger.addHandler(handler)


def config_bgp(bgp):
    """Add config data to bgp object."""
    # global configuration
    bgp.global_.config.as_ = 5
    afi_safi = bgp.global_.afi_safis.AfiSafi()
    afi_safi.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.enabled = True
    bgp.global_.afi_safis.afi_safi.append(afi_safi)

    # configure IBGP peer group
    peer_group = bgp.peer_groups.PeerGroup()
    peer_group.peer_group_name = "EBGP"
    peer_group.config.peer_group_name = "EBGP"
    peer_group.config.peer_as = 6
    peer_group.transport.config.local_address = "Loopback0"
    afi_safi = peer_group.afi_safis.AfiSafi()
    afi_safi.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.enabled = True
    # afi_safi.apply_policy.config.import_policy.append("POLICY3")
    # afi_safi.apply_policy.config.export_policy.append("POLICY1")
    peer_group.afi_safis.afi_safi.append(afi_safi)
    bgp.peer_groups.peer_group.append(peer_group)

    # configure IBGP neighbor
    neighbor = bgp.neighbors.Neighbor()
    neighbor.neighbor_address = '10.10.30.6'
    neighbor.config.neighbor_address = '10.10.30.6'
    neighbor.config.peer_group = "EBGP"
    bgp.neighbors.neighbor.append(neighbor)


if __name__ == '__main__':
    # provider = CodecServiceProvider(type='xml')
    # codec = CodecService()

    bgp = oc_ni.NetworkInstances.NetworkInstance.Protocols.Protocol.Bgp()
    # bgp.yfilter = YFilter.replace
    config_bgp(bgp)

    # print(codec.encode(provider, bgp))

    device = DEVICES['junos']

    provider = NetconfServiceProvider(
        address=device['ip'],
        port=830,
        username='admin',
        password=device['pass'],
        protocol='ssh'
    )
    crud = CRUDService()
    crud.create(provider, bgp)

But got the following exception:

2019-12-23 13:06:11,205 - ydk - DEBUG - Trace: Password authentication (host 10.10.30.4, user admin)
2019-12-23 13:06:11,288 - ydk - DEBUG - Trace: Writing message (session ): 
<?xml version="1.0" encoding="UTF-8"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
    <capability>urn:ietf:params:netconf:base:1.1</capability>
    <capability>urn:ietf:params:netconf:capability:writable-running:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:startup:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
  </capabilities>
</hello>

2019-12-23 13:06:11,776 - ydk - DEBUG - Trace: Received message (session ): <!-- No zombies were killed during the creation of this user interface -->
<!-- user admin, class j-super-user -->
<nc:hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
   <nc:capabilities>
    <nc:capability>urn:ietf:params:netconf:base:1.0</nc:capability>
    <nc:capability>urn:ietf:params:netconf:capability:candidate:1.0</nc:capability>
    <nc:capability>urn:ietf:params:netconf:capability:confirmed-commit:1.0</nc:capability>
    <nc:capability>urn:ietf:params:netconf:capability:validate:1.0</nc:capability>
    <nc:capability>urn:ietf:params:netconf:capability:url:1.0?scheme=http,ftp,file</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&amp;revision=2011-06-01</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:netconf:capability:candidate:1.0</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:netconf:capability:url:1.0?scheme=http,ftp,file</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;revision=2013-07-15</nc:capability>
    <nc:capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</nc:capability>
    <nc:capability>http://xml.juniper.net/netconf/junos/1.0</nc:capability>
    <nc:capability>http://xml.juniper.net/dmi/system/1.0</nc:capability>
  </nc:capabilities>
  <nc:session-id>59296</nc:session-id>
</nc:hello>

2019-12-23 13:06:11,776 - ydk - DEBUG - NetconfSSHClient: NC session status: 1
2019-12-23 13:06:11,776 - ydk - INFO - Path where models are to be downloaded: /home/horseinthesky/.ydk/10.10.30.4
2019-12-23 13:06:11,776 - ydk - DEBUG - Creating libyang context in path: /home/horseinthesky/.ydk/10.10.30.4
2019-12-23 13:06:11,776 - ydk - DEBUG - [libyang] Extension plugin "/usr/local/lib/libyang/libyang_ext_test.so" successfully loaded.
2019-12-23 13:06:11,777 - ydk - DEBUG - [libyang] Extension plugin "/usr/local/lib/libyang/metadata.so" successfully loaded.
2019-12-23 13:06:11,777 - ydk - DEBUG - [libyang] Extension plugin "/usr/local/lib/libyang/nacm.so" successfully loaded.
2019-12-23 13:06:11,777 - ydk - DEBUG - [libyang] Reading module "ietf-yang-metadata".
2019-12-23 13:06:11,777 - ydk - DEBUG - [libyang] Module "ietf-yang-metadata@2016-08-05" successfully parsed as implemented.
2019-12-23 13:06:11,778 - ydk - DEBUG - [libyang] Reading module "yang".
2019-12-23 13:06:11,778 - ydk - DEBUG - [libyang] Resolving "yang" unresolved schema nodes and their constraints...
2019-12-23 13:06:11,778 - ydk - DEBUG - [libyang] All "yang" schema nodes and constraints resolved.
2019-12-23 13:06:11,778 - ydk - DEBUG - [libyang] Module "yang@2017-02-20" successfully parsed as implemented.
2019-12-23 13:06:11,779 - ydk - DEBUG - [libyang] Reading module "ietf-inet-types".
2019-12-23 13:06:11,779 - ydk - DEBUG - [libyang] Resolving derived type "union" failed, it will be attempted later.
2019-12-23 13:06:11,779 - ydk - DEBUG - [libyang] Resolving derived type "union" failed, it will be attempted later.
2019-12-23 13:06:11,779 - ydk - DEBUG - [libyang] Resolving derived type "union" failed, it will be attempted later.
2019-12-23 13:06:11,779 - ydk - DEBUG - [libyang] Resolving derived type "union" failed, it will be attempted later.
2019-12-23 13:06:11,780 - ydk - DEBUG - [libyang] Resolving "ietf-inet-types" unresolved schema nodes and their constraints...
2019-12-23 13:06:11,780 - ydk - DEBUG - [libyang] All "ietf-inet-types" schema nodes and constraints resolved.
2019-12-23 13:06:11,780 - ydk - DEBUG - [libyang] Module "ietf-inet-types@2013-07-15" successfully parsed as implemented.
2019-12-23 13:06:11,781 - ydk - DEBUG - [libyang] Reading module "ietf-yang-types".
2019-12-23 13:06:11,781 - ydk - DEBUG - [libyang] Module "ietf-yang-types@2013-07-15" successfully parsed as implemented.
2019-12-23 13:06:11,781 - ydk - DEBUG - [libyang] Reading module "ietf-datastores".
2019-12-23 13:06:11,781 - ydk - DEBUG - [libyang] Module "ietf-datastores@2017-08-17" successfully parsed as implemented.
2019-12-23 13:06:11,782 - ydk - DEBUG - [libyang] Reading module "ietf-yang-library".
2019-12-23 13:06:11,783 - ydk - DEBUG - [libyang] Module "ietf-yang-library@2017-08-17" successfully parsed as implemented.
2019-12-23 13:06:11,783 - ydk - DEBUG - Loading module 'ydk', revision '2016-02-26'
2019-12-23 13:06:11,783 - ydk - DEBUG - Getting module 'ydk' submodule 'none'
2019-12-23 13:06:11,783 - ydk - DEBUG - Looking for file in folder: /home/horseinthesky/.ydk/10.10.30.4
2019-12-23 13:06:11,783 - ydk - DEBUG - Opening file '/home/horseinthesky/.ydk/10.10.30.4/ydk@2016-02-26.yang'
2019-12-23 13:06:11,783 - ydk - DEBUG - Path found with revision: /home/horseinthesky/.ydk/10.10.30.4/ydk@2016-02-26.yang
2019-12-23 13:06:11,785 - ydk - DEBUG - [libyang] Module "ydk@2016-02-26" successfully parsed as implemented.
2019-12-23 13:06:11,785 - ydk - DEBUG - Loading module 'ietf-netconf', revision '2011-06-01'
2019-12-23 13:06:11,785 - ydk - DEBUG - Getting module 'ietf-netconf' submodule 'none'
2019-12-23 13:06:11,786 - ydk - DEBUG - Looking for file in folder: /home/horseinthesky/.ydk/10.10.30.4
2019-12-23 13:06:11,786 - ydk - DEBUG - Opening file '/home/horseinthesky/.ydk/10.10.30.4/ietf-netconf@2011-06-01.yang'
2019-12-23 13:06:11,786 - ydk - DEBUG - Path found with revision: /home/horseinthesky/.ydk/10.10.30.4/ietf-netconf@2011-06-01.yang
2019-12-23 13:06:11,787 - ydk - DEBUG - [libyang] Module "ietf-netconf@2011-06-01" successfully parsed as implemented.
2019-12-23 13:06:11,787 - ydk - DEBUG - Populating new module schema 'ietf-yang-metadata'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'yang'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'ietf-inet-types'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'ietf-yang-types'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'ietf-datastores'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'ietf-yang-library'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'ydk'
2019-12-23 13:06:11,788 - ydk - DEBUG - Populating new module schema 'ietf-netconf'
2019-12-23 13:06:11,788 - ydk - INFO - Connected to 10.10.30.4 on port 830 using ssh with timeout of -1
2019-12-23 13:06:11,788 - ydk - INFO - Executing CRUD create operation on [bgp]
2019-12-23 13:06:11,788 - ydk - INFO - Executing 'edit-config' RPC on [bgp]
Traceback (most recent call last):
  File "test.py", line 74, in <module>
    crud.create(provider, bgp)
  File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 112, in helper
    return func(self, provider, entity, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/ydk/services/crud_service.py", line 49, in create
    return _crud_update(provider, entity, self._crud.create)
  File "/usr/local/lib/python3.6/dist-packages/ydk/services/crud_service.py", line 70, in _crud_update
    return crud_call(provider, entity)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 82, in handle_runtime_error
    _raise(_exc)
  File "/usr/local/lib/python3.6/dist-packages/ydk/errors/error_handler.py", line 54, in _raise
    exec("raise exc from None")
  File "<string>", line 1, in <module>
ydk.errors.YInvalidArgumentError:  ancestor for entity cannot be nullptr as one of the ancestors is a list. Path: bgp
2019-12-23 13:06:11,861 - ydk - INFO - Disconnected from device
2019-12-23 13:06:11,863 - ydk - DEBUG - Trace: Writing message (session 59296): 
<?xml version="1.0" encoding="UTF-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <close-session/>
</rpc>

2019-12-23 13:06:11,877 - ydk - DEBUG - Trace: Received message (session 59296): 
<nc:rpc-reply xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/19.2R0/junos" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
<nc:ok/>
</nc:rpc-reply>

That is expected result, because you missed building of network_instance and protocol lists. Besides, you need to start building python object from the top level entity to assure proper child-parent relationships in the entity hierarchy. It should be something like this:

    nis = oc_ni.NetworkInstances()
ni = oc_ni.NetworkInstances.NetworkInstance() # list element has 1 key
ni.name = 'default' # must define network instance key
nis.network_instance.append(ni) # must add network instance to the list

pr = oc_ni.NetworkInstances.NetworkInstance.Protocols.Protocol() # list element has 2 keys
pr.name = 'BGP-5' # must define protocol key
from ydk.models.openconfig import openconfig_policy_type as oc_policy
pr.identifier = oc_policy.BGP() # must define protocol key
ni.protocols.protocol.append(pr) # must add protocol to the list

# Also need to define protocol.config attributes
pr.config.name = 'BGP-5'
pr.config.identifier = oc_policy.BGP()
pr.config.enabled = True

bgp = pr.bgp # bgp is attribute of protocol and has already been instantiated above
config_bgp(bgp)

# Sanity check before CRUD operation (could be skipped)
codec_provider = CodecServiceProvider(type='xml')
codec = CodecService()
nis_xml = codec.encode(codec_provider, nis)

# Then in actual router configuration you can use non-top level entity 'bgp'
# or top level entity 'nis'; the Netconf RPC will be the same.

When building entities, I strongly suggest you to learn better corresponding model bundle API. You can learn it directly from source or leverage existing documentation.

Yan Gorelik
YDK Solutions

Ok, using CodecService I was able to build the RPC:

<network-instances xmlns="http://openconfig.net/yang/network-instance">
  <network-instance>
    <name>default</name>
    <protocols>
      <protocol>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
        <name>BGP-5</name>
        <config>
          <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
          <name>BGP-5</name>
          <enabled>true</enabled>
        </config>
        <bgp>
          <global>
            <config>
              <as>5</as>
            </config>
            <afi-safis>
              <afi-safi>
                <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                <config>
                  <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                  <enabled>true</enabled>
                </config>
              </afi-safi>
            </afi-safis>
          </global>
          <neighbors>
            <neighbor>
              <neighbor-address>10.10.30.6</neighbor-address>
              <config>
                <peer-group>EBGP</peer-group>
                <neighbor-address>10.10.30.6</neighbor-address>
              </config>
            </neighbor>
          </neighbors>
          <peer-groups>
            <peer-group>
              <peer-group-name>EBGP</peer-group-name>
              <config>
                <peer-group-name>EBGP</peer-group-name>
                <peer-as>6</peer-as>
              </config>
              <transport>
                <config>
                  <local-address>Loopback0</local-address>
                </config>
              </transport>
              <afi-safis>
                <afi-safi>
                  <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                  <config>
                    <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                    <enabled>true</enabled>
                  </config>
                </afi-safi>
              </afi-safis>
            </peer-group>
          </peer-groups>
        </bgp>
      </protocol>
    </protocols>
  </network-instance>
</network-instances>

Seems valid.

 

The full script:

import logging

from ydk.services import CodecService, CRUDService
from ydk.providers import CodecServiceProvider, NetconfServiceProvider
from ydk.models.openconfig import openconfig_bgp as oc_bgp
from ydk.models.openconfig import openconfig_network_instance as oc_ni
from ydk.models.openconfig import openconfig_policy_types as oc_policy
from ydk.models.openconfig import openconfig_bgp_types as oc_bgp_types
from ydk.filters import YFilter

from devices import DEVICES

logger = logging.getLogger('ydk')
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
formatter = logging.Formatter(("%(asctime)s - %(name)s - "
                               "%(levelname)s - %(message)s"))
handler.setFormatter(formatter)
logger.addHandler(handler)


def config_bgp(bgp):
    """Add config data to bgp object."""
    # global configuration
    bgp.global_.config.as_ = 5
    afi_safi = bgp.global_.afi_safis.AfiSafi()
    afi_safi.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.enabled = True
    bgp.global_.afi_safis.afi_safi.append(afi_safi)

    # configure IBGP peer group
    peer_group = bgp.peer_groups.PeerGroup()
    peer_group.peer_group_name = "EBGP"
    peer_group.config.peer_group_name = "EBGP"
    peer_group.config.peer_as = 6
    peer_group.transport.config.local_address = "Loopback0"
    afi_safi = peer_group.afi_safis.AfiSafi()
    afi_safi.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.afi_safi_name = oc_bgp_types.IPV6UNICAST()
    afi_safi.config.enabled = True
    # afi_safi.apply_policy.config.import_policy.append("POLICY3")
    # afi_safi.apply_policy.config.export_policy.append("POLICY1")
    peer_group.afi_safis.afi_safi.append(afi_safi)
    bgp.peer_groups.peer_group.append(peer_group)

    # configure IBGP neighbor
    neighbor = bgp.neighbors.Neighbor()
    neighbor.neighbor_address = '10.10.30.6'
    neighbor.config.neighbor_address = '10.10.30.6'
    neighbor.config.peer_group = "EBGP"
    bgp.neighbors.neighbor.append(neighbor)


if __name__ == '__main__':
    nis = oc_ni.NetworkInstances()
    ni = oc_ni.NetworkInstances.NetworkInstance()    # list element has 1 key
    ni.name = 'default'    # must define network instance key
    nis.network_instance.append(ni)   # must add network instance to the list

    pr = oc_ni.NetworkInstances.NetworkInstance.Protocols.Protocol()  # list element has 2 keys
    pr.name = 'BGP-5'  # must define protocol key
    pr.identifier = oc_policy.BGP()  # must define protocol key

    ni.protocols.protocol.append(pr)  # must add protocol to the list

    # Also need to define protocol.config attributes
    pr.config.name = 'BGP-5'
    pr.config.identifier = oc_policy.BGP()
    pr.config.enabled = True

    bgp = pr.bgp   # bgp is attribute of protocol and has already been instantiated above
    config_bgp(bgp)

    # codec = CodecService()
    # pr = CodecServiceProvider(type='xml')
    # print(codec.encode(pr, nis))
    device = DEVICES['junos']

    provider = NetconfServiceProvider(
        address=device['ip'],
        port=830,
        username='admin',
        password=device['pass'],
        protocol='ssh'
    )
    crud = CRUDService()
    crud.create(provider, nis)

But it fails before sending RPC. DEBUG is attached.

Here is the error:

2019-12-24 16:07:22,933 - ydk - ERROR - Data is invalid according to the yang model. Libyang error: Invalid keyword "[1-9][0-9]{1,2}|[1-9])|\*)"".

This is the same as this. It appears because Juniper incorrectly used escape character '\*' when modified the pattern string from original standard openconfig model. The correct use of escape character would be '\\*' or put the pattern string in single quotes. Although it is not YDK issue, I have added escape of this combination in our fork of Libyang. Please recompile the core YDK library and python package to get corrected version of Libyang and then repeat your script.

cd ydk-gen
python3 generate.py --core --cpp -is
python3 generate.py --core --python -is

 

Yan Gorelik
YDK Solutions

I've checked openconfig repo for https://github.com/openconfig/public/blob/master/release/models/vlan/openconfig-vlan-types.yang
It is updated on the 20th of April and RFC7950, Chapter 6.1.3 isn't there still.

Your fix made it able to send the RPC but it's behavior is similar to CSR1000v: it accepts it and sends ok as a reply.

2019-12-25 11:17:56,676 - ydk - INFO - Path where models are to be downloaded: /home/horseinthesky/.ydk/10.10.30.4
2019-12-25 11:17:56,686 - ydk - INFO - Connected to 10.10.30.4 on port 830 using ssh with timeout of -1
2019-12-25 11:17:56,686 - ydk - INFO - Executing CRUD create operation on [openconfig-network-instance:network-instances]
2019-12-25 11:17:56,687 - ydk - INFO - Executing 'edit-config' RPC on [openconfig-network-instance:network-instances]
2019-12-25 11:17:56,814 - ydk - INFO - ============= Sending RPC to device =============
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <target>
    <candidate/>
  </target>
  <config><network-instances xmlns="http://openconfig.net/yang/network-instance" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="merge">
  <network-instance>
    <name>default</name>
    <protocols>
      <protocol>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
        <name>BGP-5</name>
        <config>
          <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
          <name>BGP-5</name>
          <enabled>true</enabled>
        </config>
        <bgp>
          <global>
            <config>
              <as>5</as>
            </config>
            <afi-safis>
              <afi-safi>
                <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                <config>
                  <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                  <enabled>true</enabled>
                </config>
              </afi-safi>
            </afi-safis>
          </global>
          <neighbors>
            <neighbor>
              <neighbor-address>10.10.30.6</neighbor-address>
              <config>
                <peer-group>EBGP</peer-group>
                <neighbor-address>10.10.30.6</neighbor-address>
              </config>
            </neighbor>
          </neighbors>
          <peer-groups>
            <peer-group>
              <peer-group-name>EBGP</peer-group-name>
              <config>
                <peer-group-name>EBGP</peer-group-name>
                <peer-as>6</peer-as>
              </config>
              <transport>
                <config>
                  <local-address>Loopback0</local-address>
                </config>
              </transport>
              <afi-safis>
                <afi-safi>
                  <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                  <config>
                    <afi-safi-name xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">oc-bgp-types:IPV6_UNICAST</afi-safi-name>
                    <enabled>true</enabled>
                  </config>
                </afi-safi>
              </afi-safis>
            </peer-group>
          </peer-groups>
        </bgp>
      </protocol>
    </protocols>
  </network-instance>
</network-instances>
</config>
</edit-config>
</rpc>
2019-12-25 11:17:57,253 - ydk - INFO - ============= Received RPC from device =============
<?xml version="1.0"?>
<nc:rpc-reply xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/19.2R0/junos" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <nc:ok/>
</nc:rpc-reply>

2019-12-25 11:17:57,253 - ydk - INFO - Executing 'commit' RPC
2019-12-25 11:17:57,254 - ydk - INFO - ============= Sending RPC to device =============
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><commit xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/>
</rpc>
2019-12-25 11:17:58,110 - ydk - INFO - ============= Received RPC from device =============
<?xml version="1.0"?>
<nc:rpc-reply xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/19.2R0/junos" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2">
  <nc:ok/>
</nc:rpc-reply>

2019-12-25 11:17:58,110 - ydk - INFO - Operation succeeded
2019-12-25 11:17:58,118 - ydk - INFO - Disconnected from device

But it creates this section pf config:

root> show configuration openconfig-network-instance:network-instances 
network-instance default {
    protocols {
        protocol oc-pol-types:BGP BGP-5 {
            config {
                identifier BGP;
                name BGP-5;
                enabled true; ## Warning: 'enabled' is deprecated
            }
            bgp {
                global {
                    config {
                        as 5;
                    }
                    afi-safis {
                        afi-safi oc-bgp-types:IPV6_UNICAST {
                            config {
                                afi-safi-name IPV6_UNICAST;
                                enabled true;
                            }
                        }
                    }
                }
                neighbors {
                    neighbor 10.10.30.6 {
                        config {
                            peer-group EBGP;
                            neighbor-address 10.10.30.6;
                        }
                    }
                }
                peer-groups {
                    peer-group EBGP {
                        config {
                            peer-group-name EBGP;
                            peer-as 6;
                        }
                        transport {
                            config {
                                local-address Loopback0;
                            }
                        }
                        afi-safis {
                            afi-safi oc-bgp-types:IPV6_UNICAST {
                                config {
                                    afi-safi-name IPV6_UNICAST;
                                    enabled true;
                                }       
                            }
                        }
                    }
                }
            }
        }
    }
}

And I don't know how to use it

root> show bgp summary 
BGP is not running