...
Anuta ATOM

ATOM Development Guide – Service – 11.9

Table of Contents

ATOM Platform Guide – Service

Modeling

version 11.9

Table of Contents

Outline of the document5

Intended Audience5

Overview of Modelling in ATOM7

How Service Modeling Works8

Service Package Development8

Create the Service package8

Update the Dependencies & Version in build.gradle10

Yang Modelling and Service Logic11

Archive the Service Package11

Service Yang Modeling and Logic12

Contents of a Service package12

Procedure for Modelling & Defining Logic12

Create a Service model .yang file12

AutoGenerate & Define Service logic in Python16

Create (Codegen)20

Update (AutoUpdate)21

Delete (AutoDelete)21

Extending Service Model & Custom Logic21

Deploying & Operating Service Packages24

Deploying a Service Package24

Testing the Service Package25

Upgrading Service package27

Exercise: L2Edge Service Modeling29

Exercise: L3 Service Service Modeling36

Appendix45

ATOM Schema Browser45

Example45

ATOM Extensions to YANG48

YANG Validations & Constraints49

Library Utils for Service Modelling51

ATOM SDK58

Introduction58

Folder hierarchy58

Setting up the environment for ATOM Package Plugin59

Prerequisites59

Setting up the environment in Ubuntu59

Setting up the environment in Windows59

Setting up the environment in Centos60

Setting up the repository for developing packages62

Tasks for developing packages65

General Gradle tasks65

ATOM specific tasks66

generateServicePackage69

generateDevicePyBinds71

Running ATOM Package Plugin Tasks80

Running Tasks in IDE80

Running Tasks in CLI81

Troubleshoot & FAQs – Service Modelling81

Errors during package upload into ATOM81

Package Deletion Error83

Logging Level for Task Logs84

Handler maps84

Registering the Service Package with ATOM85

Binding of the logic with ATOM86

Syntax Errors in Python plugin file87

Semantic Errors in the Service package files88

Attribute Error91

Sorting of Create/Delete commands:93

IPAM Pools integration with services:94

VLAN Pools integration with services:97

Outline of the document

ATOM Platform provides users to develop various extensions to out-of-the box capabilities.

  • Device Drivers – Device Drivers allow ATOM to work with devices to Collect configuration, Provision Configuration, Collect Performance & Other Operational Data, Execute Show and Diagnostic Commands.
    • Configuration Discovery & Provisioning
    • Performance & Inventory Collection (SNMP, SNMP Trap, Syslog, Telemetry)
  • Network Automation
    • Stateful Services like Application Delivery, L3 VPN, L2 VPN, Day0, Cloud Interconnect etc.,
    • MOP Automation like Software Upgrade, Password Rotation etc.,

This document covers Network Automation Stateful Services Development flows that have the following life cycle:

  • Create – Create a green field service
  • Update – Update Service. This may be repeated multiple times
  • Delete – Retire the service Following is a high level breakdown of the content:
  • Working with Development tooling
  • Services Development against ATOM platform
  • Deploying, Upgrading & Operating Services in ATOM

In the Appendix, additional examples, extensions, library utils and FAQs are available in detail.

Intended Audience

This document is meant for the reader who is interested in developing network services or applications against ATOM.

ATOM relies heavily on YANG modeling language and RESTCONF. Hence, a good knowledge of

YANG and working knowledge of RESTCONF are required.

Service logic is implemented in python hence good working knowledge of python is required.

ATOM SDK is built on top of the Gradle build system. This document explains the build commands in detail.

YANG : https://tools.ietf.org/html/rfc7950 RESTCONF : https://tools.ietf.org/html/rfc8040 Gradle : https://gradle.org/

Overview of Modelling in ATOM

Anuta ATOM platform with it’s layered, YANG model driven approach helps in delivering vendor neutral, extensible and maintainable network services for multiple domains such as branch/CPE, Data Center, Cloud, and Carrier Core networks.

Network Service or application development involves the following major components:

  • Device Model (Not required for Native/Openconfig Models)
    • Abstracted object model defined using IETF YANG
    • Defined once for each device feature or function
  • Vendor Plugin (Not required for Native/Openconfig Models)
    • Common model mapped to vendor specific CLI or API
    • Defined once for each vendor or OS type of a platform
  • Service Model
    • Service description in YANG
    • Mapping to Device models
    • Glue logic to augment service model & mappings with business logic (Optional)

ATOM SDK and Platform provides a full life cycle for network services & apps in – Design, Develop, Package, Deploy, Test, Upgrade.

Each of the individual blocks covered under ATOM SDK development are illustrated below:

How Service Modeling Works

Service Package Development

Create the Service package

After the successful one time setup of the ATOM SDK environment (Refer Appendix section

ATOM SDK), you can create packages of your choice.

  • Run the command to create the requisite package:

create.py: This script helps you create different types of package; service package, device package, or device driver package.

  • Select the type SERVICE_MODEL package type as shown below:

  • Enter the name of the package and other inputs as shown below

After the successful run of the above build, the service package folder structure for service development purpose is created. The service package folder contains the following artifacts

Update the Dependencies & Version in build.gradle

After a successful creation of a package, there could be some additional package(s) required as ‘dependencies’. Accordingly modify the default dependencies listed in the build.gradle file, which is located in the root level of the created package.

In scenarios where service performs API invocations against Device or other Models, make sure dependency of that respective model package is there along with the servicemodel package which the library utils.

Let’s consider a Service which performs invocations against Juniper Device Models, then make sure dependencies of servicemodel-7.0.4.0, juniper-8.0.0.1, juniper_cli-8.0.0.1 are mentioned as

below. (The package names are a combination of the name of the package and the version number separated by a hyphen)

Resolve the dependencies

Run the command : gradle build –refresh-dependencies

Successful execution of this command ensures that the dependencies mentioned in the

build.gradle file are mapped fine.

Update the version

In the “build.gradle” file, metadata about the package is present in the version & packageXml object. Update the version based on the revision of the service package you are working on.

Yang Modelling and Service Logic

Network Service modelling and defining of Service logic in python can be done within the model and scripts folder respectively of the created service package structure. Refer to Service Modelling section for detailed procedure of it.

Archive the Service Package

Once the modelling and service logic are defined in the respective package structure, use the gradle task “gradle archive” for creating the uploadable zip with its dependencies.

The zip will be stored in the build folder and is ready for Upload to ATOM.

Service Yang Modeling and Logic

Contents of a Service package

The service package which can be uploaded into ATOM as a zip format typically contains the following entities:

  • The model folder contains the following:
    • <service_name>.yang file – Contains the schema of the service defined in YANG
  • The scripts folder contains python based service logic consiqueting following files typically:
    • <service_name>.py – Contains the logic binding of the service to the device

Generates the device model operations with reference to the service defined in the yang model file and also registers service in ATOM

    • plugin.py – Code for adding the service as a new plug-in to ATOM
    • _init_py – Required to make ATOM treat the directories as containing packages
  • The package.xml file contains the metadata about the service.
    • Information such as package name, version, module name, type and description should be provided.

This section outlines the procedure for creating, deploying, and testing a service package built by using the ATOM SDK.

Procedure for Modelling & Defining Logic

Follow these steps for creating a service package:

  • Define the service model file – write the service.yang
    • Add Yang validations & constraints for building intelligence in the model
    • Define ATOM extensions useful to map service node to device node
    • Above extensions will help for codegen in step2
  • AutoGenerate service logic using SDK & Define any custom logic in python

Let us take an example of building a service package (day0service package) from service.yang file (day0config.yang) using Plugin Tasks for package development. This day0service is intended to deploy some of the day0 features on the device after it was plugged into the lab with management reachability.

Create a Service model .yang file

  • Extract the provided ATOM SDK .zip and Setup the environment as per steps mentioned in Setting up the environment for package development.
  • Select the required package type as SERVICE_MODEL.
  • Give the name of the service model: day0config

After the successful run of the build, the service package, day0config gets created.

  • Take reference of the .yang present in the examples folder of ATOMSDK to develop day0config.yang service model and place it day0config package path day0config/src/main/model. This model is for creating multiple user login a/c’s on the device as part of day0 configurations to be done on the device.

import user { prefix cu;

}

import ncx-extensions { prefix n-ext;

}

organization “Anuta Networks”; description

“This module contains a collection of YANG definitions for day0 configuration “;

revision 2016-06-16 { description

“Initial revision”;

}

augment “/ac:services” { container day0services { list day0service {

key “name”; leaf name { type string; description “string”;

}

leaf device-ip { type leafref {

path “/ac:devices/ac:device/ac:id”;

}

mandatory true; description “device-ip”;

}

container users { list user {

key “name”;

  • In the above yang model we can see various Yang Constraints and ATOM extensions added to bring intelligence into the model and enhance the capabilities of ATOM UI/platform and SDK.

AutoGenerate & Define Service logic in Python

For any given service.yang ATOM SDK has the capability to generate service package structure and the required files for service logic by using python libraries available at atomsdk/packages/servicemodel/scripts/. For detailed reading on python libraries refer to the Appendix section Library Utils for Service Modelling.

SDK can auto generate python based business logic completely where custom logic addition is not required at all. To utilize the functionality of the full code generation, use the extension, maps-to, for all leaf nodes in a service.yang file.

Example: n-ext:maps-to <device model x-path/rc-path>

Few more ATOM yang extensions relevant to UI and code-generation refer to the Appendix section ATOM Extensions to yang.

To generate a service package, make sure the service yang is inside the directory ‘src/main/model’. The user has the flexibility to generate the output in ‘build/generated’ or in ‘src/main’ itself. For details refer plugin task.

Change to current directory i.e. the service package directory and run the commands

gradle tasks –all (this will display all the tasks)

gradle generateServicePackage(Runs the ServicePackage generate task)

Verify the package is created in the destination folder with below folders and file:

In the Scripts folder, multiple python files and folders are generated as explained below:

  • A sample of the plugin.py file that is required for registering and unregistering of package to ATOM is shown below:

  • A sample of the “day0config.py” file is as below and explained:
Import Block:

Below block represents importing library servicemodel.util, servicemodel.yang and servicemodel.devicemgr

Handler-Maps

Every use-case contains one main file, here day0config.py with its class DAY0CONFIGService() having handler maps as below.

Significance of Handler-Maps: When client enters data from UI or from RESTCONF Client of any entity (container or list) in usecase, respective handler map is called from python glue logic. Each handler-map is associated with its entity class definition.

  • The supporting methods specific to this service package are available in the form of “day0config_lib.py” file. In addition to these, you can add any other lib python modules, if required for this service package.

When ATOM SDK is used for code generation of a service.yang file, it will generate a folder hierarchy within the scripts folder of the generated package as per yang tree structure.

For each folder there will be a service_customization.py file to add modifications required in auto generated python service logic. For example, a user model which is of a yang type list will have the following file structure.

Below we can see the structure of code generated within these files.

Class Structure Hierarchy

The structure of the User class is shown below:

Create (Codegen)

When a client creates the service from UI or via RESTCONF, the payload is sent as an input to the create() block of service code as sdata. ATOM Platform keeps track of all the references for device entries/entities it created during a service create operation.

‘create’ code contains below basic structure of generated code

Fetching input values

The input values sent by the client to the python glue logic is captured in inputdict as shown in the following snippet of the code:

Create logic using input values

The input values given for service yang leafs are assigned to respective leaf variables of device models based on the maps-to statement defined for that service yang leaf. This mapping is maintained in a dictionary called mapping_dict.

Create method requires this mapping_dict as one input along with sdata, dev(which is device object), and addReference.

In the above we see the create method present in library servicemodel.device_abs_lib.users.user is invoked which is based on the maps-to statements defined in the service yang. This create method translates to device entity creation in ATOM with reference held in the platform based on addReference being True/False.

In case the developer wants to code additional custom logic for service Create, he can do it on top of generated code within the create() block.

Update (AutoUpdate)

When a client tries to edit an existing service entry, then the payload is sent as an input to the create() block itself as sdata. The code within the create itself will be executed with latest updated service parameter values.

ATOM platform handles the update on device entries/entities automatically using the references it had previously. Hence ATOM as a platform gives AutoUpdate functionality.

In case the developer wants to code additional custom logic for service Update without affecting Create logic, he can still do it using a flag sdata.autoupdate which gets set as True when client did an update of service entry. Hence the update specific code customization can be added under if (sdata.autoupdate) within the create block itself.

Delete (AutoDelete)

With the service entity deleted, ATOM Platform handles the delete of device entries/entities automatically using the references it had previously. Hence the ATOM as a platform gives AutoDelete functionality.

In case the developer wants to code additional custom logic for service Delete, he can still do it by having delete() definition defined.

Extending Service Model & Custom Logic

Let us take an example of adding an extra day0 feature (dns-name-server) to the existing

day0service. The service logic should be modified to accommodate the changes in the service thereby extending the service model.

  • Open the day0config.yang file present in src/main/model and add the dns-name-server list entry as shown below.
  • Extend the day0config.yang as shown below:

  • For the service.yang generate service package using ATOM SDK
    • Change to current directory i.e /ServicePackage
    • Run the commands

  • Verify the package is updated with new service logic and new folders.
    • Open the “name_server.py” file (in the

<pkg>/scripts/day0services/day0service/dns/name_server folder) and look for the existing python logic.

As ATOM Extensions of the ‘maps-to’ attribute has not been added for the name-server, the python logic is not fully complete. The logic does not contain the device bindings and the corresponding payload.

  • Add the required custom logic in the “service_customization.py” file (in the
<pkg>/scripts/day0services/day0service/dns/name_server folder).

Add the missing name-server device bindings and then the create operation with name-server payload.

An excerpt of the code from the def process_service_device_bindings of the “service_customization.py” file is shown below:

  • Open the build.gradle and upgrade service package by modifying value of version field from 7.0.0.0 to 7.0.1.0

  • This package can be archived and uploaded to ATOM for use. For archiving manually zip the model, scripts folders, and the package.xml and upload to ATOM.

For archiving using SDK, change to the directory level of package and run command:

gradle archive

Deploying & Operating Service Packages

Deploying a Service Package

  • Considering the previously created day0config service, Upload the day0config.zip into ATOM.
  • Click Add package and upload the day0config.zip and click the OK button.

If any error occurs, verify if all the dependent packages are uploaded and registered in ATOM.

  • Load the Service Package

To load day0config.zip in ATOM, select the package in the list and click the Load button and verify that the service package is in “Active” state (true) as shown below.

  • All the above manual steps can be done using SDK gradle cmds.

gradle load (to upload package to ATOM)

gradle activate (to activate package, sets active = true) gradle deactivate (to deactivate package, sets active = false)

  • For Extending/Migrating the existing day0config-7.0.0.0.zip to day0config-7.0.1.0.zip,

refer to the section, “Upgrading Service packages”

Testing the Service Package

  • Navigate to Automation > Services to instantiate the day0service service. Click on day0services below

  • Fill the form and click on the OK button
  • Successfully created day0 service entry can be seen below,

  • To view details of the task associated with service creation, go to Task viewer and look for DataModel Create:day0service task. Select the task and click on the Details option to see the details of the service created. We will be able to see the details of what are sent

as input to day0service.

  • Commands generated for day0service can also be viewed in the Task Details:

Upgrading Service package

  • Service packages can be upgraded to newer versions without disrupting the ATOM.
  • Add the required modifications to the existing service package and tag changes with appropriate version number in the respective build.gradle file.

  • Create the zip of the required service package to be upgraded.

  • The package can be upgraded in the ATOM using below gradle task:
gradle upgrade

This gradle upgrade task will do following steps:

    • Enable’s maintenance mode on ATOM
    • Load the package need to be upgraded
    • Activates the Package and then disables maintenance mode.

  • Look for the ‘Active’ state status of the upgraded package.
  • Observe that the status of the Base package (version 7.0.0.0) is set to FALSE and the upgraded package status is set to TRUE(version 7.0.1.0).

Exercise: L2Edge Service Modeling

This section describes the procedure for creating a service package for L2Edge service. (in this example, l2edge.yang is modelled to configure an interface as L2 interface-types access/trunk with respective vlans)

  • Extract the provided atomsdk zip and create a service package environment by selecting option of type SERVICE_MODEL and package name as l2edge as per Creating a Package using SDK.
  • Create l2edge.yang under src/main/model
  • Put below content in l2edge.yang

import sdk-extensions { prefix s-ext;

}

description

“This module provides the l2-edge service”;

revision 2018-06-19 { description

“Initial revision.”;

}

augment “/ac:services” { list l2-edge {

n-ext:ncx-service;

n-ext:ncx-auto-update “ENTITY_LEVEL”;

description “Provides configuration for l2-edge ports.The l2-edge service provides network connectivity for end hosts”;

key name; leaf name {

description “Name of the l2-edge service”; type string;

}

leaf description {

description “Description of the user of the service (port description)”; type string;

}

container devices {

description “Devices that should form an l2-edge service.”; list device {

description “Device the port should be configured on.”; key name;

unique “device-id interface-name”; leaf name {

type string;

}

leaf device-id {

type leafref {

path “/ac:devices/ac:device/ac:id”;

}

}

leaf unit { type uint32; description

“unit value”;

n-ext:maps-to “/jcr:configuration/jci:interfaces/jci:interface/jci:unit/jci:name”{ s-ext:device-platform “JUNOS”;

}

}

leaf variant {

type enumeration { enum “trunk”; enum “access”;

}

default “trunk”;

n-ext:non-updatable; n-ext:maps-to

“/jcr:configuration/jci:interfaces/interface[jci:name=current()/../interface-name]/unit[jci:name=current()

/../unit]/family/ethernet-switching/port-mode”{ s-ext:device-platform “JUNOS”;

}

n-ext:maps-to

“/jcr:configuration/jci:interfaces/interface[jci:name=current()/../port-channel-id]/unit[jci:name=current()

/../unit]/family/ethernet-switching/port-mode”{ s-ext:device-platform “JUNOS”;

}

}

leaf interface-name {

description “Interface for the l2-edge service”; type string {

n-ext:atom-leafref-path

“/ac:devices/ac:device[ac:id=current()/../device-id]/jcr:configuration/jci:interfaces/jci:interface/jci:name”

;

}

mandatory true;

n-ext:maps-to “/jcr:configuration/jci:interfaces/interface/name”{ s-ext:device-platform “JUNOS”;

}

n-ext:ncx-add-reference-false;

}

must

‘(count(/ac:services/l2edge:l2-edge/devices/device[device-id=current()/device-id]/interface-name[interfa ce-name=current()/interface-name]) < 2)’ {

error-message “Interface Name already used”;

}

leaf native-vlan {

description “Native VLAN that is configured when trunk ports are used”; type int16 {

range 1..4094;

}

mandatory true;

when “../variant = ‘trunk'”;

n-ext:maps-to “/jcr:configuration/jcv:vlans/vlan/vlan-id”{ s-ext:device-platform “JUNOS”;

}

n-ext:ncx-maps-to-expr “/jcr:configuration/jcv:vlans/vlan/name = Vlancurrent()”{ s-ext:device-platform “JUNOS”;

}

n-ext:maps-to

“/jcr:configuration/jci:interfaces/interface/unit/family/ethernet-switching/native-vlan-id”{ s-ext:device-platform “JUNOS”;

}

}

container vlans {

description “List of vlans permitted on the l2-edge ports”; leaf-list vlan-id {

type int16 { range 2..4094;

}

min-elements 1;

n-ext:maps-to “/jcr:configuration/jcv:vlans/vlan/vlan-id”{ s-ext:device-platform “JUNOS”;

}

n-ext:ncx-maps-to-expr “/jcr:configuration/jcv:vlans/vlan/name = Vlancurrent()”{ s-ext:device-platform “JUNOS”;

}

  • Using ATOM sdk plugin task generate the service package code for l2edge.yang as below.

Change to current directory i.e. the service package directory & run the commands

gradle tasks –all (this will display all the tasks )

gradle generateServicePackage(Runs the ServicePackage generate task )

  • Now the scripts folder has the auto-generated code. This code will have device mapping code as well since the yang has mappings between service leafs and device model leafs using maps-to statement.
  • Now we need to generate pybinds specific to device mappings:

gradle gDPB

  • Change to the current directory, i.e., servicepackage and run:

gradle archive

  • Uploading l2edge service package zip to ATOM

Navigate to Administration > Plugins & Extensions > Packages > Add

On successful upload of the package, the following is displayed on the screen:

  • To Activate the l2edge package by selecting from list of packages using search box as below

After entering ‘l2edge’ key in search box hit the enter button to get the result

Select the package and hit Activate button

After Active Package completion, notice Active state changed to true.

  • Creating the l2edge through ATOM Navigate to Automation > Services

In the Catalog pane, click the l2edge:l2-edge > click + to add the l2edge.

In the Create l2edge, fill the values in the properties displayed in the form:

Click ✅ to instantiate the service.

To track the service, Go to Administration -> Tasks and Events and find for the tasks created:

To view the commands generated for this service, click the view button

Exercise: L3 Service Service Modeling

This section describes the procedure for creating service package for a L3 service (in this example, l3service.yang is modelled to configure an interface either as l3/sub/vlan and make it part of a vrf and assign IP)

  • Extract the provided atomsdk zip and create a service package environment by selecting the option of type SERVICE_MODEL and package name as l3service as per Creating a Package using SDK.
  • Create l3service.yang under src/main/model
  • Put below content in l3service.yang

module l3service {

namespace “https://anutanetworks.com/l3service“; prefix l3service;

import ietf-inet-types { prefix inet;

}

import ncx-extensions { prefix n-ext;

}

import sdk-extensions { prefix s-ext;

}

import controller { prefix ac;

}

import interface { prefix ai;

}

import l2features { prefix l2;

}

import l3features { prefix l3;

}

import ncx-types { prefix nt;

}

organization “Anuta Networks”;

revision 2014-07-01 { description

“Initial revision”;

}

typedef interface-mode-type { type enumeration {

enum “sub-interface”; enum “l3-interface”; enum “vlan”;

}

}

grouping l3service { leaf service-status { type string; description

“string”; config false;

default “AVAILABLE”;

}

leaf name { type string; description “string”;

mandatory true;

}

leaf device-id { type leafref {

path “/ac:devices/ac:device/ac:id”;

}

description “device-id”; mandatory true;

}

leaf interface-mode {

type interface-mode-type; description

“sub-interface l3-interface vlan

“;

mandatory true; n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/mode”;

}

leaf interface { type leafref {

path “/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/ai:interface/ai:long-name”;

}

description “interface”;

when “../interface-mode = ‘sub-interface’ or ../interface-mode = ‘l3-interface’ “;

n-ext:ncx-maps-to-expr “/ac:devices/device/ai:interfaces/interface/long-name = current()”; n-ext:ncx-maps-to-expr “/ac:devices/device/ai:interfaces/interface/name = current()”;

s-ext:ncx-maps-to-expr-when “../interface-mode = ‘l3-interface'”;

n-ext:ncx-add-reference-when “../interface-mode = ‘sub-interface’ or ../interface-mode = ‘vlan'”; n-ext:non-updatable;

}

leaf description { type string; description “string”;

n-ext:maps-to “/ac:devices/ac:device[ac:id=current()/../device-id]/l2:vlans/l2:vlan/l2:name”;

n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/description”;

}

leaf vrf { type string; description “string”;

n-ext:maps-to “/ac:devices/ac:device[ac:id=current()/../device-id]/l3:vrfs/l3:vrf/l3:name”;

n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/vrf”;

}

leaf vlan-id { type uint32 {

range “1..4096”;

}

description “1..4096”;

mandatory true;

n-ext:maps-to “/ac:devices/ac:device[ac:id=current()/../device-id]/l2:vlans/l2:vlan/l2:id”; n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/vlan”;

when “../interface-mode = ‘sub-interface’ or ../interface-mode = ‘vlan’ “;

n-ext:ncx-maps-to-expr “/ac:devices/device/ai:interfaces/interface/long-name = Vlan+current()”; n-ext:ncx-maps-to-expr “/ac:devices/device/ai:interfaces/interface/name = Vlan+current()”;

s-ext:ncx-maps-to-expr-when “../interface-mode = ‘vlan'”;

}

leaf ip-address {

type inet:ipv4-address; description

“Valid IPv4 Address (A.B.C.D for e.x: 172.16.1.1)”;

n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/ip-address”;

}

leaf netmask {

type inet:ipv4-address; description

“Valid IPv4 Address (A.B.C.D for e.x: 172.16.1.1)”;

n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/netmask”;

}

leaf ipv6-address {

type inet:ipv6-address; description

“Valid IPv6 Address (X::Y for e.x: 2001::1)”;

n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../device-id]/ai:interfaces/interface[long-name=current()/../interfa ce]/ipv6-address”;

}

leaf ipv6-prefix-length { type nt:ipv6-prefix-length; description

“IPv6 netmask in CIDR notation.”;

  • Using ATOM sdk plugin task generate the service package code for l3service.yang as below

Change to current directory i.e. the service package directory & run the commands

gradle tasks –all (this will display all the tasks )

gradle generateServicePackage(Runs the ServicePackage generate task )

  • Now the scripts folder has the auto-generated code. This code will have device mapping code as well since the yang has mappings between service leafs and device model leafs using maps-to statement.
  • Change to the current directory, i.e., servicepackage and run:

gradle archive

  • Uploading l3service service package zip to ATOM

Navigate to Administration > Plugins & Extensions > Packages > Add

On successful upload of the package, the following is displayed on the screen:

  • To Activate the l3service package by selecting from the list of packages using search box as below.After entering ‘l3service’ or ‘l3’ key in search box hit the enter button to give the result and Select the package and hit the Activate button.

After Active Package completion, notice Active state changed to true.

  • Creating the l3service through ATOM Navigate to Automation > Services

In the Details pane, click the L3service icon > click Add L3service.

In the Create l3service pane, fill the values in the properties displayed in the form:

Click OK to instantiate the service.

To track the service, Go to Administration -> Tasks and Events and find for the tasks created:

To view the commands generated for this service, click the view button

Appendix

ATOM Schema Browser

Using the Schema Browser, you can browse the YANG schema (object tree) to derive the relative path for the modelled entities in ATOM. Using this utility, you can look at all the ATOM entities that have been modelled in YANG. Apart from the schema structure of the individual entities, you can also view the schema of any device or service package that is activated in ATOM.

Example

In this example, let us explore how the schema for VRFs

/controller:devices/device/l3features:vrfs can be obtained using the Schema Browser..

  • Go to Administration > System > General settings. Select the Enable-Developer-Mode.
  • Navigate to Developer Tools > Schema Browser
  • In the text box, type /controller:

  • By typing the keyword devi in Schema Path (/controller:devi), all the entities starting with that start with devi as shown below:
  • As devices container is modeled under controller, xpath to fetch the devices schema present in ATOM is /controller:devices

  • Hit the Enter button to get the devices schema

The schema path for the VRFs: /controller:devices/device/l3features:vrfs/vrf

ATOM Extensions to YANG

Anuta Networks developed its own custom extensions to enhance the usage of YANG and these extensions are located in the following folders:

atomsdk/packages/Anuta/anuta/ncx/ncx-extensions.yang atomsdk/packages/Anuta/anuta/ncx/ncx-ui-extensions.yang atomsdk/packages/abstractdevicemodels/model/sdk-extensions.yang

Some of the commonly used UI extensions in ATOM are listed below:

  • ncx-ext-seq-no: This extension is used to indicate the display order of the property in the ATOM UI.

E..g:

leaf cpu-mhz {

type uint32;

n-ext-ui:ncx-ext-seq-no 56;

}

  • ncx-ext-hidden: This extension can be used to hide a node from UI form.
  • ncx-ext-multi-select: This extension can be used to select multiple values in combobox.

Below are some of the extensions useful in service package code-generation and more can be found in the above mentioned files.

  • maps-to: This extension is used to define a mapping between service data node to device data node. The mapping can be an Xpath or RC path.

E.g:

leaf auth-password { type string {

length “1..8”;

}

description “string”;

n-ext:maps-to “/controller:devices/device/if:interfaces/interface/hsrp:hsrp/auth-key”;

}”;

  • ncx-maps-to-expr: This extension is a superset of maps-to, we can write an expression about how it maps element(s) in service yang to element in device yang.

E.g:

list endpoints {

n-ext:ncx-maps-to-expr ‘/ac:devices/device/ai:interfaces/interface/long-name’ = ‘$(interface-name).$(unit)’;

leaf unit { type uint8;

}

leaf interface-name { type string;

}

}

  • device-platform: Use this extension as a sub-statement of maps-to for specifying the platform to which this maps-to is applicable for.

E.g:

leaf native-vlan-id { type uint16 {

range “1..4094”;

}

mandatory true;

when “../variant = ‘trunk'”; n-ext:maps-to

“/ac:devices/ac:device[ac:id=current()/../switch1-device-id]/if:interfaces/interface/allowed-vlans/if-ext:nativ e-vlan”{

sdk-ext:device-platform “JUNOS”;

}

}

YANG Validations & Constraints

Below are few yang statements which will help to build intelligence(validations/ checks/constraints) in the model

  • when

Nodes are valid only if the when condition is satisfied. E.g:

leaf variant {

type enumeration { enum “trunk”;

enum “access”;

}

}

leaf native-vlan {

description “Native VLAN that is configured when trunk ports are used”; type int16 {

range 1..4094;

}

when “../variant = ‘trunk'”;

}

In the above example native-vlan will be used only if variant = trunk.

  • must

It can be used on any data to have some constraints E.g:

leaf variant {

type enumeration { enum “trunk”;

enum “access”;

}

}

container vlans {

description “List of vlans permitted on the l2-edge ports”; list vlan {

key vlan-id; leaf vlan-id { type int16 {

range 2..4094;

}

}

must

‘(count(/ac:services/l2-edge:l2edge[name=current()/../../../../name]/devices/device[name=current()/../../nam e]/vlans/vlan/id) = 1 and ../../variant = “access”) or

(count(/ac:services/l2-edge:l2edge[name=current()/../../../../name]/devices/device[name=current()/../../name

]/vlans/vlan/id) >= 1 and ../../variant = “trunk”)’ {

error-message “vlan should be one if variant is access or vlan should be >= one if variant is trunk”;

}

}

}

Above must is used to validate vlan count to be exactly 1 if the variant is access or vlan count to be >=1 if variant is trunk

Library Utils for Service Modelling

For service modeling development Anuta provides library utils which are accessible at atomsdk/packages/servicemodel/scripts. These can be used in python based service logic written either manually or auto generated via SDK.

The python classes generated for the device yang models (Python Bindings for Device YANG Models) will also be present in the above directory which effectively makes the servicemodel package as a complete library for usage in service python logic.

servicemodel/scripts/device_abs_lib.py consists of various definitions which are basic CRUD operations performed on an object.

  • create()- To create the object in ATOM using post operation
  • update()- To edit the object in ATOM using put operation (overwrite)
  • delete()- To delete the object in ATOM using delete operation.

The other definition validate_inputs_form_payload in this file will use the python bindings present in servicemodel/scripts/controller to validate the inputs and form the payload required for above CRUD operations.

Few other commonly used python modules in servicemodel/scripts are

  • yang.py
  • util.py
  • devicemgr.py
  • yang.py provides Sdk class and AbstractYangServiceHandler class

Sdk Class provides basic methods to do CRUD operations for service models.

    • createData()- To create the object to ATOM using post operation
    • updateData()- To edit the object of ATOM using put operation (overwrite)
    • patchData()- To patch the object of ATOM using patch operation(extension)
    • getData()- To get the object of ATOM using get operation
    • deleteData()- To delete the object of ATOM using delete operation.

These methods are used for modeled entities only, not for RPC’s. To deal with RPC’s Sdk Class provides invokeRpc() method

CreateData Method

createData() method takes inputs as url, payload, yang_session, addReference and failOnExistingData arguments and posts the data to the server.

    • url : target on which data to be posted
    • payload: xml/json object to be posted
    • yang_session: session object
    • addReference: If AddReference is True, ATOM will create a reference for this object to keep track of this object.

Note: if addReference is True, no need to handle delete block for this object, as ATOM platform will take care of deletion of this object using reference.

Example

In this example, addReference is True by default as it is not mentioned, So for this entity no need to handle delete code in service logic

Similarly we have updateData, patchData and deleteData Methods in this Sdk class. Please refer yang.py module for more details in atomsdk/packages/servicemodel/scripts

invokeRpc() Method

This method takes inputs as rpcname and payload and provide respective output

    • rpcname: Name of the rpc
    • payload: payload object in xml/json

If any entity in ATOM is not modeled then we can implement RPC for the entity and call when we require in service modeling using this method.

Example

In this example rpc-name is device-discovery and the payload we are forming with the help of kwargs dictionary, finally we will get output_xml object when invokeRpc is called.

AbstractYangServiceHandler class provide two basic methods

    • register() Method: Register all the resource unit handlers. This method is called from the plugin.py module of the service package.

This register method internally calls registerServiceHandler() class for details refer

yang.py module

    • unregister() Method: Unregister all the resource unit handlers. This method is called

from the plugin.py module of the service package when unloading packages done from ATOM.

This unregister method internally calls unregisterServiceHandler() class, for details refer

yang.py module

  • util.py provides utilities for service model development with the help of IPPrefix class and some other functions

IPPrefix class takes cidr as input and provides details about address, netmask and wild card etc., as output.

Example of IPPrefix

In this example IPPrefix class takes cidr as input and provides netmask as output

Few frequently used methods in Module util.py are:

    • isEmpty() This will check if the object is empty or not. Code Snippet for isEmpty() Method
Example for isEmpty():

In this example checking if protocol is empty or not, if empty then we are return from there

    • isNotEmpty() This will check if the object is not empty or not. Code Snippet for isNotEmpty() Method

Example for isNotEmpty():

This example checks inputdict[‘name’] is not empty and then only proceeds further

  • devicemgr.py provides basic methods to get device obj from device ip or device id or device name etc.,
getDeviceByIp() Method

takes input as device management ip and provide device object to service model Code Snippet for getDeviceByIp() Method:

Example

In this example getDeviceByIp() method takes input as ip(device-management-ip) and provides device_object for further actions

Note: If dev object is None then need to check whether device is onboarded or not (or) device is online or not.

Similarly we have few other frequently used methods getDeviceById() method

getDeviceByName() method getDeviceByUniqueName() method getDeviceByInterfaceName() method

Please refer devicemgr.py module for more details at build/lib/servicemodel/scripts

ATOM SDK

Introduction

ATOM Software Development Kit (SDK) provides a gradle-based plugin Package-Plugin jar that serves as a backbone for package development in ATOM. ATOM SDK provides CLI and also integration into IDE like IntelliJ. The plugin enables you to perform the following tasks of Services/Drivers Development process in ATOM:

  • Develop device packages
  • Develop service packages
  • Compile, validate, generate device and service packages
  • Load Packages to ATOM
  • Upgrade of Packages

Folder hierarchy

Unzip the contents of the ATOM SDK zip to view the following folder structure:.

  • doc – This folder contains README and the plugin documentation.
  • examples This folder has package zip files for different types of packages.
  • packages – The core Package Plugin jar is part of the packages folder, which also has a few more library and base dependency packages required for development of new device and service packages.
  • create.py, sdk.py, setup.py – These are the python files required for setting up device and service packages environment.

SettinguptheenvironmentforATOMPackage Plugin

ATOM Package Plugin supports multiple gradle tasks that help create an environment suited for developing packages. These tasks can be triggered from an IDE or CLI.

For the plugin tasks to run, ensure that the prerequisites are met with.

Prerequisites

To setup the environment, you must ensure that the following software requirements are met: 1. Python (2.7.12/3.x)

  • Python setup tools
  • Python Pip and Python modules bitarray, cmd2, TAPI, XEGER 4. Pyang(1.7.8/2.5.2(for python3)).
  • JAVA (java 1.8 or greater)
  • Gradle

For information about installing gradle in your environment, visit https://gradle.org.

Setting up the environment in Ubuntu

  • Execute the following commands:

  • Install Oracle JDK for Linux and unzip it.

Set the JAVA_HOME environment variable pointing to jdk directory.

  • Install gradle by executing the following command:

Setting up the environment in Windows

  • Set the JAVA_HOME environment variable pointing to jdk directory. Example: C:Program FilesJavajdk1.8.0_91

6 . Gradle Installation in windows

Step 1. https://gradle.org/releases/ get the latest Gradle distribution Step 2. Unpack the distribution zip

Step 3. Configure your system environment Path variable For e.x: C:Gradlegradle-4.10.2bin.

Step 4. Verify your installation

Open a console (or a Windows command prompt) and run gradle -v to run gradle and verify the version, e.g.:

Setting up the environment in Centos

  • Execute the following commands:

  • Install Oracle JDK for Centos and unzip it.

Set the JAVA_HOME environment variable pointing to jdk directory.

6 . Gradle Installation in centos

Step 1. Start downloading the Gradle Binary-only zip file in the /tmp directory using the following wget command.

Step 2. Unpack the distribution zip with the following command.

Step 3. Configure your system environment Path variable For e.x: C:Gradlegradle-5.0bin.

Step 4. Verify your installation

Open a console (or a Windows command prompt) and run gradle -v to run gradle and verify the version, e.g.:

Setting up the repository for developing packages

In ATOM SDK, the sdk.py script sets up the SDK plugin environment for creating various packages.

To setup the repository of your choice, follow the steps as outlined below:

  • Run the command: python sdk.py -s

This command runs the setup.py script which setups an environment for packages

repository.

setup.py – This script is used to setup repositories for core-dependent packages. The core-dependent packages are present inside the “packages” folder and are necessary for developing new device and service packages.

  • Select the repository of your choice.

You can either setup a local repository or can publish the core-dependent packages to an artifact repository such as Nexus.

  • Local Repository (Flat Directory Structure) : This option enables you to copy the core-dependent packages present in the “packages” folder to a flat directory.
  • The absolute path of this particular flat directory, for example, ‘/home/’ as shown below(verifythatthisfolderispresentalready)
  • Maven Artifact Repository : This option enables the user to copy the core-dependent packages in the “packages” folder uploaded to the artifact repository, for example Nexus.

After setting up the repository, the script generates a config.xml file. This file contains two tags:

    • repo-type : Maven or Flat Directory
    • repo-path : The absolute path or URL of the directory.

The metadata present in the config.xml is important to run the subsequent scripts.

Let us take the example of the selected repository as the Flat Directory(a local repository) and the steps to be followed are illustrated below:

  • Enter the IP address of ATOM

If port is required for accessing the ATOM application then mention that as well. E.g: 172.16.1.10:30443, 127.0.0.1:8890

  • Enter the credentials to login into ATOM

After the successful setup process, the following files and folders are generated

  • global.properties – contains the username, password and ATOM ip which will be used in package development process
  • config.xml – contains the information of repo-type and path to dependencies.
  • dependencies -The dependency packages for development of device and service models are copied to the destination folder of your choice.

Tasks for developing packages

ATOM package plugin internally uses gradle for providing various options in package development.

General Gradle tasks

Command Description
grade -help All the commands are listed here
gradle tasks –all All the gradle tasks are listed here
gradle -help

All the commands can be viewed as shown below:

gradle tasks –all

Execute this command at root level as shown below:

Execution of these commands at the package level displays all the tasks that are available in the plugin, Build, Documentation

ATOM specific tasks

Few of the Important Gradle Tasks, specific to ATOM, along with their descriptions are listed

below:

Task Description Modeling Relevance
generateYin This task is used to convert a YANG file to a YIN equivalent. The generateYin task internally uses python’s PYANG tool which has been modified to support validating of the ATOM YANG models. Device & Service Modelling
generateDeviceOperationTe mplate This task generates the deviceoperation.xml file containing the details of the create, delete, and update operations. Device Modelling
verifyDeviceOperations This task is used to verify the device operations defined for a device yang model. It creates a file that consists of warning statements of invalid device operation yang Xpath targets. Device Modelling
generateDevicePackage This task is used to generate device packages for a given device.yang being developed. Device Modelling
generatePyBinds This task is used to generate python class hierarchy for a YANG data model and its dependencies. Device Modelling
generateDeviceDriverPacka ge This task is used to generate a device driver package for a given

device-driver-yang being developed.

Device Modelling
generateServicePackage This task is used to generate a service package for a given service.yang being developed. Service Modelling
generateDevicePybinds This task is used to generate python class hierarchy for a YANG data model and its dependencies in a service package. Service Modelling
Load This task is used to upload a package to an ATOM instance. Device & Service Modelling
Activate This task is used to activate a package present in an ATOM instance. Device & Service Modelling
Deactivate This task is used to deactivate a package loaded in an ATOM instance. Device & Service Modelling
Delete This task is used to delete a package present in an ATOM instance. Device & Service Modelling
Upgrade This task is used to upgrade an already existing package present in an ATOM instance. Device & Service Modelling
Replace Replace a package with new package content without any manual package upgrade steps Device & Service Modelling
Purge Clean all/specific data and its reference data under the package Device & Service Modelling
cleanBuild This task is a combination of two gradle tasks, ‘clean’ and ‘ build

–refresh-dependencies’. This task first executes gradle clean. The clean task is defined by the java plugin and it removes the buildDir folder, thus cleaning previous builds’ artifacts, which are no longer relevant.

Device & Service Modelling
copyToDependencies This task internally runs the archive task (which generates the

ready-to-be-uploadable zip). After generating the zip, it ascertains the repository type (whether maven/local) from config.xml file and the repository path.

Device & Service Modelling
enableMaintenanceMode This task is used to enable maintenance mode on an ATOM instance. To run this task make sure all the necessary modifications are made in gradle.properties file, that have been explained in the load task. Device & Service Modelling
disableMaintenanceMode This task is used to disable maintenance mode on an ATOM instance. To run this task, ensure that all the necessary Device & Service Modelling
modifications are made in gradle.properties file, explained in the load task.
restartServiceModelPlugin Agent This gradle task is used to stop and restart service model plugin for the agent. Device & Service Modelling
restartServiceModelPluginS erver This gradle task is used to stop and restart service model plugin for server. Device & Service Modelling

Below is a bit more detailed explanation of Gradle Tasks useful in Service Modelling.

generateYin
  • Before running this task, ensure that the YANG model of the package is available in the path: srcmainmodel.
  • The generated yin file is created in the buildgenerated directory.

In the gradle.properties file, if the overwrite flag is set to ‘true’, the result is generated in the folder, usermodelsrcmain, where ‘usermodel’ is the name of the package created.

If this flag is set to ‘false’, the file is generated in the path usermodelbuildgenerated

generateServicePackage

The service package generated contains the following entities:

  • The model folder contains the following:

<service_name>.yang file – Contains the schema of the service defined in YANG. This yang will be taken as input for the task to generate a service package basic service

logic files.

  • The scripts folder contains the following files:
    • <service_name>.py – Contains the logic binding the service to the device.
    • plugin.py – Code for adding the service as a new plug-in to ATOM
    • _init_.py – Required to make ATOM treat the directories as containing packages

If gradle.properties file autoupdate flag is set to true, it won’t generate updates and delete pieces of code, whereas ATOM platform will handle it automatically.

If the driverimport flag is set to true it will take the driver name as the import for pybinds.

If gradle.properties file overwrite flag is set to false, the result is generated in path

servicepackage/build/generated else it is generated in src/main as shown below:

generateDevicePyBinds

By performing this task on device models of ATOM, the resulting python classes allow additional methods to be associated with the service modelling.

This generates with <devicedrivername> named library package which has python classes for the YANG data models mentioned as dependency.

Load

This task is used to upload a package to an ATOM instance.

Before uploading the package to ATOM, make sure the parameter values in the

gradle.properties file are as per ATOM instance you use.

  • atomHost property should be provided with a valid IP address.

If a port needs to be included for accessing applications. Then include that as well. E.g: https://172.16.16.177:30443

  • authToken should be provided.

AuthToken is used for basic authorization. The format of the authtoken is, the keyword Basic followed by base64 encoding of the string <username>:<password>”, as shown above. These are the default values that can be updated as required.

Upon Load gradle task being successful, the desired changes can be observed in the ATOM UI.

Activate

This task is used to activate a package available in an ATOM instance. To activate a package, ensure the gradle.properties file has the aforementioned properties (mentioned in load task).

This task changes the active flag of a package to ‘true’ in ATOM. Upon success, the desired changes can be observed in the ATOM UI.

Deactivate

This task is used to deactivate a package loaded in an ATOM instance. To deactivate a package ensure that the gradle.properties file has the aforementioned properties (mentioned in load task). This task changes the active flag of a package to ‘false’.

Upon success, the desired changes can be observed in the ATOM UI.

Delete

This task is used to delete a package from an ATOM instance.

Upon success, the desired changes can be observed in the ATOM UI.

Upgrade

This task is used to upgrade an already existing package present in an ATOM instance. To upgrade a package ensure that the gradle.properties file has the properties mentioned in the load task. The ‘to be upgraded’ package should have a different version than the existing package in ATOM.

The version of the package can be changed in the build.gradle file as shown below.

Version being changed to ‘7.0.1.0’ from ‘7.0.0.0’

On completion of the upgrade task, the latest version of the package is updated to ‘Active: true’ and the older version of the same package is set to ‘Active:False’ as shown below:

cleanBuild

This task is a combination of two gradle tasks, ‘clean’ and ‘build –refresh-dependencies’. This task first executes gradle clean. The clean task is defined by the java plugin and it removes the buildDir folder, thus cleaning previous builds’ artifacts, which are no longer relevant.

After cleaning, this task runs gradle build –refresh-dependencies.

The –refresh-dependencies option – Enables Gradle to ignore all cached entries for resolved modules and artifacts. A fresh resolve will be performed against all configured repositories, with dynamic versions recalculated, modules refreshed, and artifacts downloaded.

To run this task, enter: gradle cleanBuild

copyToDependencies

This task internally runs the archive task (which generates the ready-to-be-uploadable zip). After generating the zip, it ascertains the repository type (whether maven/local) from config.xml file and the repository path.

Based on the information gathered, it either publishes the artifact repository in case the repository is maven or copies the dependencies to the local dependencies directory in case the repository is flat Directory.

To run this task, enter: gradle copyToDependencies

Above task copied from usermodel zip into package dependency folder so that usermodel package can serve as a dependency for any other package development.

enableMaintenanceMode

This task is used to enable maintenance mode on an ATOM instance. To run this task make sure all the necessary modifications are made in gradle.properties file, that have been explained in the load task.

Upon success, the desired changes can be observed in the ATOM UI.

disableMaintenanceMode

This task is used to disable maintenance mode on an ATOM instance. To run this task , ensure that all the necessary modifications are made in gradle.properties file, explained in the load task.

Upon success, the desired changes can be observed in the ATOM UI.

restartServiceModelPluginAgent

This gradle task is used to stop and restart service model plugin for the agent.

During the task execution, the desired changes can be observed in the ATOM UI.

restartServiceModelPluginServer

This gradle task is used to stop and restart service model plugin for server.

Upon success, the desired changes can be observed in the ATOM Tasks UI.

Running ATOM Package Plugin Tasks

The ATOM Package Plugin gradle tasks available for package development as described in the section, “Tasks for developing packages” can be executed from an IDE (For reference, Intellij is used as an IDE) or directly from the CLI as described below.

Running Tasks in IDE

  • Install Intellij from https://www.jetbrains.com/idea/download/
  • Select File > New > Project from existing sources.
  • To import the ATOM-package plugin into IntelliJ, select the build.gradle file from the package being developed as discussed in Setting up ATOM Package Plugin Environment.
  • Select View > Tool windows > gradle

Gradle support is displayed on the right-hand side.

  • Select the “Tasks” list. Execute the following operations:
    • build > clean
    • build
  • Run the ATOM plugin tasks based on your requirements as discussed in ATOM specific

tasks

Example: gradle generateYin

Running Tasks in CLI

  • Follow the procedure as described in the section, “Setting up the repository for package development”, locate the new package being developed and execute the following commands:
  • To view all the available tasks in gradle, enter the command: – gradle tasks –all
  • To clean the latest build, enter : gradle tasks clean
  • To build the project, enter: gradle tasks build
  • To run a required ATOM plugin task based on your requirement as discussed in ATOM specific tasks, enter : gradle <task-name>

E.g: gradle genarateYin

Troubleshoot & FAQs – Service Modelling

Errors during package upload into ATOM

Package Dependency Error

Make sure all the packages mentioned in import statements of your service yang are present in the ATOM already. Those dependency packages if not uploaded then ATOM will throw package dependency Errors. For E.g in below snippet, make sure all import statements yang files are present.

Example exception:

Solution:

First upload and load all dependency packages, after that upload the service package.

Package Deletion Error

Users trying to delete the package from Administration > Plugins & Extensions > Packages, but the services related to this package still exist in the Services tab, then the following exception will be seen.

Solution:

Ensure that the services instantiated using the service package are deleted. Before the deletion of the service package, do the following:

  • Go to the Automation -> Services tab and delete all the services.

  • Navigate to the packages tab, Unload the package first and after that delete package.

Logging Level for Task Logs

Log_info or Log_debug statements can be added in python code to get those debug or info messages in the Task Logs downloaded from ATOM.

E.x:

Handler maps

To debug issues of python code whether it entered into each module or not, we need to check if the required handler map is triggered or not. Handler map is to know which handles of service code are getting triggered first when service is triggered. Generally these will be present in

{module name}.py file (ex: suppose module name is acl_service, file in service package will be with the name of Acl_Service.py).

Verification In tasklog

Look for keyword After Sorting which shows what are the handles of service being invoked

Registering the Service Package with ATOM

After the service package is loaded successfully into ATOM, in the Services tab, user can check if the python code with respect to yang is registered with ATOM or not. Users should cross check like below.

  • Click Administration > Troubleshoot>Services & Metrics > Servers > Components >

Python > ServiceModelPlugin > click the Statistics tab

  • Check the status of the service package.
  • In the Statistics tab, if LOADED is displayed in the State column, the service package is loaded into the ATOM system successfully.
  • If State column is FAILED for uploaded service package, then service package contains some errors
  • Check for the exceptions in Service Model Plugin server log, fix the exception in respective python module and upload again.

Binding of the logic with ATOM

After uploading, registering the service package with ATOM successfully, syntactical and semantic errors in the python glue logic can also cause issues that need to be resolved.

Sample Failure to upload Python Plugin files

1. Navigate to the Task Viewer, download or view the Service Model Plugin logs and look for the exception in the task log as shown below:

Due to the hyphen (-) in the postscrub-vlan.py file, the package python code registering into ATOM did not happen.

Exception:

Solution:

  • Rename the postscrub-vlan.py to postscrubvlan.py, similarly rename yang and yin files

Error

Exception

Solution:

Correct it like below

Now service package is free of syntactical errors and is loaded successfully into ATOM

Semantic Errors in the Service package files

Even if the syntactically yang and python files are correct, there might be some issues due to typos in the YANG files or URLs used in python, glue logic

Though these errors are not displayed in the log, check for the following:

    • The used URLs are appropriate
    • Typos in the yang files or python modules
Typo in Yang File

In glue logic, the path is described as shown in the following snippet:

Solution

Correct the typo present in yang and yin files

Defined in the YANG module is as shown below:

Mismatch in the yang and python module due to typos leads to improper call invocation.

Solution

Correct the typos in the python module as shown below:

Commands not being generated in ATOM
  • Go to the naas server.log or the task log.
  • Look for the pattern “best match platform”.
  • For operation best match platform found and respective command conditions are validated and $ variables are replaced by values provided by the end user.
  • The detailed highlights are marked in red as shown below:

  • If the best match platform is null, check if the device operations are defined in the vendor-data.
  • In the ATOM UI, navigate to Administration >Plugins & Extensions > Device Support > Operations
  • If the Operations are defined in the Device support and the commands are not being generated still, check with Anuta Networks
  • However, if the operations have not been defined, create an operation in the UI.
Solution

If device operation is not defined for the platform, define it by adding the Create, Update, and

Delete operations for that platform as illustrated below:

Attribute Error

Error:

When the leaf is defined in yang and at the time of service creation the user gives an empty value to that leaf, below error will be seen.

Base-Object has no Attribute/object

Solution

To overcome the above exception, make sure that the user should add the get_field_value like shown in below snippet to fetch the value from service yang and assign it to create call.

Sorting of Create/Delete commands:

After service instantiated sometimes commands will be generated in the wrong order in task details, due to this operations can fail to execute on device. To overcome the failure follow below procedure.

Example code :

Suppose devices will accept ‘CreateQPolicyMap’ command operations first and after that ‘CreateInterface’, ‘UpdateInterface’ command operations but commands generated in reverse order in service task details, we need to write sorting for the Create/Delete commands like below.

This class is already present in respective service_customization files. User needs to add the move or delete operation like shown below.

class CreatePreProcessor(yang.SessionPreProcessor):

def processBeforeReserve(self, session):

operations = session.getOperations()

“””Add any move operations for creation”””

log(‘operations: %s’ % (operations))

yang.moveOperations(operations, [‘CreateInterface’, ‘UpdateInterface’], [‘CreateQPolicyMap’], True)

Explanation for example code:

In above code CreateQPolicyMap command will come before CreateInterface or UpdateInterface command.

For deletion commands also same procedure.

IPAM Pools integration with services:

To integrate the IP address pools with services, make sure that user can add code like below in services.yang

After adding the leaf in yang, user will generate the code by using SDK, but in codegen bindings of IPAM related methods will not be generated automatically if extensions are not used properly. Users can add below code in some lib.py file and import those definitions wherever needed.

  • Below method is used to get the used ips from ipaddresspool.
  • Below method is used to add the ipaddress entries under ipaddress pools.

  • Below method is used to get the free ips from cidr.

def get_freeip_from_cidr(cidr, used_list): print “inside get_freeip_from_cidr” cidr_obj = util.IPPrefix(cidr) gateway_ip = cidr_obj.gateway_ip() #used_list.sort()

#ip_address = used_list[0]

#last_ip_address = used_list[used_list. len ()-1]

network_given = IPNetwork(cidr) (addrStr, cidrStr) = cidr.split(‘/’) addr = addrStr.split(‘.’)

cidr = int(cidrStr) mask = [0, 0, 0, 0]

for i in range(cidr):

mask[i/8] = mask[i/8] + (1 << (7 – i % 8)) net = []

for i in range(4): net.append(int(addr[i]) & mask[i])

network = “.”.join(map(str, net)) ip_address = network

print “gateway_ip for /32 cidr”, gateway_ip print “cidr_obj.masklen is”, cidr_obj.masklen if str(cidr_obj.masklen) == str(32):

return gateway_ip else:

gateway_ip = util.next_ip_address(ip_address) print “gateway_ip is:”, gateway_ip

while (True):

if gateway_ip not in used_list:

break else:

gateway_ip = util.next_ip_address(gateway_ip) print “final gateway_ip is :”, gateway_ip

VLAN Pools integration with services:

To integrate the VLAN pools with services, make sure that user should add code like below in services.yang

After adding the leaf in yang, user will generate the code by using SDK, but in codegen bindings of VLAN pools related methods may not be generated automatically based on the extension used. Users can add below code in some lib.py file and call those definitions when needed.

Below method is used to allocate the VLANs in a VLAN pool.