Automation

last person joined: 21 hours ago 

Ask questions and share experiences about Apstra, Paragon, and all things network automation.
  • 1.  Commands executed in the wrong order

    Posted 01-12-2011 05:15

    I recently started learning Junos scripting and have run into a confusing problem: The different steps are executed in the wrong order. Either there is some fundamental property of the language that I haven't yet grasped, or I have encountered a weird bug.

    What I'm trying to do is to save the configuration to a file and then upload that file to an FTP server. Here's the script:

    /* upload-conf.slax */
    version 1.0;
    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";
    import "../import/junos.xsl";

    match / {
        /* Save the configuration to a file. */
        /* Didn't find an API element corresponding to the following command. */
        var $save-cmd = <command> "show configuration | save test.confg";
        var $save-results = jcs:invoke($save-cmd);
        <op-script-results> {
            /* If the following line is left out, the command is not executed. */
            copy-of $save-results;
        }
        
        /* Ask for username and password and then upload the file to an FTP server. */
        var $username = jcs:get-input("Username:");
        var $password = jcs:get-secret("Password:");
        var $copy-cmd = <file-copy> {
            <source> "test.confg";
            <destination> "ftp://" _ $username _ ":" _ $password _ "@192.0.2.17/";
        }
        var $results = jcs:invoke($copy-cmd);
        expr jcs:output("Uploaded file.");
    }



    This is what happens when I run the script:

    me@router> op upload-conf
    Username:me
    Password:
    Uploaded file.
    Wrote 856 lines of output to 'test.confg'

    me@router>


    As you can see, both steps are executed, but the configuration file isn't saved until after it has been transferred. It seems as if this is done as the very last step of the script, when the <op-script-results> hierarchy is returned. I tried a couple of jcs:sleep() calls to verify that it's not a timing issue and I verified that the file that ends up on the FTP server is indeed the old version of the file. The behaviour is the same even for other commands that are specified as <command> with a command-line string instead of being invoked through the API.

    Any ideas on what I'm doing wrong and how to fix it?

    The Junos version is 10.2S5.3.



  • 2.  RE: Commands executed in the wrong order

    Posted 01-14-2011 08:07

    The issue here isn't commands being executed in the wrong order, it is output being displayed in the wrong order. The jcs:output() function displays output immediately, but output generated via the result tree is not displayed until the script has terminated. So the commands are being done as expected, but you are not seeing the first output until the end because it is being written to the result tree.

     

    Either display the save results using jcs:output(), or use the <output> result tree element to write the "Uploaded file" message, but you don't want to mix jcs:output() with result tree output due to the confusing behavior that you are referring to here.



  • 3.  RE: Commands executed in the wrong order

    Posted 01-15-2011 03:57

    My initial assumption of what was going on was exactly the same as yours. Unfortunately there is something even more strange going on here. It appears that it is the very act of displaying the result tree that causes the command to be executed. If I remove the line "copy-of $save-results;" from the script, the command isn't even executed. I can verify this by looking at the file either locally on the router or on the FTP server.

     

    Believe me, the script behaves as I describe even if it may seem totally counter-intuitive. Otherwise I wouldn't be turning to this forum for help. I tested initially on Junos 10.2S5.3 but also verified that the behaviour is the same on another router running 9.3S2.1.



  • 4.  RE: Commands executed in the wrong order
    Best Answer

    Posted 01-15-2011 04:59

    Hmm...I hadn't looked at the exact command that you used, but now I noticed that you had used the pipe and the save option. Generally, using the pipe in a command-line isn't supported as it is intended to be run within the CLI session itself. The recommended way to save the text config would be to request it like this:

     

    var $config-rpc = <get-configuration database="committed" format="text">;

    var $config = jcs:invoke( $config-rpc );

     

    And then to save it like this:

     

    var $save-rpc = {

        <file-put> {

            <filename> "test.cnfg"

            <encoding> "text";

            <file-contents> $config;

        }

    }

    var $results = jcs:invoke( $save-rpc );

     

    As it is, apparently whatever is returned in the result tree causes the file to be saved as part of the result tree processing, but once again, the issue is the jcs:output() displays its output while the script runs, but then, I guess, this action is being performed as part of the result tree processing after the script terminates. Replace jcs:output() with <output> (as a child of <op-script-results>) and the order will be resolved, since <output> is displayed as the result tree gets processed.

     

    Also, could you do me a favor and run your script with | display xml and send the results? I'm curious what exactly your script is sending in its result tree. I've never tried to use a "| save ..." command in that way with the result tree.

     

    Thanks



  • 5.  RE: Commands executed in the wrong order

    Posted 01-15-2011 06:49

    Thanks a lot! The combination of the <get-configuration> and <file-put> API elements is obviously the correct way of handling this. I modified the script and got it working correctly.

    Adding a "| display xml" when running the original script resulted in another type of interesting behaviour. To begin with, displaying the output as XML in combination with jcs:input() completely locked up my terminal window. I fixed that by hard-coding the username and password. The first time I ran the modified script, it looked like this:

    me@router> op upload-conf | display xml
    <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.2S5/junos">
        <output>
            Uploaded file.
        </output>
        <pipe>
            <more-save-file>
                test.confg
            </more-save-file>
        </pipe>
        <configuration-information>
            <configuration-output>
                ## Last commit: 2011-01-15 12:21:27 CET by me
                version 10.2S5.3;
                groups {
                    /* Apply once in [protocols isis] */
                    ISIS_DEFAULTS {
    Wrote 1704 lines of output to 'test.confg'

    me@router>

     

    As you can see, the first few lines of my configuration were sent to the terminal and the rest was written to the file. Next time I ran exactly the same script, I saw this:

    me@router> op upload-conf | display xml
    <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.2S5/junos">
        <output>
            Uploaded file.
        </output>
        <pipe>
            <more-save-file>
                test.confg
            </more-save-file>
        </pipe>
    Wrote 1711 lines of output to 'test.confg'

    me@router>


    All of the config ended up in the file on disk this time. Trying the same command one more time resulted in this output:

    me@router> op upload-conf | display xml
    <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.2S5/junos">
        <output>
            Uploaded file.
        </output>
        <pipe>
            <more-save-file>
                test.confg
            </more-save-file>
        </pipe>
        <configuration-information>
            <configuration-output>
                ## Last commit: 2011-01-15 12:21:27 CET by me
                version 10.2S5.3;
                groups {
                    /* Apply once in [protocols isis] */
                    ISIS_DEFAULTS {
                        protocols {
                            isis {
    Wrote 1702 lines of output to 'test.confg'

    me@router>


    I verified that the file on disk was indeed missing the first few lines.

    I don't know if this inconsistent behaviour may be related to my inital problems of getting things to execute in the right order. I'll follow your advice and avoid the pipe character in commands in my scripts in the future.