Hi All
I am new to developing as you will see from my code :P, I am a network engineer trying to learn Devops, and I am struggling a bit with create services that apply configs to multiple devices.
I am trying to create my own code to create a l3vpn service and when I run it I get an error from the python code, I will post the code and error and if anyone can help in pointing me to the correct way, I would be most grateful.
Yang
module l3vpnpy {
namespace "http://example.com/l3vpnpy";
prefix l3vpnpy;
import ietf-inet-types {
prefix inet;
}
import tailf-common {
prefix tailf;
}
import tailf-ncs {
prefix ncs;
}
augment /ncs:services {
list l3vpnpy {
key customername;
uses ncs:service-data;
ncs:servicepoint l3vpnpy-servicepoint;
leaf customername {
type string;
}
leaf customerdescription {
type string;
}
leaf rd {
type string;
}
leaf-list rtexport {
type string;
}
leaf-list rtimport {
type string;
}
leaf prefixlimit {
type uint16;
}
leaf vlan {
type uint16;
}
leaf ipv4address {
type string;
}
leaf warningpercent {
type uint16;
}
list devices {
key device;
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
leaf ipv4address {
type string;
}
}
}
}
}
XML
<config-template xmlns="http://tail-f.com/ns/config/1.0">
<devices xmlns="http://tail-f.com/ns/ncs">
<device>
<name>{/devices/device}</name>
<config>
<vrf xmlns="urn:ios">
<definition>
<name>{/customername}</name>
<description>{/customerdescription}</description>
<rd>{/rd}</rd>
<address-family>
<ipv4>
<route-target>
<export>
<asn-ip>{/rtexport}</asn-ip>
</export>
<import>
<asn-ip>{/rtimport}</asn-ip>
</import>
</route-target>
<maximum>
<routes>
<limit>{/prefixlimit}</limit>
<warn-threshold>{/warningpercent}</warn-threshold>
</routes>
</maximum>
</ipv4>
</address-family>
</definition>
</vrf>
<interface xmlns="urn:ios">
<GigabitEthernet>
<name>2.{/vlan}</name>
<description>{/customerdescriptopn}</description>
<encapsulation>
<dot1Q>
<vlan-id>{/vlan}</vlan-id>
</dot1Q>
</encapsulation>
<vrf>
<forwarding>{/customername}</forwarding>
</vrf>
<ip>
<address>
<primary>
<address>{/devices/ipv4address}</address>
<mask>255.255.255.0</mask>
</primary>
</address>
<ospf>
<process-id>
<id>1</id>
<area>0</area>
</process-id>
</ospf>
</ip>
</GigabitEthernet>
</interface>
<router xmlns="urn:ios">
<bgp>
<as-no>65000</as-no>
<address-family>
<with-vrf>
<ipv4>
<af>unicast</af>
<vrf>
<name>{/customername}</name>
<redistribute>
<ospf>
<id>{/vlan}</id>
</ospf>
</redistribute>
</vrf>
</ipv4>
</with-vrf>
</address-family>
</bgp>
<ospf>
<id>{/vlan}</id>
<vrf>{/customername}</vrf>
<redistribute>
<bgp>
<as-no>65000</as-no>
</bgp>
</redistribute>
</ospf>
</router>
</config>
</device>
</devices>
</config-template>
Python
# -*- mode: python; python-indent: 4 -*-
import ncs
from ncs.application import Service
# ------------------------
# SERVICE CALLBACK EXAMPLE
# ------------------------
class ServiceCallbacks(Service):
# The create() callback is invoked inside NCS FASTMAP and
# must always exist.
@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')
vars = ncs.template.Variables()
for dev in service.devices:
device = root.devices.device[service.devices.device]
self.log.info('device: ', device.name)
template = ncs.template.Template(service)
template.apply('l3vpnpy-template', vars)
# The pre_modification() and post_modification() callbacks are optional,
# and are invoked outside FASTMAP. pre_modification() is invoked before
# create, update, or delete of the service, as indicated by the enum
# ncs_service_operation op parameter. Conversely
# post_modification() is invoked after create, update, or delete
# of the service. These functions can be useful e.g. for
# allocations that should be stored and existing also when the
# service instance is removed.
# @Service.pre_lock_create
# def cb_pre_lock_create(self, tctx, root, service, proplist):
# self.log.info('Service plcreate(service=', service._path, ')')
# @Service.pre_modification
# def cb_pre_modification(self, tctx, op, kp, root, proplist):
# self.log.info('Service premod(service=', kp, ')')
# @Service.post_modification
# def cb_post_modification(self, tctx, op, kp, root, proplist):
# self.log.info('Service premod(service=', kp, ')')
# ---------------------------------------------
# COMPONENT THREAD THAT WILL BE STARTED BY NCS.
# ---------------------------------------------
class Main(ncs.application.Application):
def setup(self):
# The application class sets up logging for us. It is accessible
# through 'self.log' and is a ncs.log.Log instance.
self.log.info('Main RUNNING')
# Service callbacks require a registration for a 'service point',
# as specified in the corresponding data model.
#
self.register_service('l3vpnpy-servicepoint', ServiceCallbacks)
# If we registered any callback(s) above, the Application class
# took care of creating a daemon (related to the service/action point).
# When this setup method is finished, all registrations are
# considered done and the application is 'started'.
def teardown(self):
# When the application is finished (which would happen if NCS went
# down, packages were reloaded or some error occurred) this teardown
# method will be called.
self.log.info('Main FINISHED')
Thanks to anyone that has time to have a flick through.
Andy