The following Virtual Service functions are available in DataScripts:
Function |
Description |
---|---|
Creates and manipulates a counter-type metric. For more information, see the NSX Advanced Load Balancer Monitoring Components topic in theVMware NSX Advanced Load Balancer Monitoring and Operability Guide. |
|
Creates and manipulates a gauge-type metric. |
|
Return the user-defined metric value if one with the given name and given type exists. |
|
Returns the value of the metric, be it of type absolute, counter, or gauge. |
|
Returns the client IP address |
|
Returns the client source port |
|
Close the current TCP/UDP connection |
|
Returns IP address of the VS |
|
Write a custom log to . |
|
Returns the name of the virtual service. |
|
Returns the VS port of the connection. |
|
Creates peristence entry using the key used after load balancing traffic. |
|
avi.vs.rate_limit( type, string_to_limit, [defer_action=False] ) |
Rate limits entities of various kinds. |
Set a global variable usable across events. |
|
avi.vs.table_insert( [table_name,] key, value [, lifetime] ) |
Store custom data in a time-based table. |
Lookup data in a table. |
|
avi.vs.table_refresh( [table_name,] key [, lifetime_exten] ) |
Update the expire time for a table entry. |
Rate limits entities of various kinds. |
|
Remove data from a table. |
|
Returns the total number of open connections per Service Engine attached to the current virtual service. |
|
Returns the total number of Service Engines attached to the current virtual service. |
avi.vs.analytics.counter
Function |
|
Description |
Increments or clears the named counter metric. For more information, see NSX Advanced Load Balancer Monitoring Components topic in theVMware NSX Advanced Load Balancer Monitoring and Operability Guide |
.E.vents |
|
Parameter |
Note:
|
Returns |
No value returned |
Related |
|
Examples |
|
avi.vs.analytics.gauge
Function |
|
Description |
Increments, decrements, sets or clears the named gauge metric. For more information, see NSX Advanced Load Balancer Monitoring Components topic in theVMware NSX Advanced Load Balancer Monitoring and Operability Guide. |
Events |
|
Parameter |
Note:
|
Returns |
No value returned |
Related |
|
Examples |
|
avi.vs.analytics.get_metric
Function |
|
Description |
Returns the value of the metric, be it of type counter or gauge. Before doing so, the function first checks if metric_name has been defined. If it has, it then compares the value of metric_type to the type previously stored. If metric_name has never been defined, or the type is not correct, the function will report an error on the log and the request/response causing this function call will be cancelled. For more information, see the User-defined Metrics section in the NSX Advanced Load Balancer Monitoring Components topic in the VMware NSX Advanced Load Balancer Monitoring and Operability Guide. |
Events |
|
Parameter |
|
Returns |
The value of the metric |
Related |
|
Example |
Set goo-current-val to the current value of a counter-type metric named goo, if it exists. goo-current-val = avi.vs.analytics.get_metric ("goo", avi.vs.analytics.METRICTYPE_COUNTER) |
avi.vs.analytics.get_counter
Function |
|
Description |
Returns the metric's value, be it of type absolute, counter, or gauge. Before doing so, the function first checks if |
Events |
|
Parameter |
|
Returns |
The value of the metric |
Related |
|
Example |
TBD |
avi.vs.client_ip
Function |
|
Description |
Returns the client's IPv4 or IPv6 address. |
Events |
All |
Parameter |
None |
Returns |
String containing the client’s source IP address. |
Example |
Insert the source IP address of a client into an HTTP header. avi.http.add_header("XFF", avi.vs.client_ip()) |
avi.vs.client_port
Function |
|
Description |
Returns the client's source port. |
Events |
|
Parameter |
None |
Returns |
String containing client’s source port. |
Example |
Simple way to provide A/B testing by distributing 1/10th of connections to pool1. if string.endswith(avi.vs.client_port(), "0") then avi.pool.select("Pool1") else avi.pool.select("Pool2") end |
avi.vs.close.connection
Function |
|
Description |
Closes the current TCP/UDP connection. The reset flag is of no consequence in case of a UDP connection. |
Events |
|
Parameter |
The |
Returns |
No return value |
Example |
if avi.vs.client_ip() == "10.1.1.1" then avi.vs.close_conn() end avi.vs.close_conn(1) |
avi.vs.ip
Function |
|
Description |
Returns the virtual service IPv6 address which accepted the request or connection. |
Events |
|
Parameter |
The |
Returns |
IPv6 address in hexadecimal string format (separated by colons), for instance, |
Example |
Insert a header informing the server which VS traffic originated from. avi.http.add_header("VS_IP", avi.vs.ip()) |
avi.vs.log
Function |
|
Description |
Generate a log associated with the connection or request and viewed within the |
Events |
|
Parameter |
|
Returns |
None |
Example |
From DataScript "Log1" HTTP_REQ event: avi.vs.log("Hello World!") From DataScript "Log2" HTTP_RESP event: num = 2 avi.vs.log("Hello " .. num .. " You!") Output from the client log: DataScript Log: [string "Log1"]:1: Hello World! DataScript Log: [string "Log2"]:1: Hello 2 You!
Note:
The logs are prefixed by meta information, which is generally the function name and line number calling Significant Logging Example: From DataScript "Log1" HTTP_REQ event: avi.vs.log("Hello World!", avi.SIG_ENABLE) Output from the client log: DataScript Log: [string "Log1"]:1: Hello World! Significance: Datascript Significant Log. |
avi.vs.name
Function |
|
Description |
Returns the name of the virtual service which accepted the request or connection. |
Events |
|
Parameter |
None |
Returns |
String containing the virtual service name. |
Example |
Insert a header in traffic sent to the server: X-Source: www.avi.com-10.1.1.1 avi.http.add_header("X-Source", avi.vs.name() .. "-" .. avi.vs.ip()) |
avi.vs.port()
Function |
|
Description |
Returns the virtual service port that received the request or connection. |
Events |
|
Parameter |
None |
Returns |
String containing the virtual service port number. |
Example |
Close the connection if the HTTP request did not arrive on port 443. if avi.vs.port() ~= "443" then avi.http.close_conn() end |
avi.vs.persist
Function |
|
Description |
Load balances the request to the optional provided pool or the pool attached to the virtual service. This function also creates a key-value persistence entry for the same. The key being the passed parameter, and the value being the load balanced IP, port (Eg: 10.10.10.10-80). Optional lifetime ensures the persistence table entry is created with the passed lifetime. The default is 300s. Under the hood, this API performs traditional load balancing and automatically creates a persistence table entry with the value being the load-balanced backend server. Repeatedly calling out this API will refresh the timeout. |
Events |
|
Parameter |
Key , [lifetime], [pool] |
Returns |
No return value |
Example |
if username == “my_user” then avi.vs.persist(username, 3600, “POOL_80”) |
This API yields from a DataScript and no further statements after this API will run. This is a terminal API.
avi.vs.rate.limit
Function |
|
Description |
Rate limits entities of various kinds. |
Events |
|
Parameter |
|
Returns |
The function returns two optional, purely informational variables:
The possible options are:
|
DataScript must be configured to reference a rate limit profile, which is nested within a HTTP application profile, which is attached to one or more virtual services. This rate limit profile association is made through the CLI or API. The following CLI syntax shows how to modify the profile:
configure applicationprofile <application_profile_name> dos_rl_profile rl_profile custom_requests_rate_limit count <max_number_of_requests_allowed> period <time_period_during_which_those_requests_should_be_allowed> -- Rate limiter allows requests as long as count is not exceeded within period seconds action type <action_type> -- Default for action_type is avi.RL_ACTION_CLOSE_CONN save -- Repeat until you exit the application profile
To configure the rate limit profile on the UI:
On the Controller, navigate to Templates.
Under the Application tab, select and edit your application profile (or create a new one).
Select the DDoS tab.
Under Add Rate Limit, select Rate Limit all HTTP requests that map to any custom string to all URLs of the virtual service.
Enter the values for Threshold and Time Period. For this particular use-case select Action as Send HTTP Local Response and Status Code as 429. You do not need to upload a file.
Click Save.
Basic rate limiting
Example 1
Rate limit clients based upon a unique ID, in this case an HTTP header value
The number of requests per poeriod of time are defined within the rate limit profile
avi.vs.rate_limit(avi.RL_CUSTOM_STRING, avi.http.get_header("userID"))
Rate limiting with a penalty timer
Extend the logic of rate limiting by adding a penalty box
Normally rate limit only allows X number of connections within
Y period of time. With the penalty box, when a user exceeds the limit,
They may not send any requests until the penalty timer expires.
userID = avi.http.get_header("userID") penalty_time = 900 -- Check if the userID has been added to the table of blocked users -- The table is used to create a "penalty box" of 900 seconds -- If user is not in the list then given_action variable is nil given_action, remaining_time = avi.vs.table_lookup(userID, 0) if given_action then avi.http.close_conn() else -- if userID is not in the penalty box table count_exceeded, given_action = avi.vs.rate_limit(avi.RL_CUSTOM_STRING, userID, true) if count_exceeded then -- user just crossed the threshold and is now added to the penalty box table avi.vs.table_insert(userID, given_action, penalty_time) -- Since the optional defer_action flag from avi.vs.rate_limit() is set to true -- The rate limit profile is not enforcing the limit, so it is enforced below avi.http.close_conn() end end
avi.vs.rate.limit.exceed
Starting with Avi Load Balancer release 18.2.9, the existing rate limit DataScript API – avi.vs.rate_limit
. is deprecated. The new DataScript API for the rate limit is avi.vs.ratelimit.exceed
.
Deprecated DataScript API – avi.vs.rate_limit( type, string_to_limit, [defer_action=False] )
New DataScript API –avi.vs.ratelimit.exceed(rl_name, request_key, [consume])
The following are the parameters used in new DataScript rate limiter:
Function |
|
Description |
Rate limits entities of various kinds. |
Events |
|
Parameter |
|
Returns |
The function returns two variables:
The action can be configured as per the requirement. In the following configuration section, the action is chosen to log the event in the virtual service logs. |
This API is not supported in the events SSL_PRECONNECT, SSL_CLIENTHELLO, and SSL_HANDSHAKE_DONE.
Additional Configuration
DataScript must be configured to reference a rate limit profile, which is nested within a HTTP application profile, which is attached to one or more virtual services. This rate limit profile association is made through the CLI or API. The following CLI syntax shows how to modify the profile:
Configuring DataScript Rate Limiter
Login to the CLI and use configure vsdatascriptset <policy name> command to configure rate limiters. Provide the policy name and assign the desired value of the rate limiters (count, period, and burst size) as shown below:
[admin]: > configure vsdatascriptset rate_limiter_test [admin]: vsdatascriptset> rate_limiters [admin]: vsdatascriptset:rate_limiters> count 1 [admin]: vsdatascriptset:rate_limiters> period 15 [admin]: vsdatascriptset:rate_limiters> burst_sz 0 [admin]: vsdatascriptset:rate_limiters> name rl1 [admin]: vsdatascriptset:rate_limiters> save [admin]: vsdatascriptset> save
Use the avi.vs.ratelimit.exceed function in a DataScript with the desired action. For example:
result = avi.vs.ratelimit.exceed("rl1", "key1") if result == true then avi.vs.log("rl exceeds") else avi.vs.log("rl does not exceed") end
avi.vs.reqvar
Function |
|
Description |
Sets (write) or gets (read) a variable. These variables have scope across the HTTP_REQ and HTTP_RESP events. Their lifetime is limited to that of the HTTP request/response transaction, so it does not need to be manually unset. Any Lua value can be stored within this variable. For variable data that is only required during the current event, map the variable to the data. var = 1 if var == 1 then ... For variable data that needs to be saved across connections or mirrored to other Service Engines for the virtual service use avi.vs.table_insert() |
Events |
|
Parameter |
None |
Returns |
Boolean true upon refresh success and false upon refresh failure. |
HTTP Request Example |
avi.vs.reqvar.foo = 10
if avi.vs.reqvar.foo == 10 then avi.vs.log("Foo=" .. avi.vs.reqvar.foo) end |
avi.vs.table_insert
Function |
|
Description |
The table API is used to store and retrieve custom data. The avi.vs.table_lookup API looks up a key and return the corresponding value. This key-value store is unique per Virtual Service and is mirrored across all Service Engines hosting the VS. |
Events |
|
Parameter |
If the optional The key is used to look up the value. The optional |
Returns |
Returns the value field of the key. If no value exists or the key does not exist, returns nil.The remaining lifetime, a non-negative integer representing the remaining lifetime of the entry in seconds. |
HTTP Request Example |
This use case can also be performed through the native App-Cookie persistence mode: if avi.http.get_cookie("OAM_JSESSIONID") then if avi.vs.table_lookup(avi.http.get_cookie("OAM_JSESSIONID")) then avi.pool.select(avi.vs.table_lookup(avi.http.get_cookie("JSESSIONID"))) end end |
HTTP Response Example |
if avi.http.get_cookie("JSESSIONID") ~= "" then avi.vs.table_insert(avi.http.get_cookie("JSESSIONID"), avi.pool.server_ip(), 3600) end |
avi.vs.table_lookup
Function |
|
Description |
The table API is used to store and retrieve custom data. The avi.vs.table_lookup API looks up a key and return the corresponding value. This key-value store is unique per Virtual Service and is mirrored across all Service Engines hosting the VS. |
Events |
|
Parameter |
If the optional table_name is not specified, the key is looked up in the default table for the VS. When it is specified, a custom table will be searched. The key is used to look up the value. The optional lifetime_exten flag must be a positive integer, indicating the length of time, in seconds, that should be added to the current lifetime parameter for the key. When not specified, the default value of 300 seconds is used. This means that by default, looking up the value of a key will extend the lifetime of a key by an additional 300 seconds. To lookup the key without impacting the expiration, set the lifetime_exten flag to 0. |
Returns |
Returns the value field of the key. If no value exists or the key does not exist, returns nil.The remaining lifetime, a non-negative integer representing the remaining lifetime of the entry in seconds. |
HTTP Request Example |
This use case can also be performed via the native App-Cookie persistence mode: if avi.http.get_cookie("OAM_JSESSIONID") then if avi.vs.table_lookup(avi.http.get_cookie("OAM_JSESSIONID")) then avi.pool.select(avi.vs.table_lookup(avi.http.get_cookie("JSESSIONID"))) end end |
HTTP Response Example |
if avi.http.get_cookie("JSESSIONID") ~= "" then avi.vs.table_insert(avi.http.get_cookie("JSESSIONID"), avi.pool.server_ip(), 3600) end |
avi.vs.table_refresh
Function |
|
Description |
Refreshes the lifetime of the entry for the key in the key/value store. |
Events |
|
Parameter |
Looks up the key in the default VS table, unless another table name is specified through the optional
|
Returns |
Boolean |
Note |
The key/value entry will be removed from all Service Engines hosting the VS. |
Example |
TBD |
avi.vs.table_remove
Function |
|
Description |
The table API is used to store and retrieve custom data. The |
Events |
|
Parameter |
If the optional The |
Returns |
None |
Note |
The key/value entry will be removed from all Service Engines hosting the VS. |
Example |
TBD |
avi.vs.get_open_conns
Function |
avi.vs.get_open_conns() |
Description |
Returns the total number of open connections for the virtual service on the SE on which the request was received |
Events |
All events |
Parameter |
None |
Returns |
The total number of open connections |
Example |
The following data script example will provide the SE count and open connections: local se_count = avi.vs.se_count() local open_conn = avi.vs.get_open_conns() avi.vs.log("Open conns: " .. open_conn .. " for Total SE: " .. se_count) |
avi.vs.se_count
Function |
avi.vs.get_se_count() |
Description |
Returns the total number of service engines attached to the current virtual service |
Events |
All events |
Parameter |
None |
Returns |
The total number of SEs for the respective virtual service |
Example |
The following data script example will print 1 , if there is only one SE present: -- scale-out SE open connection limit MAX_OPEN_CON=50 local se_count = avi.vs.se_count() local open_conn = avi.vs.get_open_conns() per_se_max = MAX_OPEN_CON/se_count --Dividing the MAX count per SE, assuming equal distribution. if (open_conn > per_se_max) then avi.vs.log("Current open conns: " .. open_conn .. "> MAX_OPEN_CON=" .. MAX_OPEN_CON .. " for Total SE: " .. se_count) avi.http.response(404, {content_type="text/html"}, "<html> MAX_OPEN_CON=" .. MAX_OPEN_CON .. " exceeded, please try later! </html>\n") else avi.vs.log("Open conns: " .. open_conn .. " for Total SE: " .. se_count) end |