ilx plugin
ilx plugin(1) BIG-IP TMSH Manual ilx plugin(1)
NAME
plugin - Configures an iRules Language Extension (ILX) Plugin.
MODULE
ilx
SYNTAX
Configure the plugin component within the ilx module using the syntax shown in the following sections.
CREATE/MODIFY
create plugin [name]
options:
app-service [name]
description [string]
disabled
enabled
from-workspace [name]
log-publisher [name]
modify plugin [name]
options:
app-service [name]
description [string]
disabled
enabled
extensions {
[name] {
command-arguments [ list of strings ]
command-options [ list of strings ]
concurrency-mode [ dedicated | single ]
data-groups [ [ [name ] ...] | none ]
debug-port-range-high [port]
debug-port-range-low [port]
description [string]
heartbeat-interval [seconds]
ilx-logging [ disabled | enabled ]
log-publisher [name]
max-restarts [integer]
restart-interval [integer]
trace-level [integer]
}
}
from-workspace [name]
log-publisher [name]
reset-stats plugin [ [ [name] | [glob] | [regex] ] ... ]
options:
extensions { [name] ... }
DISPLAY
list plugin
list plugin [ [ [name] | [glob] | [regex] ] ... ]
show running-config plugin
show running-config plugin [ [ [name] | [glob] | [regex] ] ... ]
options:
all
all-properties
disk-space
node-version
non-default-properties
one-line
partition
recursive
staged-directory
show plugin
show plugin [ [name] ... ]
options:
all
all-properties (default | exa | gig | kil | meg | peta | raw | tera |
yotta | zetta)
extensions { [name] ... }
field-fmt
recursive
DELETE
delete plugin [name]
options:
all
recursive
START
start plugin [name]
STOP/RESTART
restart plugin [name]
stop plugin [name]
options:
drain-existing-connections
immediate
stop-draining
DESCRIPTION
An iRules Language Extension (ILX) plugin provides the following functionality:
An RPC interface that allows an iRule to communicate with an ILX Node.js(tm) process.
A Streaming interface that allows an ILX Node.js(tm) process to manage Virtual
Server connections and payload data.
A plugin is created from an ilx workspace. Files from the workspace are copied into a system area and run from the system
area. iRule files contained in the workspace are read into the system as ltm rule configuration. The ltm rule
configuration objects are created in a sys folder that has the same name as the plugin.
The system will start one or more Node.js(tm) process for each extension (see also concurrency-mode below). Node.js(tm)
will look in the extension directory for the file package.json. Node.js(tm) will look in package.json for a main field that
identifies the main entry point of the plugin. If the main field is not present node will look for the file index.js.
The status of plugin processes can be viewed with the show command.
show plugin my_plugin
A plugin can be started, stopped and restarted. When a plugin is initially created the system will start processes for each
extension. When a plugin is stopped existing plugin processes associated with active tmm connections are allowed to drain.
Draining processes continue to run until the connections are closed. There are several options that control how processes
are stopped, drain-existing-connections, immediate and stop-draining, and are describe below.
There are several ILX commands that an iRule may use to communicate with a Node.js(tm) extension process: ILX::init,
ILX::call and ILX::notify.
ILX::init [plugin name] [extension name] establishes a communication path from an iRule to the node process. It
returns a handle that must be passed to ILX::call and ILX::notify.
ILX::call [ILX handle] [method] [optional arg 1] [optional arg 2] ...... invokes the specified node method in the
extension associated with the ILX handle. If the node method returns a javascript array or dictionary then a Tcl list
object is returned from ILX::call, otherwise a Tcl string object is returned.
ILX::notify [ILX handle] [method] [optional arg 1] [optional arg 2] ...... sends a message to the node method but
does not wait for the method to complete before returning. TCL_OK is returned if the message was successfully queued.
Any other return value indicates the message could not be queued.
RPC
The RPC API consists of two primary components, Node.js and Tcl.
The Node.js API contains an ILXServer class. Methods are added to the server using ILXServer.addMethod("method name",
function(req, res) { ... }). "req" is an ILXRequest object and "res" is an ILXResponse object. ILXServer.listen will start
the server.
A Tcl iRule connects to the Node.js process using the Tcl command
set plugin [ILX::init "plugin name" "extension name"]
The Javascript methods are invoked from a Tcl iRule using either ILX::call or ILX::notify. The args are user defined and
passed to the Node.js method via the ILXRequest object.
set response [ILX::call $plugin "method name" args...]
ILX::notify is similar to ILX::call except that the iRule will not wait for a response from the Node.js process.
ILX::call $plugin "method name" args...]
Here is a Hello World Node.js script
var f5 = require('f5-nodejs');
var server = new f5.ILXServer();
server.addMethod("hello_world", function(req, res) {
console.log("request args: " + JSON.stringify(req));
res.reply('hello_world');
});
server.listen();
Here is the Hello World Tcl iRule that passes some data to the Node.js process, waits for a response and logs the response
to /var/log/ltm. The iRule must be associated with an ltm virtual-server.
when CLIENT_ACCEPTED {
set plugin [ILX::init rpc example]
set rv [ILX::call $plugin hello_world arg1 val1 arg2 val2]
log local0.debug $rv
}
Run the following tmsh commands to create the ilx workspace and ilx plugin configuration for the RPC example above. See
also help ilx workspace for more examples describing how to manage a workspace.
create ilx workspace rpc
create ilx workspace rpc extension example
edit ilx workspace rpc extension example
A file named index.js will be created. Replace the content of
index.js with the Node.js Hello World script above. If you
have bash shell access you can directly edit the file
/var/ilx/workspaces/Common/rpc/extensions/example/index.js.
edit ilx workspace rpc rule example
A file named rpc_example.tcl will be created. Replace the
content of rpc_example.tcl with the Tcl iRule Hello World
example above. If you have bash shell access you can directly
edit the file
/var/ilx/workspaces/Common/rpc/rules/hello_world.tcl.
create ilx plugin rpc from-workspace rpc
modify ltm virtual [name] rules { rpc/example }
You must create a Virtual Server and associate the rpc_example
rule with the Virtual Server. When a client connects to the
Virtual Server you should see the output from both the
Node.js process and Tcl iRule in /var/log/ltm.
See also the BIG-IP iRulesLX User Guide located in the Programmability Wiki at devcentral.f5.com.
Streaming
The Streaming API allows a Node.js Plugin process to act as a proxy for connections through a Virtual Server. When a client
connects to a Virtual Server an ILXFlow object is created and passed to the plugin. The ILXFlow object contains two Node.js
sockets. ILXFlow.client represents the connection from the client to the plugin. ILXFlow.server represents the connection
from the plugin to a server. The plugin will use ILXFlow.client to receive or send data to the client. The plugin will use
ILXFlow.server to send or receive data from the server. The plugin may inspect or modify any/all client or server data. The
ILXFlow.client and ILXFlow.server objects behave as native Node.js sockets. The plugin can also be configured to act as a
server and respond directly to the client without completing a connection to a server. The plugin can also be configured as
a native Node.js HTTP server.
[Client] <-> [Virtual Server] <-> [TMM]
^
|
v
[ILXFlow.client]
[Plugin]
[ILXFlow.server]
^
|
v
[TMM] <-> [Server]
Note that the plugin sees TCP payload. TCP headers are stripped by the TMM and are not visible to the plugin.
The following is a brief overview of the Javascript classes that make up the Streaming API. These classes contain many more
features and options as described in the BIG-IP iRulesLX User Guide located in the Programmability Wiki at
devcentral.f5.com.
ILXPlugin - Connects to the TMM to accept Virtual Server client connections. When a connection is made an ILXFlow object
is passed to the plugin via the "connect" event: plugin.on("connect", function(flow) { ... }).
ILXPluginOptions - Options that configure the events and data that a plugin will received.
ILXFlow - An object that represents a client socket to Virtual Server and server socket to a server.
ILXStream - An object that represents the client side connection from a client to a Virtual Server (ILXFlow.client), the
server side connection from a Virtual Server to a server (ILXFlow.server), or a plugin initiated connection to a server
(created using ILXStream.connect).
ILXLbOptions - Options that allow the plugin to specify which server the client will connect to by calling
ILXFlow.lbSelect(ILXLbOptions).
ILXTable - Functions for reading and writing the TMM Session DB. Very similar interface to the Tcl iRule table command.
ILXBufferUtil - Functions for searching and modifying a Node.js Buffer object.
ILXDatagroup - Functions for accessing ltm data-group configuration. The set of data-groups available to a plugin must be
specified using the ILXPluginOptions when the plugin is started.
ILXTransaction - If HTTP and ILX profiles are attached to a virtual server then all header and data inspection and
modification are done in the context of request and response transaction. An ILXTransaction object is passed to the
following events: requestStart, requestComplete, responseStart and responseComplete. The ILXTransaction object contains
things like request headers, URI and method, and response headers and status.
The following is a sample streaming plugin that acts as a pass through. Data is read from the client and sent to the
server. Data is read from the server and sent to the client. Note that it is important to handle "error" events as the
Node.js plugin process will exit if they are not handled.
var f5 = require("f5-nodejs");
var plugin = new f5.ILXPlugin();
plugin.on("connect", function(flow) {
flow.client.on("readable", function() {
var buffer;
while (true) {
buffer = flow.client.read();
if (buffer === null) {
break;
}
console.log("Client Data");
console.log(buffer.toString());
flow.server.write(buffer);
}
});
flow.client.on("error", function(err) {
console.log("client socket error: " + err);
});
flow.server.on("readable", function() {
var buffer;
while (true) {
buffer = flow.server.read();
if (buffer === null) {
break;
}
console.log("Server Data");
console.log(buffer.toString());
flow.client.write(buffer);
}
});
flow.server.on("error", function(err) {
console.log("server socket error: " + err);
});
flow.on("error", function(err) {
console.log("flow error: " + err);
});
});
var options = new f5.ILXPluginOptions(); // use defaults
plugin.start(options);
The following is a sample streaming HTTP plugin that acts as a pass through. Note that the example above can also be used
to manage HTTP traffic. This example requires a Virtual Server with both HTTP and ILX profiles.
var f5 = require('f5-nodejs');
var plugin = new f5.ILXPlugin();
plugin.on("connect", function(flow)
{
flow.client.on("requestStart", function(request) {
// HTTP request URI, headers and more
console.log(
"requestStart: " + JSON.stringify(request.params));
});
flow.client.on("readable", function() {
// HTTP request body, if present
var buf;
while (true) {
buf = flow.client.read();
if (buf !== null) {
console.log("request body:" + buf.length + " bytes");
console.log(buf.toString());
flow.server.write(buf);
}
else {
break;
}
}
});
flow.client.on("requestComplete", function(request) {
// Entire HTTP request received
console.log(
"requestComplete: " + JSON.stringify(request.params));
request.complete();
});
flow.client.on("error", function(err) {
console.error("flow.client error:" + err);
});
flow.server.on("responseStart", function(response) {
// HTTP response headers, status and more
console.log(
"responseStart: " + JSON.stringify(response.params));
});
flow.server.on("readable", function() {
// HTTP response body, if present
var buf;
while (true) {
buf = flow.server.read();
if (buf !== null) {
console.log(
"response body:" + buf.length + " bytes");
console.log(buf.toString());
flow.client.write(buf);
}
else {
break;
}
}
});
flow.server.on("responseComplete", function(response) {
// Entire HTTP response received
console.log(
"responseComplete: " + JSON.stringify(response.params));
response.complete();
});
flow.server.on("error", function(err) {
console.error("flow.server error:" + err);
});
flow.on("error", function(err) {
console.error("flow.error:" + err);
});
});
var options = new f5.ILXPluginOptions(); // use defaults
plugin.start(options);
Run the following tmsh commands to create ilx workspace and ilx plugin configuration for a streaming plugin using either of
the sample plugins above.
create ilx workspace streaming
create ilx workspace streaming extension example
edit ilx workspace streaming extension example
A file named index.js will be created. Replace the content of
index.js with the Node.js streaming example from above. If
you have bash shell access you can directly edit the file
/var/ilx/workspaces/Common/streaming/extensions/example/index.js.
create ilx plugin streaming from-workspace streaming
modify ilx plugin streaming extensions { example { ilx-logging
enabled concurrency-mode single } }
When ilx-logging is enabled all stdout and stderr from the
plugin is sent to
/var/log/ilx/..,
in this case /var/log/ilx/Common.streaming.example.
create ltm profile ilx streaming-profile plugin streaming
modify ltm virtual [name] profiles replace-all-with {
tcp streaming-profile }
You must create a Virtual Server and associate the
streaming-profile with the Virtual Server. When a client
connects to the Virtual Server the client should receive the
server data. The plugin also logs the client and server data
that is received to /var/log/ilx/Common.streaming.example.
If you are using the HTTP sample you will need to assign an HTTP
profile to the virtual server.
EXAMPLES
create plugin my_plugin from-workspace my_workspace
Creates a plugin named my_plugin. Rule files from the workspace are read into the system configuration and placed in the
sys folder my_plugin.
modify plugin my_plugin from-workspace my_workspace
Restart the plugin using the current files in my_workspace.
modify plugin my_plugin extensions { my_extension { concurrency-mode dedicated } }
Modify the concurrency-mode for a specific extension.
delete plugin my_plugin
Deletes the plugin named my_plugin. The iRule configuration in the sys folder named my_plugin will also be deleted. The sys
folder my_plugin will be deleted if there are no remaining (non-plugin related) configuration items in the folder.
list plugin
List the configuration for all plugins in the current sys folder.
list plugin my_plugin
List the configuration for my_plugin.
show plugin my_plugin
Displays the status of all extension processes running as part of my_plugin.
show plugin my_plugin extensions { my_extension }
Displays the status of processes in extension my_extension running as part of my_plugin.
reset-stats plugin my_plugin
Reset all statistics for my_plugin.
reset-stats plugin my_plugin extensions { my_extension }
Reset statistics for the extension my_extension in my_plugin.
start plugin my_plugin
Starts all extensions in my_plugin.
stop plugin my_plugin
Stops all extensions in my_plugin. Active processes and connections are allowed to drain.
stop plugin my_plugin drain-existing-connections
Stops all extension processes in my_plugin. Active connections that are currently using the plugin are allowed to drain.
The plugin processes will be stopped when all associated active connections are closed.
stop plugin my_plugin immediate
Immediately stops all extension processes associated with my_plugin. New and existing connections to Virtual Servers that
have iRules that interact with the plugin will receive a Tcl error when using the Tcl functions ILX::init and ILX::call.
stop plugin my_plugin stop-draining
Immediately stops all extension processes in my_plugin that are draining. Existing connections that have iRules that
interact with the plugin and were attached to the draining processes will receive a Tcl error when using the Tcl functions
ILX::init and ILX::call.
OPTIONS
app-service
Specifies the name of the application service to which the pool belongs. The default value is none. Note: If the
strict-updates option is enabled on the application service that owns the object, you cannot modify or delete the
plugin. Only the application service can modify or delete the plugin.
description
User defined description.
disabled
Disable the plugin. All node processes associated with the plugin that are associated with active tmm connections are
allowed to continue until the connections close. To immediately stop all processes use the stop command.
enabled
Enable the plugin. Node processes will be started for each plugin extension.
extensions
Modify attributes of plugin extensions.
command-arguments
The optional list of arguments to be passed to the nodejs (after the extension).
Eg.:
command-arguments { arg1 arg2 }
will result in nodejs process started like this:
/usr/bin/nodejs /extensions/ arg1 arg2
The plugin must be restarted for this setting to take affect.
command-options
The list of options passed to Node.js before the name of the extension script. These must be valid Node.js
options. The Node.js process will fail to start if it is provided with invalid options.
Example:
command-options { --debug-brk=12345 }
will result in nodejs process started like this:
/usr/bin/nodejs --debug-brk=12345 /extensions/
Please note the choice of the specified port is not guaranteed. If the specified port is not available, the
system will choose another consecutive port (see Debugging section for more details).
The plugin must be restarted for this setting to take affect.
concurrency-mode
Specifies a concurrency mode for the extension.
The value dedicated specifies that a node process should be started for each tmm that has been provisioned (see
sys db provision.tmmcountactual). Each node process will be dedicated to servicing requests from a single tmm.
The value single specifies that a single node process should be started. This node process will service requests
from all tmm processes in the system.
data-groups
The set of data-groups that will be made available to the plugin through the ILXDatagroup JavaScript class. The
default value is none.
debug-port-range-high
When debugging is enabled and the debug port is not specified in command-options, ILX will assign the port,
searching for an available port to attach the node inspector, see the section on Debugging. It will start
searching at the debug-port-range-low value and try each port until it reaches the debug-port-range-high value.
debug-port-range-low
When debugging is enabled and the debug port is not specified in command-options, ILX will assign the port,
searching for an available port to attach the node inspector, see the section on Debugging. It will start
searching at the debug-port-range-low value and try each port until it reaches the debug-port-range-high value.
description
User defined description.
heartbeat-interval
Specifies the maximum number of seconds between extension process heartbeats. The extension process heartbeat is
updated by the BIG-IP version of libuv. The BIG-IP monitors the heartbeat of each extension process. When
enabled the system will restart an extension process if the extension does not update its heartbeat over the
configured interval. A value of 0 (zero) disables heartbeat checking. The heartbeat should be disabled when the
extension is being debugged.
ilx-logging
Specifies where standard out and standard error generated by the plugin will be logged. A value of disabled will
cause output to be logged to /var/log/ltm. A value of enabled will cause output to be logged to
/var/log/ilx/[plugin].[extension] (enabled). A CPU identifier will be appended to the log file name if the
concurrency-mode is dedicated. Setting the value to enabled is intended to aid in debugging a plugin and not
overrun /var/log/ltm with debug logs. The default value is disabled.
log-publisher
Specifies the log destination for messages generated by the ILXLogger nodejs object in an extension. See sys
log-config publisher.
node-version
Display the Node.js version that is used to run the plugin.
max-restarts
Specifies the maximum number of times an extension process may fail before the system will no longer
automatically restart the process. See also restart-interval. The default value is 5.
restart-interval
Specifies the interval, in seconds, over which max-restarts may occur. The default value is 60 seconds.
trace-level
Specifies the global trace level for an extension. This can also be controlled by an extension using the
Javascript function ILXPlugin.setGlobalTraceLevel (note that this does not update the extension configuration,
only the running extension). An extension may use this setting in Javascript by calling
ILXPlugin.globalTraceLevel(). F5 extension internals also use this setting to log interaction between the
configuration system, the TMM and the plugin extension. A value of zero will stop trace logging. A value of 1
will log configuration messages. A value of 10 will log general function call location information. A value of 20
will include function call information in the packet path. A value of 30 will include packet content that is sent
and received to and from the TMM. Note that if the trace level has been set by Javascript code in the plugin
using ILXPlugin.setGlobalTraceLevel and the extension trace-level setting is zero then to disable tracing in the
plugin you must update the plugin code. See also ilx-logging.
from-workspace
Create or modify a plugin using the set of files in the specified workspace. The workspace files are copied into a
system are. New node process are started using the latest copy of workspace files. Existing node processes continue to
run until all tmm connections associated with those processes have closed.
log-publisher
Specifies the log destination for messages generated by the ILXLogger nodejs object without an extension level log-
publisher. See sys log-config publisher.
name Specifies a unique name for the component. This option is required for the commands create and modify.
staged-directory
Display the workspace directory that was used to create the plugin.
Debugging
In order to debug an ILX extension the user must enable debugging via command-options and restart the plugin. Node.js
provides three options for enabling remote debugging: --debug[=], --debug-port= and --debug-brk=.
If a debug port is specified the system will search for an available port starting with the specified port. Please note
that the debugging can only be enabled in single concurrency mode.
modify ilx plugin my_plugin extension { my_extension { command_options add { --debug } } }
restart ilx plugin my_plugin
If a debug port is not specified with either --debug=, --debug-brk= or --debug-port=, the system will
search for an available port within the configured debug-port-range-low and debug-port-range-high range. If a port is
specified the system will perform a search for an available port using the specified port instead of the debug-port-range-
low value. The assignment of the specified port is best-effort and is not guaranteed. In both cases the search for ports
is consecutive.
There is a system-wide list of ports that will be skipped during the debug port search:
Eg.
# list ilx global-settings
ilx global-settings {
debug-port-blacklist { 47019 54321 60000 }
}
The node-inspector process must be started at the bash command line, specifying a valid IP address that is either a self-ip
(net self-ip) or the management IP address (sys management-ip).
/usr/local/node/v6/lib/node_modules/.bin/node-inspector --web-host --no-inject
It will then be possible to connect to the IP address using the port that the system chose. The debug port that the system
chose can be seen by running the command show plugin my_plugin.
show plugin my_plugin extensions { my_extension }
...
-------------------------------
| Extension Process: my_extension
-------------------------------
| Status running
| PID 1190
| TMM 0
| CPU Utilization (%) 0
| Debug Port 20000
| Memory (bytes)
| Total Virtual Size 0
| Resident Set Size 0
| RPC Info
...
It is then possible to connect with a suitable debugging client, such as the Chrome(tm) browser via:
https://:8080/debug?port=20000
The externally reachable port opened by node-inspector is ":8080". Port "20000" is the port displayed by the show ilx
plugin command.
Statistics
Provided the ILX-RPC and ILX Streaming can be used simultaneously there are designated sections for each in the stats.
The plugin statistics are reset every time the plugin is restarted. Additionally the statistics can be reset from the tmsh
(see EXAMPLES above).
The output looks like the following:
---------------------------------
ILX::Plugin: my_plugin
---------------------------------
State enabled
Log Publisher local-db-publisher
-------------------------------
| Extension: my_extension
-------------------------------
| Status running
| CPU Utilization (%) 0
| Memory (bytes)
| Total Virtual Size 0
| Resident Set Size 0
| RPC Info - ILX-RPC Specific information
| RPC Connections
| Active 0 - active RPC connections
| Total 0 - total RPC connections (ILX::init calls)
| Total Calls 0 - total RPC calls (ILX::call calls)
| Notifies 0
| Timeouts 0 - number of expired connections
| Errors 0 - number of connection errors
| Octets In 0 - number of octets received
| Octets Out 0 - number of octets sent
| Average Latency 0 - average time that it takes node to respond to an iRule ILX::call
| Max Latency 0 - max response time it took node to respond to an iRule ILX::call
| Streaming Info - ILX Streaming specific information
| Flow Connections - virtual server initiated connections.
| Clientside
| Active 0 - active clientside connections
| Total 0 - total connections
| Serverside
| Active 0 - active serverside connections
| Total 0 - total connections
| Sideband Connections - connections initiated with .connect() call
| Active 0 - active connections
| Total 0 - total connections
| Aborts 0 - number of aborted connections
| Timeouts 0 - number of expired connections
| Errors 0 - number of connection errors
| Octets In 0 - number of octets received
| Octets Out 0 - number of octets sent
| Table Calls 0 - number of API calls to SessionDB (ILXTable)
| Datagroup Calls 0 - number of API calls to Datagroups (ILXDatagroup)
| Restarts 0 - number of plugin restarts
| Failures 0 - number of plugin failures
-----------------------------------------
| Extension Process: my_extension
-----------------------------------------
| Status running
| PID 20626
| TMM 0
| CPU Utilization (%) 0
| Debug Port 20001
| Memory (bytes)
| Total Virtual Size 735.6M
| Resident Set Size 15.2K
| RPC Info
| MPI channel mem://ilx:1:0 - communication channel between node.js process and TMM
| RPC Connections
| ...
| Process specific fields for ILX-RPC similar to those in the Extension output
| ...
| Streaming Info
| MPI channel mem://ilsx:2:0 - communication channel between node.js process and TMM
| Flow Connections
| ...
| Process specific fields for ILX-Streaming similar to those in the Extension output
| ...
-----------------------------------------
| Extension Process: my_extension
-----------------------------------------
| Status running
| PID 20627
| TMM 1
| CPU Utilization (%) 0
...
For ILX-Streaming, more information is available from the ILX profile statistics.
SEE ALSO
create, delete, edit, ilx workspace, list, ltm data-group, ltm virtual-server, modify, sys folder, sys log-config
publisher, tmsh
COPYRIGHT
No part of this program may be reproduced or transmitted in any form or by any means, electronic or mechanical, including
photocopying, recording, or information storage and retrieval systems, for any purpose other than the purchaser's personal
use, without the express written permission of F5 Networks, Inc.
F5 Networks and BIG-IP (c) Copyright 2008-2017. All rights reserved.
BIG-IP 2017-04-06 ilx plugin(1)