System and User Interface Configuration

Developers create configuration files to define new commands that add new functionality to the Junos software for their applications' use.

Additionally, application code can read commands and configuration parameters from users to control the system.

Note:
User interface functionality is available only on the Routing Engine. In a Services SDK application, the user interface code runs on the Routing Engine and the Routing Engine communicates the configuration to the Multiservices PIC(s). See Reliable Configuration Download for more information.

Junos User Interface Overview

The Junos management daemon, mgd, is the software process that is responsible for managing all user access to the router. Supported User Interfaces (mgd clients) include the Junos command-line interface (CLI), the Juniper Networks tools J-Web and JUNOScope, and any third-party network management tool. mgd clients communicate with mgd using XML; mgd communicates with other daemons using plain ASCII text.

Configurations are written using Data Definition Language (DDL), which defines the syntax, options, and execution details for all operational commands and configuration statements. The structure on which all of the commands and configuration statements are based is set within the DDL files and is strictly followed when executing commands and building the configuration database. That structure, an object tree, is the basis for all DDL functionality.

The CLI communicates with mgd using JUNOScript, an internal API based on the remote procedure call (RPC) protocol and encoded in XML. For example, when the user types in a command, the CLI talks with mgd over a UNIX domain socket using JUNOScript.

To create an interface to the end user, you use Output Description Language (ODL), which defines the output rendered by the CLI when it encounters the JUNOScript XML tags returned from mgd.

To read the existing system configuration, the DDL Access (DAX) API provides a set of function calls that access the object tree that defines the system objects (also called the object database). Applications use the DAX API to check the configurations provided by the user and to configure internal state once the configuration is accepted.

For details about DDL, ODL, and DAX, see the UI Programmer's Guide the DDL Guide, and the ODL Guide, all of which are included in this documentation set. To see how DDL, ODL, and DAX fit into the larger context of writing and building an application, see also the programming task topic Creating a User Interface with DDL and ODL.

How the Management Daemon Implements the UI

At system startup, the Management daemon (mgd) does the following:

mgd knows which daemon needs to execute commands input by the user into the CLI.

mgd is connected to all the Junos system daemons. Each daemon has a UNIX domain management socket. If the command is legal, mgd opens the socket and sends the command to the appropriate daemon.

The following figure shows how the management daemon interacts with DDL and ODL.

mgd-odl-g016831.gif

DDL, ODL, and mgd

The steps in this process are as follows:

  1. The user enters a text command.

  2. The CLI wraps the text in an XML RPC request and sends the request to mgd.

  3. mgd interprets the request. If the request is an an operational command that needs to go to a daemon (for instance, show version) mgd sends the command to the daemon over its management socket in text form.

  4. The daemon parses the text and calls the appropriate function based on the parse_menu_t structures. (For details about the menu structure, see Creating a Commands Menu Array.)

  5. The function outputs its responses in XML.

  6. mgd forwards the XML response to the CLI in an XML RPC reply.

  7. The CLI uses ODL to interpret the XML reply and format the output.

  8. The formatted output is displayed for the user.

The following figure shows how mgd interfaces with the system daemons and the CLI.

mgd-and-daemons-g016438.gif

mgd in the System Architecture

DDL Processing

Within the Junos operating system, the DDL files that define configurations and user interfaces are translated by the DDL compiler (ddc) to a C source file, which then is compiled to a shared library and loaded by the management daemon to build a data file containing the schema. The following figure shows this process, together with the source and object file naming:

mgd-ddl-schema-g016832.gif

Generating the Configuration Schema

Command Hierarchy

The schema organizes the CLI commands in a hierarchy. Commands that perform a similar function are grouped together under the same level of the hierarchy. For example, all commands that display information about the system and the system software are grouped under the show system command, and all commands that display information about the routing table are grouped under the show route command.

The following figure illustrates a portion of the show command hierarchy.

cli-show-command-1411.gif

Sample CLI Command Hierarchy

To execute a command, a user enters the full command name, starting at the top level of the hierarchy. For example, to display a brief view of the routes in the router table, you use the command show route brief.

Similarly, the commands used for system configuration have their own hierarchy. For example, the following figure illustrates a part of the hierarchy tree. The protocols statement is a top-level statement at the trunk of the configuration tree. The ospf, area, and interface statements are all subordinate container statements of a higher statement (they are branches of the hierarchy tree), and the hello-interval statement is a leaf on the tree.

cli-hierarchy-1412.gif

CLI Hierarchy Tree

For more information on the Junos CLI and the options it provides, see the Junos CLI User Guide, provided with your Junos documentation.

More About the Configuration Hierarchy

As just explained, the configuration database is structured as a hierarchy of objects using a tree structure.

The parent nodes in the tree contain objects or containers for objects (for example, address_value) and the terminating leaf nodes contain the data values (for example, 10.0.0.1). For example, part of the schema might look like this:

	unit 
	    unit number 
	    family 
                inet
                address 
		    address_item (of which there could be more than one)
                        address value

The Junos software defines pointers to point to each node, so a corresponding part of the database might look like this:

	unit 0  <----------pointer to unit object
           0    <----------pointer to unit number attribute
	   family inet  <------pointer to family object
               inet     <------pointer to inet attribute
               address  <------pointer to address container
                   address_item      <--------pointer to address object
                      address_value  <--------pointer to address attribute
                                              value (for example, 10.0.0.1)

As shown here, the attributes at the leaf level (address_value) represent the actual data. Attributes are objects; not all objects are attributes. In C language terminology, you can think of objects as being like structures, and of attributes as being like primitives.

Objects can contain other objects, and objects can contain attributes; however, attributes cannot contain other objects or attributes.

These concepts become important when you use the DDL Access (DAX) API, which is introduced in The DAX API and Using DAX to Read Configurations.

Configuration Model

The Junos UI makes a clear distinction between the operational and configuration aspects of device management. The Junos CLI user can be in one of two modes:

To change settings on the router, you use the configuration mode of the CLI to work on the candidate configuration file. In configuration mode, you can do the following:

In general, a piece of the configuration will be read by one daemon.

The configuration is often stored in a tree or hierarchy.

Processes can optionally be enabled or disabled by the presence of configuration for them.

All changes are made to a candidate database; changes are not final until a commit takes place.

How Configuration Changes Are Processed

The following information is important to understand so your application can be aware of when your configuration changes have been implemented in the database.

When the user executes a commit to save the configuration, the Junos operating system validates the configuration. Judging by which parts of the configuration have changed, mgd knows which daemons need to be notified (or possibly started or stopped). The Junos operating system spawns a temporary new instance of each daemon to perform an artificial configuration read and make sure all daemons have been successful. This is known as the configuration check phase.

To distinguish this phase from normal operation, the Junos operating system starts the daemon with the -c command-line option. This causes the daemon to invoke its configuration read function with the check argument set to 1 to indicate that the configuration should be read and checked. You can get a report using the commit check command.

For more information about configuration read code and how it works with initialization, see the Initializing an Application programming topic.

The daemon then has the opportunity to accept or reject the configuration. To accept it, the configuration read function you specify in the junos_daemon_init() function call should simply return 0. To reject it, it should return -1. This value is immediately propagated to mgd as the process return code.

When in configuration check phase, the daemon must do nothing but read the configuration and return. The configuration read function is not allowed to rely on any other callback function to be invoked, not even the initialization callback. This is so because while in configuration check, two instances of the same daemon are running. Moreover, mgd expects these temporary daemons to return quickly; if a daemon takes too long to perform its configuration check, mgd kills and re-spawns it. If after a number of tries the configuration check does not succeed, the check phase is considered failed and the commit is rejected.

Thus, if you want to include any functionality in the configuration read function that requires waiting (such as for a server response), your code must first verify that the check argument is not set to 1 - that is, it must execute the functionality only if the configuration read function is not being invoked by the temporary daemon.

The configuration the temporary daemons read is called the candidate configuration. It is only accessible to daemons in the configuration check phase. The real daemons only see the committed configuration.

If the commit check is successful, the system executes the commit by copying the candidate configuration file into the running configuration file.

At this point, the real daemons read their configuration. Upon startup, each daemon registers a callback, the configuration read function, to load its configuration. The configuration DDL for the daemon can (when compiled) generate macros to help this function traverse the part of the configuration tree for which it is responsible.

The DDL Access (DAX) APIs allow programs to traverse the configuration (see The DAX API); the patricia tree functions in libjuniper allow applications to store and re-access the loaded configuration. For details on using the patricia tree APIs, see Using the Patricia Tree Library.

Creating Configurations

The user interface provided by the Junos software starts with DDL files. As an SDK developer, there are three ways you might interact with DDL configurations:

Configuration DDL is found in .cnf.dd files. Generally, each daemon has one DDL file. Configuration DDL is compiled by the SDK DDL compiler (ddc) and interpreted by mgd:

DDL Examples

ddc has no knowledge of the daemon names used by the SDK. This example configures a new statement, daemon-names, to define the list of valid daemon names for a project, allowing ddc to check for misspelling in the notify statement.

The following code inserts an application into the protocols hierarchy and shows how the notify statement could be configured with respect to the acme_app1 application:

acme_app1.cnf.dd:

001	#define ACME_APP1 "acme-app1"
002
003	daemon-names ACME_APP1;
004
005	object protocols {
006	   object acme-app1 {
007	      notify ACME_APP1;
008	      attribute time-out {
009		 type uint;
010		 help "Time to wait before failing..";
011	      }
012	   }
013	}

001 - Macro to define the daemon name.

003 - The daemon-names statement tells the DDL compiler what names are valid for the notify statement.

006 - acme-app1's configuration is inserted into the [edit protocols] hierarchy.

007 - The notify statement tells mgd to send a SIGHUP to acme-app1 if any configuration under [edit protocols acme-app1] changes.

The following example shows the DDL to define a show active-session command for the same application:

acme_app1.cmd.dd:

001	#define ACME_APP1 "acme-app1"
002
003	daemon-names ACME_APP1;
004
005	command show {
006	  command acme-app1 {
007	    command active-session {
008	      action execute ACME_APP1;
009           xml-name get-acme-app1-active-session;
010	      help "Displays active session for app1";
011	    }	
012	  }
013	}

001 - Macro to define the daemon name.

003 - The daemon-names statement tells the DDL compiler what names are valid for the execute statement.

007 - This sets up the show acme-app1 active-session operational command.

008 - Tells mgd to send the command to acme-app1.

009 - Sets up the JUNOScript XML tag for the command get-acme-app1-active-session.

An acme_app1_ui.c file contains the command handler for active-session.

Operational Command Model

Operational commands return information about the current status of an application, return statistics, or can trigger behavior. The CLI passes the command the user types to mgd directly, and mgd uses the input to communicate with the required daemons to perform the requested operation.

mgd sends the ASCII text command to the daemon handling the command across a management socket that is automatically created when each daemon starts. mgd can also send quit commands this way, unless daemon restarting is disabled.

Command syntax is defined in Command DDL. Command DDL files have the .cmd.dd extension. Each daemon defining commands generally has its own command DDL file. The file is compiled by ddc and interpreted by mgd:

Handling Operational Commands

Upon startup each daemon registers a master menu which holds the organization of callback functions to handle each operational command. The system automatically parses the command string and calls appropriate functions using the master menu. There is an API to parse any arguments (options) sent with the command; these arguments are also defined in the command DDL.

You define the menus by creating a series of arrays that specify the command hierarchy, the arguments a command can take, and the callback that is executed to retrieve the data required by the command. For details about how to create menus, see Creating a Commands Menu Array.

Each function handling a command must return JUNOScript (XML) for communicating with mgd through the management socket. The syntax of the response is defined by a DTD, and the DTD is built using the Output Definition Language (ODL). There is an API to help write the JUNOScript response; the API is available in your backing sandbox at src/junos/lib/junoscript/h/junoscript/xmlrpc.h, and its usage is documented in the ODL Guide that accompanies this documentation set.

You can show a command's response in XML format for debugging or testing purposes. For example:

show chassis hardware | display xml

ODL

An ODL file captures in one place all the information that the Junos software needs about a tagged piece of data:

ODL is compiled by the ODL compiler, odc. The compiler creates macros (for tag names and styles) that are helpful to use in the functions generating the response to the operational command. ODL allows the developer to create multiple formatting options for the same structure of tags, and then apply one option as a style in the returned response. The libraries made from compiled ODL can read the style and display the response in the CLI appropriately.

A style is often selected using an argument to a command: for example, brief, detail, summary.

There are three types of output:

ODL Example

A sample ODL statement is:

tag administrative-status {
       type enum string {
         choice "up" {
       define IFX_ADMIN_STATUS_UP;
         }
         choice "down" {
       define IFX_ADMIN_STATUS_DOWN;
         }
         choice "test" {
       define IFX_ADMIN_STATUS_TEST;
         }
     }
}

The ODL compiler generates an <administrative-status> tag in XML. In the following example, the tag contains the value test:

<administrative-status>test</administrative-status>

Route Configuration


© 2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5