End-to-end Data API Examples ============================ Retrieving packet data from live interface. ------------------------------------------- SteelScript SDK ~~~~~~~~~~~~~~~ For more details please check out the `online tutorial `__. .. code:: python # Use-case: # Get the total bandwidth for last one minute broken down to ten seconds buckets. import pprint from steelscript.appresponse.core.appresponse import AppResponse from steelscript.common import UserAuth from steelscript.appresponse.core.reports import DataDef, Report from steelscript.appresponse.core.types import Key, Value, TrafficFilter from steelscript.appresponse.core.reports import SourceProxy # Open a connection to the appliance and authenticate ar = AppResponse('host', auth=UserAuth('username', 'password')) packets_source = ar.get_capture_job_by_name('default_job') source = SourceProxy(packets_source) columns = [Key('start_time'), Value('sum_tcp.total_bytes'), Value('avg_frame.total_bytes')] granularity = '10' time_range = 'last 1 minute' data_def = DataDef(source=source, columns=columns, granularity='10', time_range=time_range) data_def.add_filter(TrafficFilter('tcp.port==80')) report = Report(ar) report.add(data_def) report.run() pprint.pprint(report.get_data()) PHP ~~~ .. code:: php array("username" => USERNAME, "password" => PASSWORD), "generate_refresh_token" => false); $url = 'https://' . HOST . '/api/mgmt.aaa/1.0/token'; echo "Authenticating... "; $info = array(); $json = json_encode($request); $response = _do_POST($url, $json, $info); if ($info['http_code'] != 201) { echo "Unable to authenticate!\n"; echo $response . "\n"; exit(1); } echo "successful.\n"; return json_decode($response, true); } // Finds and returns a HTTP header function get_header($headers, $header) { foreach($headers as $h) { if (strpos($h, $header . ':') !== false) return trim(substr($h, 10)); } echo "Unable to find {$header} header!\n"; exit; } // CSV helper function echo_csv($rows) { foreach ($rows as $row) echo implode(',', $row) . "\n"; } // Prints the error message, deletes the live instance data object // and exists with error. function exit_with_error_and_cleanup($instance_url, $errmsg) { global $auth; echo $errmsg . "\n"; echo "DELETE {$instance_url} \n"; $info = array(); do_DELETE($instance_url, $info, $auth); exit(1); } // // End lib functions // // // Authenticate // $auth = authenticate(); $url = 'https://' . HOST . '/api/npm.packet_capture/2.0/vifgs'; echo "Sending VIFGs request... "; $info = array(); $response = do_GET($url, $info, $auth); if ($info['http_code'] != 200) { echo "failed.\n"; echo $response . "\n"; exit(1); } else { echo "successful.\n"; } $vifgs = json_decode($response, 1); $vifg_id = null; foreach ($vifgs['items'] as $vifg) { if ($vifg['config']['is_other_vifg']) { $vifg_id = $vifg['id']; } } if (is_null($vifg_id)) { echo "Undable to find Other vifg, full response:\n " . $response; exit(1); } // // Create live request object // $data_defs = array('live' => true, 'data_defs' => array(array('source' => array('name' => 'packets', 'path' => 'vifgs/' . $vifg_id), 'time' => array('retention_time' => '1 hour', 'granularity' => '1'), 'columns' => array('start_time', 'sum_tcp.total_bytes', 'avg_frame.total_bytes'), 'group_by' => array('start_time') ) ) ); $json = json_encode($data_defs); $url = 'https://' . HOST . '/api/npm.probe.reports/1.0/instances'; echo "Creating live request... "; $info = array(); $response = do_POST($url, $json, $info, $auth); if ($info['http_code'] != 201) { echo "failed.\n"; echo $response . "\n"; exit(1); } $location = get_header($info['headers'], 'Location'); echo "successful, instance URI: {$location}\n"; $instance_url = 'https://' . HOST . '' . $location; // // Wait for the data request to get into collecting state // $status_url = $instance_url . '/status'; echo "Waiting to get into collecting state\n"; while (true) { $info = array(); $response = do_GET($status_url, $info, $auth); if ($info['http_code'] != 200) { echo "Get status failed.\n"; exit_with_error_and_cleanup($instance_url, "Get status failed.\n" . $response); } $data_defs = json_decode($response, 1); $done = true; foreach ($data_defs as $d) { if ($d['state'] == 'error') { exit_with_error_and_cleanup($instance_url, "Data object in error state.\n" . $response); } echo " data object ID: {$d['id']} state: {$d['state']}\n"; if ($d['state'] != 'collecting') { $done = false; } } if ($done) { break; } usleep (100); } // // Print live data // echo "Getting data\n"; $last_end_time = 0; $counter = 0; while (true) { // Get info $response = do_GET($instance_url . '/data_defs/items/1', $info, $auth); if ($info['http_code'] != 200) { exit_with_error_and_cleanup($instance_url, "Get info failed.\n" . $response); } $d = json_decode($response, 1); if ($d['status']['state'] != 'collecting') { exit_with_error_and_cleanup($instance_url, "Data object no longer in collecting state.\n" . $response); } if (!isset($d['actual_time']['time_ranges'][0]['end'])) { // Can happen initially, keep waiting sleep(1); continue; } $end_time = $d['actual_time']['time_ranges'][0]['end']; if ($end_time > $last_end_time) { if ($last_end_time == 0) { // print the data headers only the first time echo implode(',', $d['columns']) . "\n"; } // New end time is availabe, get it $url = $instance_url . '/data_defs/items/1/data?granularity=1'; $url .= '&start_time=' . $last_end_time; $url .= '&end_time=' . $end_time; $response = do_GET($url, $info, $auth); if ($info['http_code'] != 200) { exit_with_error_and_cleanup($instance_url, "Get data failed.\n" . $response); } $data_resp = json_decode($response, 1); $data = array(); if (isset($data_resp['data'])) { // echo "Data for time range {$last_end_time} - {$end_time} \n"; echo_csv($data_resp['data']); } else { echo "No data for time range {$last_end_time} - {$end_time} \n"; } // set the last time to the new end time $last_end_time = $end_time; $counter++; sleep(1); } if ($counter > 10) { // That's enough, exiting // echo "DELETE {$instance_url}\n"; do_DELETE($instance_url, $info, $auth); exit(0); } } Output: :: Authenticating... successful. Sending VIFGs request... successful. Creating live request... successful, instance URI: /api/npm.probe.reports/1.0/instances/items/45 Waiting to get into collecting state data object ID: 1 state: collecting Getting data start_time,sum_tcp.total_bytes,avg_frame.total_bytes 1523025579,325243,267.025 1523025580,367649,208.427 1523025581,399139,177.478 1523025582,374621,205.57 1523025583,431028,196.044 1523025584,414299,193.134 1523025585,363306,209.815 1523025586,453000,261.833 1523025587,471342,224.392 1523025588,355008,185.305 Retrieving historical/performance data. --------------------------------------- SteelScript SDK ~~~~~~~~~~~~~~~ .. code:: python # Use-case: Get top host groups for the last 10 minutes by total bytes. import pprint from steelscript.appresponse.core.appresponse import AppResponse from steelscript.common import UserAuth from steelscript.appresponse.core.reports import DataDef, Report from steelscript.appresponse.core.types import Key, Value, TrafficFilter from steelscript.appresponse.core.reports import SourceProxy # Open a connection to the appliance and authenticate ar = AppResponse('host.com', auth=UserAuth('username', 'password')) source = SourceProxy(name='aggregates') columns = [Key('host_group.id'), Value('host_group.name'), Value('sum_traffic.total_bytes')] data_def = DataDef(source=source, columns=columns, time_range='last 10 minutes') report = Report(ar) report.add(data_def) report.run() pprint.pprint(report.get_data()) Curl (shell script) ~~~~~~~~~~~~~~~~~~~ Use-case: Get top host groups for the last 10 minutes by total bytes. To prepare, please create these two files. The auth\_request.json is used to obtain an access\_token. The data\_request.json is used to send a data request. For this example we are using the convenient 'sync' end-point, please refer to the Overview document for more details. Create the request json files: .. code:: shell % cat < auth_request.json { "user_credentials": { "username": "username", "password": "password" }, "generate_refresh_token": false } EOF % cat < data_request.json { "data_defs" : [ { "source" : { "name" : "aggregates" }, "group_by" : [ "host_group.id" ], "time" : { "duration" : "last 10 minutes" }, "top_by": [ {"id": "sum_traffic.total_bytes", "direction": "desc"} ], "columns" : [ "host_group.id", "host_group.name", "sum_traffic.total_bytes" ] } ] } EOF Authenticate: .. code:: shell % curl -H "Content-Type: application/json" \ -k -d@auth_request.json https:///api/mgmt.aaa/1.0/token The response will be JSON object with access token: .. code:: json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ ... 4rU", "token_type": "bearer", "expires_at": 1523894563 } Take the access token and make a data request (replace with the actual token in the Authorization request header): .. code:: json % curl -d@data_request.json \ -k \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ https:///api/npm.reports/1.0/instances/sync The response is JSON object that includes the data: :: ... "data":[ ["1","Default-10.x.x.x","430723319"], ["2","Default-Internet","325627617"], ["4","Default-192.168.x.x","283020518"], ["0","Other Group","177495063"], ["3","Default-172.x.x.x","12752"] ], ... PHP ~~~ .. code:: php array("username" => USERNAME, "password" => PASSWORD), "generate_refresh_token" => false); $url = 'https://' . HOST . '/api/mgmt.aaa/1.0/token'; echo "Authenticating... "; $info = array(); $json = json_encode($request); $response = _do_POST($url, $json, $info); if ($info['http_code'] != 201) { echo "Unable to authenticate!\n"; echo $response . "\n"; exit(1); } echo "successful.\n"; return json_decode($response, true); } // Finds and returns a HTTP header function get_header($headers, $header) { foreach($headers as $h) { if (strpos($h, $header . ':') !== false) return trim(substr($h, 10)); } echo "Unable to find {$header} header!\n"; exit; } // CSV helper function echo_csv($headers, $rows) { echo implode(',', $headers) . "\n"; foreach ($rows as $row) echo implode(',', $row) . "\n"; } // // End lib functions // // // Authenticate // $auth = authenticate(); // // Send data request // $data_defs = array('data_defs' => array(array('source' => array('name' => 'aggregates'), 'time' => array('duration' => 'last 10 minutes'), 'columns' => array('host_group.id', 'host_group.name', 'sum_traffic.total_bytes'), 'group_by' => array('host_group.id') ) ) ); $json = json_encode($data_defs); $url = 'https://' . HOST . '/api/npm.reports/1.0/instances'; echo "Sending data request... "; $info = array(); $response = do_POST($url, $json, $info, $auth); if ($info['http_code'] != 201) { echo "failed.\n"; echo $response . "\n"; exit(1); } $location = get_header($info['headers'], 'Location'); echo "successful, instance URI: {$location}\n"; // // Wait for the data request to complete // $status_url = 'https://' . HOST . '' . $location . '/status'; echo "Waiting to complete\n"; while (true) { $info = array(); $response = do_GET($status_url, $info, $auth); if ($info['http_code'] != 200) { echo "Get status failed.\n"; echo $response . "\n"; exit(1); } $data_defs = json_decode($response, 1); $done = true; foreach ($data_defs as $d) { if ($d['state'] == 'error') { echo "Error: \n"; echo $d['messages']; exit(1); } echo " data object ID: {$d['id']} state: {$d['state']}\n"; if ($d['state'] != 'completed') { $done = false; } } if ($done) { break; } usleep (100); } // // Get and print the data // echo "Getting data..."; $data_url = 'https://' . HOST . '' . $location . '/data'; $output = do_GET($data_url, $info, $auth); $data = json_decode($output, 1); if ($info['http_code'] != 200) { echo "failed.\n"; echo $output . "\n"; exit(1); } else { echo "successful.\n"; } // Print the data foreach ($data['data_defs'] as $d) { echo "Data object ID: " . $d['id'] . "\n"; $data = array(); if (isset($d['data'])) { $data = $d['data']; } echo_csv($d['columns'], $data); } ?> Output: :: Authenticating... successful. Sending data request... successful, instance URI: /api/npm.reports/1.0/instances/items/334 Waiting to complete data object ID: 1 state: executing data object ID: 1 state: executing data object ID: 1 state: completed Getting data...successful. Data object ID: 1 host_group.id,host_group.name,sum_traffic.total_bytes 0,Other Group,16174105659 1,Default-10.x.x.x,31395223107 2,Default-Internet,21423988720 3,Default-172.x.x.x,1049557 4,Default-192.168.x.x,25632954659 Perl ~~~~ .. code:: perl #!/usr/bin/perl # Tested on Perl version: 5.10.1 # Use-case: Get top host groups for the last 10 minutes by total bytes. use strict; use warnings; use LWP::UserAgent; use HTTP::Request; use List::MoreUtils qw(firstidx); use JSON qw( encode_json decode_json ); use constant HOST => 'host.com'; use constant USERNAME => 'username'; use constant PASSWORD => 'password'; # # Lib functions # our $ua = LWP::UserAgent->new; $ua->agent("ExampleScript"); our $API_BASE = "https://" . HOST; sub _request($) { my $req = shift; $req->header('Accept' => 'application/json'); my $res = $ua->request($req); return { code => $res->code, status => $res->status_line, headers => $res->headers(), data => decode_json($res->content) }; } # HTTP GET, re-authenticates when acess token is expired sub GET($$) { my $req = HTTP::Request->new(GET => $API_BASE . shift); my $auth = shift; $req->authorization('Bearer ' . $auth->{access_token}); my $response = _request($req); if ($response->{code} == 401) { $auth = authenticate(); $req->authorization('Bearer ' . $auth->{access_token}); return _request($req); } return $response; } # HTTP POST, re-authenticates when acess token is expired sub POST($$$) { my $req = HTTP::Request->new(POST => $API_BASE . shift); my $auth = shift; $req->authorization('Bearer ' . $auth->{access_token}); $req->content_type('application/json'); $req->content(encode_json(shift)); my $response = _request($req); if ($response->{code} == 401) { $auth = authenticate(); $req->authorization('Bearer ' . $auth->{access_token}); return _request($req); } return $response; } # Using a username and password, get an access token # The function is not using refresh tokens, if you are building # long lasting application, please consider using generate_refresh_token: true # and use the refresh token to re-authenticate. For more information please # refer to the Authentication overview document. sub authenticate() { print "Authenticating... "; my $struct = { user_credentials => { username => USERNAME, password => PASSWORD }, generate_refresh_token => JSON::false }; my $req = HTTP::Request->new(POST => $API_BASE . '/api/mgmt.aaa/1.0/token'); $req->content_type('application/json'); $req->content(encode_json($struct)); my $response = _request($req); if ($response->{code} != 201) { print "Unable to authenticate!\n"; print encode_json($response->{data}); exit(); } print "successful.\n"; return $response->{data} } # # Authenticate # my $auth = authenticate(); # # Send data request # my $data_defs = { data_defs => [ {source => {name => 'aggregates'}, time => {duration => 'last 10 minutes'}, columns => ['host_group.id', 'host_group.name', 'sum_traffic.total_bytes'], group_by => ['host_group.id'] } ] }; my $url = '/api/npm.reports/1.0/instances'; print "Sending data request... "; my $response = POST($url, $auth, $data_defs); if ($response->{code} != 201) { print "failed.\n"; print encode_json($response->{data}) . "\n"; exit(1); } my $location = $response->{headers}->header('Location'); print "successful, instance URI: $location\n"; # # Wait for the data request to complete # my $status_url = $location . '/status'; print "Waiting to complete\n"; while (1) { my $response = GET($status_url, $auth); if ($response->{code} != 200) { print "Get status failed.\n"; print encode_json($response->{data}) . "\n"; exit(1); } my $done = 1; foreach my $d (@{$response->{data}}) { if ($d->{state} eq 'error') { print "Error: \n"; print encode_json($d->{messages}); exit(1); } print " data object ID: $d->{id} state: $d->{state}\n"; if ($d->{state} ne 'completed') { $done = 0; } } last if $done eq 1; sleep(1); } # # Get and print the data # print "Getting data..."; my $data_url = $location . '/data'; $response = GET($data_url, $auth); if ($response->{code} != 200) { print "failed.\n"; print encode_json($response->{data}) . "\n"; exit(1); } else { print "successful.\n"; } # Print the data foreach my $d (@{$response->{data}->{data_defs}}) { print "Data object ID: " . $d->{id} . "\n"; my @columns = @{$d->{columns}}; print join ",", @columns; print "\n"; foreach my $row (@{$d->{data}}) { print join ",", @$row; print "\n"; } } Output: :: Authenticating... successful. Sending data request... successful, instance URI: /api/npm.reports/1.0/instances/items/702 Waiting to complete data object ID: 1 state: completed Getting data...successful. Data object ID: 1 host_group.id,host_group.name,sum_traffic.total_bytes 0,Other Group,139925908 1,Default-10.x.x.x,483894223 2,Default-Internet,406507955 3,Default-172.x.x.x,12456 4,Default-192.168.x.x,210087340