cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1750
Views
0
Helpful
1
Comments
Andrew Melsom
Level 1
Level 1

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

1 Comment
Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the NSO Developer community: