This SLAX script leverages the configuration-management API to create a change-request that includes configuration in XML format. XML format is used in this instance as that provides the ability to insert a newly created term before an existing term.
The SLAX script is shown below and as an attachment.
/*
# <*******************
#
# Copyright 2017 Juniper Networks, Inc. All rights reserved.
# Licensed under the Juniper Networks Script Software License (the "License").
# You may not use this script file except in compliance with the License, which is located at
# http://www.juniper.net/support/legal/scriptlicense/
# Unless required by applicable law or otherwise agreed to in writing by the parties, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# *******************>
*/
version 1.2;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
ns str = "http://exslt.org/strings";
ns func extension = "http://exslt.org/functions";
ns curl extension = "http://xml.libslax.org/curl";
ns xutil extension = "http://xml.libslax.org/xutil";
ns jspace = "http://jspace-utils/asharp@juniper.net";
import "../import/junos.xsl";
/* Junos Space specific context, name and description */
/* @CONTEXT = "/device" */
/* @NAME = "Add route target to policy" */
/* @DESCRIPTION = "Add route target to policy" */
/* @ISLOCAL = "true" */
/* @PASSSPACEAUTHHEADER = "true" */
/* @PASSDEVICECREDENTIALS = "true" */
/* @EXECUTIONTYPE = "GROUPEDEXECUTION" */
var $curl = curl:open();
var $fabric = jspace:fabric();
var $arguments = {
<argument> {
<name> "termname";
<description> "Name of term to add";
}
<argument> {
<name> "commname";
<description> "Name of community to add";
}
<argument> {
<name> "vnitarget";
<description> "Name of vnitarget";
}
}
main <op-script-results> {
<output> {
if ($fabric) {
var $devices = jspace:credentials();
if ($devices) {
for-each ($devices/device) {
sort host;
var $myhost = host;
/* find the device using API call */
/*
* url, content-type, item-type, condition, item
*/
var $findDevice = curl:perform($curl,jspace:findItem(
"http://" _ $fabric _ ":8080/api/space/device-management/devices",
"",
"name",
"eq",
$myhost
));
/* get the key of the selected device */
var $deviceKey = $findDevice/data/devices/device/@key;
/* make changeRequest using the API */
/*
* url, content-type, deviceKey, orig-name, new-name, resync
*/
var $results = curl:perform($curl,jspace:addTerm(
"http://" _ $fabric _ ":8080/api/space/configuration-management/change-requests",
"application/vnd.net.juniper.space.configuration-management.change-request+xml;version=2;charset=UTF-8",
$deviceKey,
$termname,
$commname,
$vnitarget,
"true"
));
if ($results/headers/code == "200") {
/* job accepted */
expr "Adding term " _ $termname _ "\n";
/* need to see if the commit was successful or not */
/* to get the XML data which is embedded within more xml needs lots of parsing... */
/* parse and convert the raw-data node */
var $parseOne = {
uexpr $results/raw-data/.;
}
var $parseTwo = xutil:string-to-xml($parseOne);
var $parseThree := {copy-of $parseTwo;}
/*
parse and convert the change-request/xmlData node
this step is only required if you want to display
the configuration that was pushed to the device.
*/
var $xmlDataOne = {
uexpr $parseThree/change-request/xmlData/.;
}
var $xmlDataTwo = xutil:string-to-xml($xmlDataOne);
var $xmlDataThree := {copy-of $xmlDataTwo;}
copy-of $xmlDataThree;
/* display the change-request/result */
uexpr substring-before($parseThree/change-request/result/.,"rpc-reply: ");
} else {
expr "Job failed with error code " _ $results/headers/code _ "\n";
}
}
}
} else {
expr "Could not identify the fabric!";
}
}
}
/*
* Used to identify the fabric that the script has been executed on
* knowing this is essential in a multi fabric environment when making
* RESTful API calls to Junos Space and using the session cookies for
* authentication.
*/
<func:function name="jspace:fabric"> {
if( $CONTEXT ) {
var $fabric = {
if ( contains( $JSESSIONID, "server") ) {
expr jcs:regex("\.(space-[A-Za-z0-9]+):server",$JSESSIONID)[2];
} else {
expr jcs:regex("\.(space-[A-Za-z0-9]+)",$JSESSIONID)[2];
}
}
<func:result select="$fabric">;
} else {
<func:result select="false()">;
}
}
/* findItem */
<func:function name="jspace:findItem">
{
param $url;
param $content-type;
param $item-type;
param $condition;
param $item;
var $curlData := {
<method> "get";
<insecure>;
<url> $url;
<header name="Cookie"> "JSESSIONID=" _ $JSESSIONID _ ";Path=/;";
<header name="Cookie"> "JSESSIONIDSSO=" _ $JSESSIONIDSSO _ ";Path=/;";
<param name="filter"> "(" _ $item-type _ " " _ $condition _ " '" _ $item _ "')";
<content-type> $content-type;
<format> "xml";
}
<func:result select=" $curlData ">;
}
/* add term */
<func:function name="jspace:addTerm">
{
param $url;
param $content-type;
param $deviceId;
param $termname;
param $commname;
param $vnitarget;
param $syncAfterPush; /* true | false */
var $curlData := {
<method> "post";
<insecure>;
<url> $url;
<content-type> $content-type;
<header name="Cookie"> "JSESSIONID=" _ $JSESSIONID _ ";Path=/;";
<header name="Cookie"> "JSESSIONIDSSO=" _ $JSESSIONIDSSO _ ";Path=/;";
<format> "xml";
<contents> {
uexpr '
<change-request>
<name>Add_route_target_to_policy</name>
<description>Add_route_target_to_policy</description>
<xmlData>
<![CDATA[
<configuration>
<policy-options>
<policy-statement>
<name>vrf-imp</name>
<term operation="create" insert="before" name="REJECT">
<name>' _ $termname _ '</name>
<from>
<community>' _ $commname _ '</community>
</from>
<then>
<accept/>
</then>
</term>
</policy-statement>
<community>
<name>' _ $commname _ '</name>
<members>' _ $vnitarget _ '</members>
</community>
</policy-options>
</configuration>
]]>
</xmlData>
<device href="/api/space/device-management/devices/' _ $deviceId _ '"/>
<syncAfterPush>' _ $syncAfterPush _ '</syncAfterPush>
</change-request>
';
}
}
<func:result select=" $curlData ">;
}
/*
* Can be used to identify selected devices, and their credentials.
* Must be used with PASSDEVICECREDENTIALS = "true" annotation for credentials.
* Must be used with EXECUTIONTYPE = "GROUPEDEXECUTION" annotation for multiple devices
*/
<func:function name="jspace:credentials"> {
if( $CONTEXT ) {
var $splitCredentials = str:split( $credentials, "\\;" );
var $targets := {
for-each ( $splitCredentials ) {
var $splitCredential = str:split( ., "\\:" );
var $user-target = str:split($splitCredential[1], "\@");
var $host = substring-before( substring-after( $deviceipmap, substring-after( $splitCredential[1], "@" ) _ "\":\"" ), "\"" );
<device> {
<ipAddr> {
expr $user-target[2];
}
<user> {
expr $user-target[1];
}
<passwd> {
expr $splitCredential[2];
}
<host> {
expr $host;
}
}
}
}
<func:result select="$targets">;
} else {
<func:result select="false()">;
}
}