Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #446 from earies/yang-action-sros
Support for YANG 1.1 action + Nokia SROS devices
- Loading branch information
Showing
14 changed files
with
378 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#!/usr/bin/env python | ||
# | ||
|
||
import logging | ||
import sys | ||
|
||
from ncclient import manager | ||
from ncclient.xml_ import to_xml | ||
from ncclient.operations.rpc import RPCError | ||
|
||
_NS_MAP = { | ||
'nc': 'urn:ietf:params:xml:ns:netconf:base:1.0', | ||
'nokia-conf': 'urn:nokia.com:sros:ns:yang:sr:conf' | ||
} | ||
|
||
_NOKIA_MGMT_INT_FILTER = ''' | ||
<configure xmlns="%s"> | ||
<system> | ||
<management-interface/> | ||
</system> | ||
</configure> | ||
''' % (_NS_MAP['nokia-conf']) | ||
|
||
def connect(host, port, user, password): | ||
m = manager.connect(host=host, port=port, | ||
username=user, password=password, | ||
device_params={'name': 'sros'}, | ||
hostkey_verify=False) | ||
|
||
## Retrieve full configuration from the running datastore | ||
running_xml = m.get_config(source='running') | ||
logging.info(running_xml) | ||
|
||
## Retrieve full configuration from the running datastore and strip | ||
## the rpc-reply + data elements | ||
running_xml = m.get_config(source='running').xpath( | ||
'/nc:rpc-reply/nc:data/nokia-conf:configure', | ||
namespaces=_NS_MAP)[0] | ||
logging.info(to_xml(running_xml, pretty_print=True)) | ||
|
||
## Retrieve full configuration from the running datastore and strip | ||
## out elements except for /configure/system/management-interface | ||
running_xml = m.get_config(source='running').xpath( | ||
'/nc:rpc-reply/nc:data/nokia-conf:configure' \ | ||
'/nokia-conf:system/nokia-conf:management-interface', | ||
namespaces=_NS_MAP)[0] | ||
logging.info(to_xml(running_xml, pretty_print=True)) | ||
|
||
## Retrieve a specific filtered subtree from the running datastore | ||
## and handle any rpc-error should a portion of the filter criteria | ||
## be invalid | ||
try: | ||
running_xml = m.get_config(source='running', | ||
filter=('subtree', _NOKIA_MGMT_INT_FILTER), | ||
with_defaults='report-all').xpath( | ||
'/nc:rpc-reply/nc:data/nokia-conf:configure', | ||
namespaces=_NS_MAP)[0] | ||
logging.info(to_xml(running_xml, pretty_print=True)) | ||
|
||
except RPCError as err: | ||
logging.info('Error: %s' % err.message.strip()) | ||
|
||
m.close_session() | ||
|
||
if __name__ == '__main__': | ||
LOG_FORMAT = '%(asctime)s %(levelname)s %(filename)s:%(lineno)d %(message)s' | ||
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=LOG_FORMAT) | ||
|
||
try: | ||
connect(sys.argv[1], '830', 'admin', 'admin') | ||
|
||
except IndexError: | ||
logging.error('Must supply a valid hostname or IP address') | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#!/usr/bin/env python | ||
# | ||
# For Nokia SR OS > 20.10, support for issuing a subset of CLI commands | ||
# (e.g. 'show', 'admin', 'clear', 'ping', etc..) over NETCONF RPCs is | ||
# achieved by the use of the <md-cli-raw-command> YANG 1.1 action | ||
|
||
import logging | ||
import sys | ||
|
||
from ncclient import manager | ||
from ncclient.operations.rpc import RPCError | ||
|
||
_NS_MAP = { | ||
'nc': 'urn:ietf:params:xml:ns:netconf:base:1.0', | ||
'nokia-oper': 'urn:nokia.com:sros:ns:yang:sr:oper-global' | ||
} | ||
|
||
def connect(host, port, user, password): | ||
m = manager.connect(host=host, port=port, | ||
username=user, password=password, | ||
device_params={'name': 'sros'}, | ||
hostkey_verify=False) | ||
|
||
## Issue 'show card' and display the raw XML output | ||
result = m.md_cli_raw_command('show card') | ||
logging.info(result) | ||
|
||
## Issue 'show port' from MD-CLI context and emit only | ||
## the returned command contents | ||
result = m.md_cli_raw_command('show port') | ||
output = result.xpath( | ||
'/nc:rpc-reply/nokia-oper:results' \ | ||
'/nokia-oper:md-cli-output-block', | ||
namespaces=_NS_MAP)[0].text | ||
logging.info(output) | ||
|
||
## Issue 'show version' from Classic CLI context and emit | ||
## only the returned command contents | ||
result = m.md_cli_raw_command('//show version') | ||
output = result.xpath( | ||
'/nc:rpc-reply/nokia-oper:results' \ | ||
'/nokia-oper:md-cli-output-block', | ||
namespaces=_NS_MAP)[0].text | ||
logging.info(output) | ||
|
||
## Issue 'ping' from MD-CLI context and emit only the | ||
## returned command contents | ||
result = m.md_cli_raw_command( | ||
'ping 127.0.0.1 router-instance "Base" count 3') | ||
output = result.xpath( | ||
'/nc:rpc-reply/nokia-oper:results' \ | ||
'/nokia-oper:md-cli-output-block', | ||
namespaces=_NS_MAP)[0].text | ||
logging.info(output) | ||
|
||
## Issue an admin command that returns only NETCONF <ok/> or | ||
## <rpc-error/> | ||
result = m.md_cli_raw_command('admin save') | ||
try: | ||
if len(result.xpath('/nc:rpc-reply/nc:ok', namespaces=_NS_MAP)) > 0: | ||
logging.info('Admin save successful') | ||
else: | ||
logging.info('Admin save unsuccessful') | ||
|
||
except RPCError as err: | ||
logging.info('Error: %s' % err.message.strip()) | ||
|
||
|
||
## Issue an unsupported command and handle the RPC error gracefully | ||
try: | ||
result = m.md_cli_raw_command('configure') | ||
if len(result.xpath('/nc:rpc-reply/nc:ok', namespaces=_NS_MAP)) > 0: | ||
logging.info('Command successful') | ||
else: | ||
logging.info('Command unsuccessful') | ||
|
||
except RPCError as err: | ||
logging.info('Error: %s' % err.message.strip()) | ||
|
||
m.close_session() | ||
|
||
if __name__ == '__main__': | ||
LOG_FORMAT = '%(asctime)s %(levelname)s %(filename)s:%(lineno)d %(message)s' | ||
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=LOG_FORMAT) | ||
|
||
try: | ||
connect(sys.argv[1], '830', 'admin', 'admin') | ||
|
||
except IndexError: | ||
logging.error('Must supply a valid hostname or IP address') | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from lxml import etree | ||
|
||
from .default import DefaultDeviceHandler | ||
from ncclient.operations.third_party.sros.rpc import MdCliRawCommand | ||
from ncclient.xml_ import BASE_NS_1_0 | ||
|
||
|
||
def passthrough(xml): | ||
return xml | ||
|
||
class SrosDeviceHandler(DefaultDeviceHandler): | ||
""" | ||
Nokia SR OS handler for device specific information. | ||
""" | ||
|
||
def __init__(self, device_params): | ||
super(SrosDeviceHandler, self).__init__(device_params) | ||
|
||
def get_capabilities(self): | ||
"""Set SR OS device handler client capabilities | ||
Set additional capabilities beyond the default device handler. | ||
Returns: | ||
A list of strings representing NETCONF capabilities to be | ||
sent to the server. | ||
""" | ||
base = super(SrosDeviceHandler, self).get_capabilities() | ||
additional = [ | ||
'urn:ietf:params:xml:ns:netconf:base:1.0', | ||
'urn:ietf:params:xml:ns:yang:1', | ||
'urn:ietf:params:netconf:capability:confirmed-commit:1.1', | ||
'urn:ietf:params:netconf:capability:validate:1.1'] | ||
return base + additional | ||
|
||
def get_xml_base_namespace_dict(self): | ||
return {None: BASE_NS_1_0} | ||
|
||
def get_xml_extra_prefix_kwargs(self): | ||
d = {} | ||
d.update(self.get_xml_base_namespace_dict()) | ||
return {"nsmap": d} | ||
|
||
def add_additional_operations(self): | ||
operations = { | ||
'md_cli_raw_command': MdCliRawCommand | ||
} | ||
return operations | ||
|
||
def perform_qualify_check(self): | ||
return False | ||
|
||
def transform_reply(self): | ||
return passthrough |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from ncclient.xml_ import * | ||
|
||
from ncclient.operations.rpc import RPC | ||
|
||
def global_operations(node): | ||
"""Instantiate an SR OS global operation action element | ||
Args: | ||
node: A string representing the top-level action for a | ||
given global operation. | ||
Returns: | ||
A tuple of 'lxml.etree._Element' values. The first value | ||
represents the top-level YANG action element and the second | ||
represents the caller supplied initial node. | ||
""" | ||
parent, child = yang_action('global-operations', | ||
attrs={'xmlns': SROS_GLOBAL_OPS_NS}) | ||
ele = sub_ele(child, node) | ||
return (parent, ele) | ||
|
||
class MdCliRawCommand(RPC): | ||
def request(self, command=None): | ||
node, raw_cmd_node = global_operations('md-cli-raw-command') | ||
sub_ele(raw_cmd_node, 'md-cli-input-line').text = command | ||
self._huge_tree = True | ||
return self._request(node) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.