Automation
Automation

Scripting How-To: Auto-configure all nodes via the remote-rpc mechanism when a node is inserted into an existing BGP mesh

by Cordelia on ‎08-10-2015 08:10 AM - edited on ‎08-23-2017 12:22 PM by Administrator Administrator (1,276 Views)
Overview

Auto-configure all nodes via the remote-rpc mechanism when a node is inserted into an existing BGP mesh.

 

Description

 

This script uses the remote-rpc (cross-box scripting) mechanism available from 9.3 onwards.

 

Source Code

 

GitHub Links

 

The source code below is also available from GitHub at the following locations:

 

Example Configuration

 

01	Remote-rpc meachanism works only with ssh-agent setup. The prerequisite for
02	this script to work is the ssh-agent should be configured properly and the
03	ssh connection from the current node to all the peers in the BGP mesh should
04	work without password/passpharse.
05	 
06	This scripts takes the following input:
07	 
08	  bgp-peer-group     BGP peer group name
09	  bgp-peer-type      BGP peer type
10	  local-address      IP-address of local machine (This node)
11	  local-as-number    Local AS Number
12	  peer-address       IP-address of one of the peer
13	 
14	 'peer-address' is the address of one-of-the member in the BGP mesh.
15	 
16	The script gets the BGP peer information from 'peer-address' and add this
17	node ('local-address') as neighbor in all the peers. Also configure the
18	peer details locally.
19	 
20	Run the script from the node which you want to add to BGP mesh.
21	 
22	Steps to setup ssh-agent.
23	-------------------------
24	 
25	Note: The below steps are given very briefly, for details please refer the
26	appropriate manuals.
27	 
28	1) Configure user's to connect.
29	 
30	   Note: User name should be same in desktop and all the peers. Since I am
31	         executing this from my desktop with my userid, I have created the
32	         same user in all the peers.
33	 
34	user@cli# show system login user rsankar
35	uid 2000;
36	class super-user;
37	 
38	user@cli# show system login user rsankar
39	uid 2000;
40	class super-user;
41	 
42	2) Configure ssh-key and associate the public key with rsankar login account
43	in both the machines.
44	 
45	Please refer the below JUNOS document for details regarding ssh key generation.
46	 
47	http://www.juniper.net/techpubs/software/junos/junos90/netconf-guide/creating-a-publicprivate-key-pair.html#id-10314765
48	 
49	3) Make sure routers are added to ssh-known-hosts under
50	   [security ssh-know-hosts]
51	 
52	4) Run ssh-agent in desktop
53	 
54	   # Execute the below command from bash shell.
55	 
56	   >`ssh-agent -s `
57	 
58	   # Make sure ssh-agent is running.
59	 
60	   >ps -auwwx | grep ssh-agent
61	rsankar  99086  0.0  0.1  3164  2000  ??  Is    3:23PM   0:00.00 ssh-agent -s
62	 
63	5) Add identities to ssh-agent.
64	 
65	   > ssh-add
66	 
67	   # ssh-add will ask for passphrase, give the passphrase given during the
68	   # key generation.
69	 
70	6) Make sure the ssh forwarding is enabled in your desktop.
71	 
72	  To enable forwarding add the following lines  to ~/.ssh/config
73	 
74	Host *
75	ForwardAgent yes
76	ForwardX11 yes
77	 
78	7) Login to all the peers and verify the setup. Login should succeed without
79	asking password or passphras

 

SLAX Script Contents

 

001	/*
002	 * Script to add a node to the existing BGP mesh.
003	 *
004	 * This script uses the remote-rpc mechanism available from 9.3 onwards.
005	 *
006	 * Remote-rpc meachanism works only with ssh-agent setup. The prerequisite for
007	 * this script to work is the ssh-agent should be configured properly and the
008	 * ssh connection from the current node to all the peers in the BGP mesh should
009	 * work without password/passpharse.
010	 *
011	 * This scripts takes the following input:
012	 *
013	 *  bgp-peer-group     BGP peer group name
014	 *  bgp-peer-type      BGP peer type
015	 *  local-address      IP-address of local machine (This node)
016	 *  local-as-number    Local AS Number
017	 *  peer-address       IP-address of one of the peer
018	 *
019	 * 'peer-address' is the address of one-of-the member in the BGP mesh.
020	 * The script gets the BGP peer information from 'peer-address' and add this
021	 * node ('local-address') as neighbor in all the peers. Also configure the
022	 * peer details locally.
023	 *
024	 * Run the script from the node which you want to add to BGP mesh.
025	 *
026	 * Steps to setup ssh-agent.
027	 * -------------------------
028	 *
029	Note: The below steps are given very briefly, for details please refer the
030	appropriate manuals.
031	 
032	1) Configure user's to connect.
033	 
034	   Note: User name should be same in desktop and all the peers. Since I am
035	         executing this from my desktop with my userid, I have created the
036	         same user in all the peers.
037	 
038	user1@ritter# show system login user rsankar
039	uid 2000;
040	class super-user;
041	 
042	user1@waffy# show system login user rsankar
043	uid 2000;
044	class super-user;
045	 
046	2) Configure ssh-key and associate the public key with rsankar login account
047	in both the machines.
048	 
049	Please refer the below JUNOS document for details regarding ssh key generation.
050	 
051	http://www.juniper.net/techpubs/software/junos/junos90/netconf-guide/creating-a-publicprivate-key-pair.html#id-10314765
052	 
053	3) Make sure routers are added to ssh-known-hosts under
054	   [security ssh-know-hosts]
055	 
056	4) Run ssh-agent in desktop
057	 
058	   # Execute the below command from bash shell.
059	 
060	   >`ssh-agent -s ` 
061	 
062	   # Make sure ssh-agent is running.
063	 
064	   >ps -auwwx | grep ssh-agent
065	rsankar  99086  0.0  0.1  3164  2000  ??  Is    3:23PM   0:00.00 ssh-agent -s
066	 
067	5) Add identities to ssh-agent.
068	  
069	   > ssh-add
070	 
071	   # ssh-add will ask for passphrase, give the passphrase given during the
072	   # key generation.
073	 
074	6) Make sure the ssh forwarding is enabled in your desktop.
075	 
076	  To enable forwarding add the following lines  to ~/.ssh/config
077	 
078	Host *
079	ForwardAgent yes
080	ForwardX11 yes
081	 
082	7) Login to all the peers and verify the setup. Login should succeed without
083	asking password or passphrase.
084	 
085	 *
086	 */
087	version 1.0;
088	 
089	ns junos = "http://xml.juniper.net/junos/*/junos";
090	ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
091	ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
092	 
093	import "../import/junos.xsl";
094	 
095	var $arguments = {
096	    <argument> {
097	    <name> "bgp-peer-group";
098	    <description> "BGP peer group name";
099	    }
100	    <argument> {
101	    <name> "bgp-peer-type";
102	    <description> "BGP peer type";
103	    }
104	    <argument> {
105	    <name> "local-as-number";
106	    <description> "Local AS Number";
107	    }
108	    <argument> {
109	    <name> "peer-address";
110	    <description> "IP-address of one of the peer";
111	    }
112	    <argument> {
113	    <name> "local-address";
114	    <description> "IP-address of local machine (This node)";
115	    }
116	}
117	 
118	param $bgp-peer-group;
119	param $bgp-peer-type;
120	param $local-as-number;
121	param $peer-address;
122	param $local-address;
123	 
124	match / {
125	    <op-script-results> {
126	    /*
127	     * Validate the paramaters passed
128	     */
129	    if ($bgp-peer-type != "internal" && $bgp-peer-type != "external") {
130	        call emit-error($message = "bgp-peer-type is mandatory and should" _
131	                " be either 'internal' or 'external'");
132	    } else if (jcs:empty($local-address)) {
133	        call emit-error($message = "local-address is mandatory");
134	    } else if (jcs:empty($local-as-number)) {
135	        call emit-error($message = "local-as-number is mandatory");
136	    } else if (jcs:empty($peer-address)) {
137	        call emit-error($message = "peer-address is mandatory");
138	    } else if (jcs:empty($bgp-peer-group)) {
139	        call emit-error($message = "bgp-peer-group is mandatory");
140	    } else {
141	        call main-template();
142	    }
143	    }
144	 
145	}
146	 
147	template main-template()
148	{
149	    expr jcs:progress("Connecting locally ... ");
150	 
151	    var $local-con = jcs:open();
152	 
153	    if (jcs:empty($local-con)) {
154	    call emit-error($message = "Not able to connect locally");
155	    } else {
156	    expr jcs:progress("Connected locally ... ");
157	 
158	    var $peer-bgp-config := {
159	        call get-peer-bgp-group-config($address = $peer-address);
160	    }
161	 
162	    var $peer-group =
163	        $peer-bgp-config/configuration/protocols/bgp/group[name == $bgp-peer-group];
164	 
165	    if (not($peer-group)) {
166	        call emit-error($message = "BGP configuration for group '" _
167	                $bgp-peer-group _ "' does not exist in peer '" _
168	                $peer-address _ "'");
169	    } else if ($peer-group/type != $bgp-peer-type) {
170	        call emit-error($message = "Given peer type does not match with " _
171	                "the peer type configured in '" _
172	                $peer-address _ "'");
173	    } else {
174	        expr jcs:progress("Adding this node as peer in all the BGP ",
175	                  "peers ...");
176	 
177	        call add-bgp-peer($peer = $peer-address);
178	        for-each ($peer-group/neighbor) {
179	        if (name != $local-address) {
180	            call add-bgp-peer($peer = name);
181	        }
182	        }
183	 
184	        expr jcs:progress("Added this node as peer in all the BGP ",
185	                  "peers ...");
186	 
187	        /*
188	         * BGP group config in the given peer will not have its own
189	         * entry in 'protocols bgp group <group-name> neighbor' hierarchy.
190	         * So, get the detail about the given peer from one of the
191	         * neighbor configured.
192	         */
193	 
194	        var $another-peer-bgp-config := {
195	        call get-peer-bgp-group-config($address =
196	                           $peer-group/neighbor/name);
197	        }
198	 
199	        var $given-peer-detail =
200	            $another-peer-bgp-config/configuration/protocols/bgp/group[name == $bgp-peer-group]/neighbor[name == $peer-address];
201	 
202	 
203	        expr jcs:progress("Configuring BGP locally ...");
204	 
205	        var $local-xml = {
206	        <configuration> {
207	            <protocols> {
208	            <bgp> {
209	                <group> {
210	                <name> $bgp-peer-group;
211	                <type> $bgp-peer-type;
212	                <local-as> {
213	                    <as-number> $local-as-number;
214	                }
215	                <local-address> $local-address;
216	                for-each ($peer-group/neighbor) {
217	                    if (name != $local-address) {
218	                    copy-of .;
219	                    }
220	                }
221	                copy-of $given-peer-detail;
222	                }
223	            }
224	            }
225	        }
226	        }
227	 
228	        var $results := {
229	        call jcs:load-configuration($connection = $local-con,
230	                        $configuration = $local-xml);
231	        }
232	 
233	        if ($results//xnm:error) {
234	        call emit-warning($message = "Got the following error while " _
235	                  "adding configuring BGP locally");
236	 
237	        for-each ($results//xnm:error) {
238	            call emit-error($message = message);
239	        }
240	        } else {
241	        expr jcs:progress("Successfully configured BGP locally");
242	        }
243	    }
244	    expr jcs:close($local-con);
245	    }
246	}
247	 
248	/*
249	* Add the current node as BGP peer in the given peer machine
250	*/
251	template add-bgp-peer($peer)
252	{
253	 
254	    expr jcs:progress("Adding this node as peer in '", $peer, "' ...");
255	 
256	    expr jcs:progress("Connecting to peer '", $peer, "' ...");
257	 
258	    var $conn = jcs:open($peer);
259	 
260	    var $xml = {
261	    <configuration> {
262	        <protocols> {
263	        <bgp> {
264	            <group> {
265	            <name> $bgp-peer-group;
266	            <type> $bgp-peer-type;
267	            <neighbor> {
268	                <name> $local-address;
269	                if ($bgp-peer-type == "external") {
270	                <peer-as> $local-as-number;
271	                }
272	            }
273	            }
274	        }
275	        }
276	    }
277	    }
278	             
279	    if (jcs:empty($conn)) {
280	    call emit-warning($message = "Not able to connect to peer " _
281	            $peer-address);
282	    call emit-warning($message = "Not able to add this node as peer in '" _
283	              $peer _ "',  add it manually");
284	    } else {
285	 
286	    expr jcs:progress("Connected to peer '", $peer, "' ...");
287	    expr jcs:progress("Loading configuration on to peer '", $peer, "' ...");
288	 
289	    var $results := {
290	        call jcs:load-configuration($connection = $conn,
291	                    $configuration = $xml);
292	    }
293	 
294	    if ($results//xnm:error) {
295	        call emit-warning($message = "Got the following error while " _
296	                  "adding the node as peer in '" _ $peer _
297	                  "', add it manually");
298	 
299	        for-each ($results//xnm:error) {
300	        call emit-error($message = message);
301	        }
302	    } else {
303	        expr jcs:progress("Successfully loaded configuration on to peer '",
304	                  $peer, "' ...");
305	    }
306	    }
307	 
308	    expr jcs:close($conn);
309	 
310	}
311	 
312	/*
313	* Get the bgp group configuration of the peer
314	*/
315	template get-peer-bgp-group-config ($address)
316	{
317	    var $conn = jcs:open($address);
318	 
319	    if (jcs:empty($conn)) {
320	    call emit-error($message = "Not able to connect to peer " _ $address);
321	    }
322	 
323	    if ($conn) {
324	    var $get-config-remote = {
325	            <get-configuration database="committed" inherit="inherit"> {
326	            <configuration> {
327	                <protocols> {
328	                <bgp> {
329	                    <group> {
330	                    <name> $bgp-peer-group;
331	                    }
332	                }
333	                }
334	            }
335	            }
336	        }
337	 
338	    expr jcs:progress("Getting BGP group '", $bgp-peer-group,
339	                "' configuration from '", $address, "' ...");
340	     
341	    var $peer-config = jcs:execute($conn, $get-config-remote);
342	 
343	    expr jcs:close($conn);
344	 
345	    copy-of $peer-config;
346	    }
347	}
348	 
349	/*
350	 * Emit the give error message
351	 */
352	template emit-error($message) {
353	    <xnm:error> {
354	    <message> $message;
355	    }
356	}
357	 
358	/*
359	 * Emit the give warning message
360	 */
361	template emit-warning($message) {
362	    <xnm:warning> {
363	    <message> $message;
364	    }
365	}

 

XML Script Contents

 

01	<?xml version="1.0"?>
02	<script>
03	  <title>add-node-bgp.slax</title>
04	  <author>rsankar</author>
05	  <synopsis>
06	    Auto-configure all nodes via remote-rpc mechanism when a node is inserted to an existing BGP mesh
07	  </synopsis>
08	  <coe>op</coe>
09	  <type>protocols</type>
10	 
11	  <description>
12	This script uses the remote-rpc (cross-box scripting) mechanism available from 9.3 onwards
13	 
14	  </description>
15	 
16	  <example>
17	    <title>Configuration</title>
18	    <description>Configuration required for this op script.</description>
19	    <config>example-1.conf</config>
20	  </example>
21	 
22	  <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml"
23	                src="../../../../../web/leaf.js"
24	            type="text/javascript"/>
25	</script>