line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Geneos::API - Handy Perl interface to ITRS Geneos XML-RPC Instrumentation API |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 VERSION |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Version 0.12 |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 SYNOPSIS |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use Geneos::API; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# open API to NetProbe running on host example.com and port 7036 |
14
|
|
|
|
|
|
|
my $api = Geneos::API->new("http://example.com:7036/xmlrpc"); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# get the sampler "Residents" in the managed entity "Zoo" |
17
|
|
|
|
|
|
|
my $sampler = $api->get_sampler("Zoo", "Residents"); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# create view "Monkeys" in the group "Animals" |
20
|
|
|
|
|
|
|
my $view = $sampler->create_view("Monkeys", "Animals"); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# prepare some data |
23
|
|
|
|
|
|
|
my $monkeys = [ |
24
|
|
|
|
|
|
|
["Name", "Type" ], |
25
|
|
|
|
|
|
|
["Funky", "Red-tailed monkey"], |
26
|
|
|
|
|
|
|
["Cheeky", "Tibetan macaque" ] |
27
|
|
|
|
|
|
|
]; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# populate the view |
30
|
|
|
|
|
|
|
$view->update_entire_table($monkeys); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# get stream "News" on sampler "Channels" in the managed entitity "Zoo" |
33
|
|
|
|
|
|
|
my $stream = $api->get_sampler("Zoo","Channels")->get_stream("News"); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# add a message to the stream |
36
|
|
|
|
|
|
|
$stream->add_message("Funky beats Cheeky in a chess boxing match!"); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 DESCRIPTION |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
C is a Perl module that implements ITRS XML-RPC Instrumentation API. |
41
|
|
|
|
|
|
|
It can be used to create clients for both Geneos API and API Steams plug-ins. |
42
|
|
|
|
|
|
|
The plug-ins act as an XML-RPC server. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
Geneos C, C and C are represented by instances of |
45
|
|
|
|
|
|
|
C, C and C classes. |
46
|
|
|
|
|
|
|
This provides easy to use building blocks for developing monitoring applications. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
This module comes with its own XML-RPC module based on XML::LibXML as ITRS implementation |
49
|
|
|
|
|
|
|
of XML-RPC does not conform to the XML-RPC standard and therefore most of the available XML-RPC |
50
|
|
|
|
|
|
|
modules cannot be used. The client uses C and gives access to all |
51
|
|
|
|
|
|
|
the available constructor options provided by C. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
The module also provides customizable error and debug hanlders. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 METHODS |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 Constructor |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head3 $api->new($url, $options) |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
C<$url> is required and must be in the format: |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
C |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
For example: |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
my $api = Geneos::API->new("http://localhost:7036/xmlrpc"); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
XML-RPC Client is initialized upon call to the API constructor |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Options |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
The constructor accepts a reference to the options hash as optional second parameter: |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
my $api = Geneos::API->new("http://localhost:7036/xmlrpc", { |
76
|
|
|
|
|
|
|
api => {raise_error => 1,}, |
77
|
|
|
|
|
|
|
ua => {keep_alive=>10, timeout=>5,}, |
78
|
|
|
|
|
|
|
}); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head4 api - XML-RPC options |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=over |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=item * C<< raise_error >> |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Force errors to raise exceptions via C |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=item * C<< print_error >> |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Force errors to raise warnings via C |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=item * C<< error_handler >> |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Custom error handler. See C section for more details. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=item * C<< debug_handler >> |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Debug handler. See C section for more details. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=back |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
The order of presedence for error handling is as follows: |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=over |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item * C<< error_handler >> |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=item * C<< raise_error >> |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item * C<< print_error >> |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=back |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
If neither is set, the errors won't be reported and C<$api-Eerror> |
115
|
|
|
|
|
|
|
method will need to be called to check if the latest call generated an error or not. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head4 ua - UserAgent options |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=over |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=item * C<< any options supported by L >> |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=back |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=head2 Error handling |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head3 $api->raise_error() |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Get the raise_error attribute value |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Returns true is the raise_error attribute is set or false otherwise |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
If the raise_error attribute is set, errors generated by API calls will be passed to C |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head3 $api->remove_raise_error() |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Remove the raise_error attribute |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head3 $api->print_error() |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Get the print_error attribute value |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Returns true is the print_error attribute is set or false othersise |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
If the print_error attribute is set, errors generated by API calls will be passed to C |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
print_error attribute is ignored if raise_error is set. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=head3 $api->remove_print_error() |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
Remove the print_error attribute |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head3 $api->status_line |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Returns the string " ". Returns undef if there is no error. |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head3 $api->error |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Get the error produced by the last api call. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
Returns reference to the error hash or undef if the last call produced no error. |
162
|
|
|
|
|
|
|
The hash contains three elements: |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=over |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=item * code |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
HTTP or XML-RPC error code. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=item * message |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
Error string. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item * class |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
The component that produced the error: C or C. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=back |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head3 Error handler |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Allows you to provide your own behaviour in case of errors. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
The handler must be passed as a reference to subroutine and it could be done as a constructor option: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
my $api = Geneos::API->new("http://localhost:7036/xmlrpc", { |
187
|
|
|
|
|
|
|
api => { error_handler => \&my_error_handler, }, |
188
|
|
|
|
|
|
|
}); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
or via a separate method: |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
$api->error_handler(\&my_error_handler) |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
The subroutine is called with two parameters: reference to the error hash and the api object itself. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
For example, to die with a full stack trace for any error: |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
use Carp; |
199
|
|
|
|
|
|
|
$api->error_handler( sub { confess("$_[0]->{code} $_[0]->{message}") } ); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Please note that the custom error handler overrides the raise_error and print_error settings. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
The error handler can be removed by calling: |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
$api->remove_error_handler() |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=head2 API and API Streams Function Calls |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
There are two classes that represent Samplers and Views. Samplers are represented by |
210
|
|
|
|
|
|
|
the internal C class. First, a sampler object must be created: |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
$sampler = $api->get_sampler($managed_entity, $sampler_name) |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
This will create a Sampler object representing a sampler with the name C<$sampler_name> in the managed |
215
|
|
|
|
|
|
|
entity C<$managed_entity>. You can call any method from the section "Sampler methods" on this object. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Views are represented by the internal C class. |
218
|
|
|
|
|
|
|
In order to create an instance of this class, you can use: |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# if the view already exists |
221
|
|
|
|
|
|
|
$view = $sampler->get_view($view_name, $group_heading) |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# if the view does not exist yet and you want to create it |
224
|
|
|
|
|
|
|
$view = $sampler->create_view($view_name, $group_heading) |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
Once the view object is created, you can call any of the "View methods" on it. |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Streams are represented by the internal C class. In order to create |
229
|
|
|
|
|
|
|
an instance of this class, you can use: |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
$stream = $sampler->get_stream($stream_name) |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Once the object is created, you can call any of the "Stream methods" on it. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head2 Sampler methods |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head3 $api->get_sampler($managed_entity, $sampler) |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
This method doesn't check whether the sampler exists. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Returns sampler object. |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head3 $sampler->get_stream($stream_name) |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
The stream must already exist. This method will NOT check that the stream extists or not. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
Returns an object representing the stream C<$stream_name>. |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head3 $sampler->create_view($view_name, $group_heading) |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Creates a new, empty view C<$view_name> in the specified sampler under the specified C<$group_heading>. |
252
|
|
|
|
|
|
|
This method will create a view and returns the object representing it. An error will be produced |
253
|
|
|
|
|
|
|
if the view already exists. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Returns OK on successful completion. |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=head3 $sampler->get_view($view_name, $group_heading) |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
The view must already exist. This method will NOT check that the view extists or not. |
260
|
|
|
|
|
|
|
Use C<$sampler-Eview_exists> method for that. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
Returns an object representing the view C<$view_name>. |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head3 $sampler->view_exists($view_name, $group_heading) |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Checks whether a particular view exists in this sampler. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Returns true if the view exists, false otherwise. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=head3 $sampler->remove_view($view_name) |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Removes a view that has been created with create_view. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
Returns OK on successful completion. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head3 $sampler->get_parameter($parameter_name) |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Retrieves the value of a sampler parameter that has been defined in the gateway configuration. |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
Returns the parameter text written in the gateway configuration. |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head3 $sampler->sign_on($period) |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
$period - The maximum time between updates before samplingStatus becomes FAILED |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Commits the API client to provide at least one heartbeat or update to the view within |
287
|
|
|
|
|
|
|
the time period specified. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
Returns OK on successful completion. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=head3 $sampler->sign_off() |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Cancels the commitment to provide updates to a view. |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Returns OK on successful completion. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=head3 $sampler->heartbeat() |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Prevents the sampling status from becoming failed when no updates are needed to a view and |
300
|
|
|
|
|
|
|
the client is signed on. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Returns on successful completion. |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=head2 View methods |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head3 $view->add_table_row($row_name,$data) |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Adds a new, table row to the specified view and populates it with data. Returns OK |
309
|
|
|
|
|
|
|
on successful completion. |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head3 $view->remove_table_row($row_name) |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Removes an existing row from the specified view. |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Returns OK on successful completion. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head3 $view->add_headline($headline_name) |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Adds a headline variable to the view. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
Returns OK on successful completion. |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head3 $view->remove_headline($headline_name) |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
Removes a headline variable from the view. |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Returns OK on successful completion. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head3 $view->update_variable($variable_name, $new_value) |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
Can be used to update either a headline variable or a table cell. |
332
|
|
|
|
|
|
|
If the variable name contains a period (.) then a cell is assumed, |
333
|
|
|
|
|
|
|
otherwise a headline variable is assumed. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Returns OK on successful completion. |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head3 $view->update_headline($headline_name, $new_value) |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Updates a headline variable. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
Returns OK on successful completion. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=head3 $view->update_table_cell($cell_name, $new_value)) |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Updates a single cell in a table. The standard row.column format should be used |
346
|
|
|
|
|
|
|
to reference a cell. |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Returns OK on successful completion. |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=head3 $view->update_table_row($row_name, $new_value)) |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Updates an existing row from the specified view with the new values provided. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
Returns OK on successful completion. |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=head3 $view->add_table_column($column_name) |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
Adds another column to the table. |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
Returns OK on successful completion. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head3 $view->update_entire_table($new_table) |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
Updates the entire table for a given view. This is useful if the entire table |
365
|
|
|
|
|
|
|
will change at once or the table is being created for the first time. |
366
|
|
|
|
|
|
|
The array passed should be two dimensional. The first row should be the column |
367
|
|
|
|
|
|
|
headings and the first column of each subsequent row should be the name of the row. |
368
|
|
|
|
|
|
|
The array should be at least 2 columns by 2 rows. Once table columns have been |
369
|
|
|
|
|
|
|
defined, they cannot be changed by this method. |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Returns OK on successful completion. |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=head3 $view->column_exists($column_name) |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Check if the headline variable exists. |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Returns true if the column exists, false otherwise. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head3 $view->row_exists($row_name) |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Check if the headline variable exists. |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
Returns true if the row exists, false otherwise. |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=head3 $view->headline_exists($headline_name) |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
Check if the headline variable exists. |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
Returns true if the headline variable exists, false otherwise. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=head3 $view->get_column_count() |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
Return the column count of the view. |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Returns the number of columns in the view. This includes the rowName column. |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=head3 $view->get_row_count() |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
Return the headline count of the view. |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
Returns the number of headlines in the view. This includes the samplingStatus headline. |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=head3 $view->get_headline_count() |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
Returns the number of headlines in the view. This includes the samplingStatus headline. |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=head3 $view->get_column_names() |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
Returns the names of existing columns in the view. This includes the rowNames column name. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=head3 $view->get_row_names() |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
Returns the names of existing rows in the view |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=head3 $view->get_headline_names() |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
Returns the names of existing headlines in the view. |
418
|
|
|
|
|
|
|
This includes the samplingStatus headline. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=head3 $view->get_row_names_older_than($epoch) |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
C<$epoch> - The timestamp against which to compare row update time. |
423
|
|
|
|
|
|
|
The timestamp should be provided as Unix timestamp, i.e. number of seconds |
424
|
|
|
|
|
|
|
elapsed since UNIX epoch. |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
Returns the names of rows whose update time is older than the time provided. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=head2 Stream methods |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=head3 $stream->add_message($message) |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
Adds a new message to the end of the stream. |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
Returns OK on successful completion. |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=head2 NetProbe Function Calls |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=head3 $api->managed_entity_exists($managed_entity) |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
Checks whether a particular Managed Entity exists on this NetProbe |
441
|
|
|
|
|
|
|
containing any API or API-Streams samplers. |
442
|
|
|
|
|
|
|
Returns true if the Managed Entity exists, false otherwise |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
=head3 $api->sampler_exists($managed_entity, $sampler) |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
Checks whether a particular API or API-Streams sampler exists on this NetProbe |
447
|
|
|
|
|
|
|
Returns true if sampler exists, false otherwise |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=head3 $api->gateway_connected() |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
Checks whether the Gateway is connected to this NetProbe Returns true |
452
|
|
|
|
|
|
|
if the Gateway is connected, false otherwise |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=head2 Gateway Function Calls |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=head3 $api->add_managed_entity($managed_entity, $data_section) |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
Adds the managed entity to the particular data section Returns true on success, false otherwise |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=head2 Debugging |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
The module comes with a debug handler. The handler must be passed as a reference |
463
|
|
|
|
|
|
|
to subroutine and it could be done as a constructor option: |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
my $api = Geneos::API->new("http://localhost:7036/xmlrpc", { |
466
|
|
|
|
|
|
|
api => { debug_handler => \&my_debug_handler, }, |
467
|
|
|
|
|
|
|
}); |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
or via a separate method: |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
$api->debug_handler(\&my_debug_handler) |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
The subroutine is called with one parameter: C object. |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
The following C methods might be useful for debugging purposes: |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
=over 4 |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=item * C |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
Returns the time at the start of the request. It's captured using Time::HiRes::gettimeofday |
482
|
|
|
|
|
|
|
method: C<$t0 = [gettimeofday]> |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=item * C |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
Returns the C object. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=item * C |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Returns the C object. |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=item * C |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
Returns the C object. See C for more details. |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=item * C |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Returns the C object. See C for more details. |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=back |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
The debug handler can be removed by calling: |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
$api->remove_debug_handler() |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
Example. |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
The custom debug handler in this example will output the following stats: |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=over 4 |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=item * Elapsed time |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=item * HTTP request headers |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=item * HTTP response headers |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=back |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
use Time::HiRes qw(tv_interval); |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
$api->debug_handler(\&custom_debug_handler); |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
sub custom_debug_handler { |
525
|
|
|
|
|
|
|
my $api_obj = shift; |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
printf "# elapsed time: %f\n\n# request header:\n%s\n# response header:\n%s\n", |
528
|
|
|
|
|
|
|
tv_interval($api_obj->t0), |
529
|
|
|
|
|
|
|
$api_obj->http_request->headers_as_string, |
530
|
|
|
|
|
|
|
$api_obj->http_response->headers_as_string; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
Upon execution, it will produce output similar to: |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
# elapsed time: 0.002529 |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
# request header: |
538
|
|
|
|
|
|
|
User-Agent: libwww-perl/6.04 |
539
|
|
|
|
|
|
|
Content-Type: text/xml |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
# response header: |
542
|
|
|
|
|
|
|
Connection: Keep-Alive |
543
|
|
|
|
|
|
|
Server: GENEOS XML-RPC |
544
|
|
|
|
|
|
|
Content-Length: 152 |
545
|
|
|
|
|
|
|
Content-Type: text/xml |
546
|
|
|
|
|
|
|
Client-Date: Fri, 26 Dec 2014 16:18:10 GMT |
547
|
|
|
|
|
|
|
Client-Peer: 127.0.0.1:9033 |
548
|
|
|
|
|
|
|
Client-Response-Num: 1 |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=head1 ONLINE RESOURCES AND SUPPORT |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=over 4 |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=item * L ITRS Group |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=item * L XML-RPC Specification |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
=item * Drop me an email if you have any questions with Geneos::API in the subject |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=back |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=head1 BUGS |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
Of course. Please raise a ticket via L |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
=head1 AUTHOR |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
Ivan Dmitriev, Etot@cpan.orgE |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
Copyright (C) 2014 by Ivan Dmitriev |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify it |
575
|
|
|
|
|
|
|
under the same terms as Perl itself. |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=cut |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
############################################################### |
580
|
|
|
|
|
|
|
# |
581
|
|
|
|
|
|
|
# package Geneos::API::XMLRPC::Response |
582
|
|
|
|
|
|
|
# |
583
|
|
|
|
|
|
|
# Parses XML-RPC response and converts it into Perl structure |
584
|
|
|
|
|
|
|
# |
585
|
|
|
|
|
|
|
############################################################### |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
package Geneos::API::XMLRPC::Response; |
588
|
|
|
|
|
|
|
|
589
|
1
|
|
|
1
|
|
20659
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
44
|
|
590
|
|
|
|
|
|
|
|
591
|
1
|
|
|
1
|
|
1987
|
use XML::LibXML qw(:libxml); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
sub new { |
594
|
|
|
|
|
|
|
my $this = shift; |
595
|
|
|
|
|
|
|
my $class = ref($this) || $this; |
596
|
|
|
|
|
|
|
my $self = { |
597
|
|
|
|
|
|
|
_response => {}, |
598
|
|
|
|
|
|
|
_error => undef, |
599
|
|
|
|
|
|
|
}; |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
bless $self, $class; |
602
|
|
|
|
|
|
|
$self->_init(@_); |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
sub _init { |
606
|
|
|
|
|
|
|
my ($self, $response) = @_; |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# Check if the HTTP request succeeded |
609
|
|
|
|
|
|
|
if ($response->is_success) { |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
my $dom = XML::LibXML->load_xml(string => $response->decoded_content); |
612
|
|
|
|
|
|
|
process_node($self->{_response}, $dom->documentElement); |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
if (exists $self->{_response}{fault}) { |
615
|
|
|
|
|
|
|
my $code = exists $self->{_response}{fault}{faultCode} |
616
|
|
|
|
|
|
|
? $self->{_response}{fault}{faultCode} |
617
|
|
|
|
|
|
|
: -1; |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
my $str = exists $self->{_response}{fault}{faultString} |
620
|
|
|
|
|
|
|
? $self->{_response}{fault}{faultString} |
621
|
|
|
|
|
|
|
: 'NO_ERROR_STRING'; |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
$self->error({class=>"XML-RPC", code=>$code, message=>$str,}); |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
else { |
628
|
|
|
|
|
|
|
$self->error({class=>"HTTP", code=>$response->code, message=>$response->message,}); |
629
|
|
|
|
|
|
|
} |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
return $self; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
sub is_success {!shift->error} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
sub params {shift->{_response}{params}} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
sub error { |
639
|
|
|
|
|
|
|
my ($self, $error) = @_; |
640
|
|
|
|
|
|
|
$self->{_error} = $error if $error; |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
return $self->{_error}; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# --------------- |
646
|
|
|
|
|
|
|
# Response parser |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
sub process_node { |
649
|
|
|
|
|
|
|
my ($r, $node) = @_; |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
for my $child ($node->childNodes) { |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
if ($child->nodeName eq "struct") { |
654
|
|
|
|
|
|
|
process_struct($r, $child); |
655
|
|
|
|
|
|
|
} |
656
|
|
|
|
|
|
|
elsif ($child->nodeName eq "fault") { |
657
|
|
|
|
|
|
|
process_fault($r, $child); |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
elsif ($child->nodeName eq "params") { |
660
|
|
|
|
|
|
|
process_params($r, $child); |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
elsif ($child->nodeName eq "array") { |
663
|
|
|
|
|
|
|
process_array($r, $child); |
664
|
|
|
|
|
|
|
} |
665
|
|
|
|
|
|
|
elsif ($child->nodeName =~ m/^i4|int|boolean|string|double|dateTime\.iso8601|base64$/) { |
666
|
|
|
|
|
|
|
$$r = $child->textContent; |
667
|
|
|
|
|
|
|
} |
668
|
|
|
|
|
|
|
elsif ($child->nodeType == 3 |
669
|
|
|
|
|
|
|
&& $node->nodeName eq "value" |
670
|
|
|
|
|
|
|
&& $node->childNodes->size == 1 |
671
|
|
|
|
|
|
|
) { |
672
|
|
|
|
|
|
|
$$r = $child->textContent; |
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
else { |
675
|
|
|
|
|
|
|
process_node($r, $child); |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
sub process_fault { |
681
|
|
|
|
|
|
|
my ($r, $node) = @_; |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
my ($value) = $node->findnodes("./value"); |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
process_node(\$r->{fault}, $value); |
686
|
|
|
|
|
|
|
} |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
sub process_struct { |
689
|
|
|
|
|
|
|
my ($r, $node) = @_; |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
foreach my $member ( $node->findnodes("./member") ) { |
692
|
|
|
|
|
|
|
my ($name) = $member->findnodes("./name"); |
693
|
|
|
|
|
|
|
my ($value) = $member->findnodes("./value"); |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
process_node(\$$r->{$name->textContent}, $value); |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
sub process_array { |
700
|
|
|
|
|
|
|
my ($r, $node) = @_; |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
foreach my $value ( $node->findnodes("./data/value") ) { |
703
|
|
|
|
|
|
|
process_node(\$$r->[++$#{$$r}], $value); |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
} |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
sub process_params { |
708
|
|
|
|
|
|
|
my ($r, $node) = @_; |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
$r->{params} = []; |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
foreach my $param ( $node->findnodes("./param") ) { |
713
|
|
|
|
|
|
|
my ($value) = $param->findnodes("./value"); |
714
|
|
|
|
|
|
|
process_node(\$r->{params}[++$#{$r->{params}}], $value); |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
########################################### |
719
|
|
|
|
|
|
|
# |
720
|
|
|
|
|
|
|
# package Geneos::API::XMLRPC::Request |
721
|
|
|
|
|
|
|
# |
722
|
|
|
|
|
|
|
# Converts method and Perl data structure |
723
|
|
|
|
|
|
|
# into an XML-RPC request |
724
|
|
|
|
|
|
|
# |
725
|
|
|
|
|
|
|
########################################### |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
package Geneos::API::XMLRPC::Request; |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
use XML::LibXML; |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
sub new { |
732
|
|
|
|
|
|
|
my $this = shift; |
733
|
|
|
|
|
|
|
my $class = ref($this) || $this; |
734
|
|
|
|
|
|
|
my $self = {}; |
735
|
|
|
|
|
|
|
bless $self, $class; |
736
|
|
|
|
|
|
|
$self->_init(@_); |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
# Private methods |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub _init { |
742
|
|
|
|
|
|
|
my ($self, $method, @params) = @_; |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
# remember the method and params |
745
|
|
|
|
|
|
|
$self->{_method} = $method; |
746
|
|
|
|
|
|
|
$self->{_params} = \@params; |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
$self->{doc} = XML::LibXML::Document->new('1.0', 'utf-8'); |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
my $root = $self->{doc}->createElement("methodCall"); |
751
|
|
|
|
|
|
|
$self->{doc}->setDocumentElement($root); |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
# ------------------ |
754
|
|
|
|
|
|
|
# Add the methodName |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
my $methodName = $self->{doc}->createElement("methodName"); |
757
|
|
|
|
|
|
|
$methodName->appendTextNode($method); |
758
|
|
|
|
|
|
|
$root->appendChild($methodName); |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
# -------------- |
761
|
|
|
|
|
|
|
# Add the params |
762
|
|
|
|
|
|
|
my $params = $self->{doc}->createElement("params"); |
763
|
|
|
|
|
|
|
$root->appendChild($params); |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
# --------------------- |
766
|
|
|
|
|
|
|
# Process the agruments |
767
|
|
|
|
|
|
|
foreach (@params) { |
768
|
|
|
|
|
|
|
my $param = $self->{doc}->createElement("param"); |
769
|
|
|
|
|
|
|
$params->addChild($param); |
770
|
|
|
|
|
|
|
$self->parse($param, $_); |
771
|
|
|
|
|
|
|
} |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
return $self; |
774
|
|
|
|
|
|
|
} |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
# Public methods |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
# accessor for the method |
779
|
|
|
|
|
|
|
sub method {shift->{_method}} |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
# accessor for the params |
782
|
|
|
|
|
|
|
sub params {shift->{_params}} |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
sub content {shift->{doc}->toString} |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
sub parse { |
787
|
|
|
|
|
|
|
my ($self, $node, $p) = @_; |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
my $value = $self->{doc}->createElement("value"); |
790
|
|
|
|
|
|
|
$node->addChild($value); |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
if ( ref($p) eq 'HASH' ) { |
793
|
|
|
|
|
|
|
$self->parse_hash($value,$p); |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
elsif ( ref($p) eq 'ARRAY' ) { |
796
|
|
|
|
|
|
|
$self->parse_array($value,$p); |
797
|
|
|
|
|
|
|
} |
798
|
|
|
|
|
|
|
elsif ( ref($p) eq 'CODE' ) { |
799
|
|
|
|
|
|
|
$self->parse_code($value,$p); |
800
|
|
|
|
|
|
|
} |
801
|
|
|
|
|
|
|
else { |
802
|
|
|
|
|
|
|
$self->parse_scalar($value,$p); |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
# It seems that Geneos treats everything as a string |
807
|
|
|
|
|
|
|
# no need for anything sophisticated here |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
sub parse_scalar { |
810
|
|
|
|
|
|
|
my ($self, $node, $scalar) = @_; |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
$scalar ||= ""; |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
if (( $scalar =~ m/^[\-+]?\d+$/) && (abs($scalar) <= (0xffffffff >> 1))) { |
815
|
|
|
|
|
|
|
my $i = $self->{doc}->createElement("i4"); |
816
|
|
|
|
|
|
|
$i->appendTextNode($scalar); |
817
|
|
|
|
|
|
|
$node->appendChild($i); |
818
|
|
|
|
|
|
|
} |
819
|
|
|
|
|
|
|
elsif ( $scalar =~ m/^[\-+]?\d+\.\d+$/ ) { |
820
|
|
|
|
|
|
|
my $d = $self->{doc}->createElement("double"); |
821
|
|
|
|
|
|
|
$d->appendTextNode($scalar); |
822
|
|
|
|
|
|
|
$node->appendChild($d); |
823
|
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
else { |
825
|
|
|
|
|
|
|
my $s = $self->{doc}->createElement("string"); |
826
|
|
|
|
|
|
|
$s->appendTextNode($scalar); |
827
|
|
|
|
|
|
|
$node->appendChild($s); |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
sub parse_hash { |
832
|
|
|
|
|
|
|
my ($self, $node, $hash) = @_; |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
my $struct = $self->{doc}->createElement("struct"); |
835
|
|
|
|
|
|
|
$node->appendChild($struct); |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
foreach (keys %$hash) { |
838
|
|
|
|
|
|
|
my $member = $self->{doc}->createElement("member"); |
839
|
|
|
|
|
|
|
$struct->appendChild($member); |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
my $name = $self->{doc}->createElement("name"); |
842
|
|
|
|
|
|
|
$name->appendTextNode($_); |
843
|
|
|
|
|
|
|
$member->appendChild($name); |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
$self->parse($member, $hash->{$_}); |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
} |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
sub parse_array { |
850
|
|
|
|
|
|
|
my ($self, $node, $args) = @_; |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
my $array = $self->{doc}->createElement("array"); |
853
|
|
|
|
|
|
|
$node->appendChild($array); |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
my $data = $self->{doc}->createElement("data"); |
856
|
|
|
|
|
|
|
$array->appendChild($data); |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
$self->parse($data, $_) for @$args; |
859
|
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
sub parse_code { |
862
|
|
|
|
|
|
|
my ($self, $node, $code) = @_; |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
my ($type, $data) = $code->(); |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
my $e = $self->{doc}->createElement($type); |
867
|
|
|
|
|
|
|
$e->appendTextNode($data); |
868
|
|
|
|
|
|
|
$node->appendChild($e); |
869
|
|
|
|
|
|
|
} |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
######################################################################## |
872
|
|
|
|
|
|
|
# |
873
|
|
|
|
|
|
|
# package Geneos::API::XMLRPC |
874
|
|
|
|
|
|
|
# |
875
|
|
|
|
|
|
|
# XML-RPC client |
876
|
|
|
|
|
|
|
# The reason for yet another XML-RPC implementation is that |
877
|
|
|
|
|
|
|
# because Geneos XML-RPC does not conform to the XML-RPC standard: |
878
|
|
|
|
|
|
|
# |
879
|
|
|
|
|
|
|
# * '-' is used in the method names |
880
|
|
|
|
|
|
|
# * the values do not default to type 'string' |
881
|
|
|
|
|
|
|
# |
882
|
|
|
|
|
|
|
# Among other reasons, ensuring that HTTP1.1 is used to take advantage |
883
|
|
|
|
|
|
|
# of the keep_alive feature supported by Geneos XML-RPC server |
884
|
|
|
|
|
|
|
# |
885
|
|
|
|
|
|
|
######################################################################## |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
package Geneos::API::XMLRPC; |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
use LWP::UserAgent; |
890
|
|
|
|
|
|
|
use Time::HiRes qw(gettimeofday); |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
# ----------- |
893
|
|
|
|
|
|
|
# Constructor |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
sub new { |
896
|
|
|
|
|
|
|
my $this = shift; |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
my $class = ref($this) || $this; |
899
|
|
|
|
|
|
|
my $self = {}; |
900
|
|
|
|
|
|
|
bless $self, $class; |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
$self->_init(@_); |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
# --------------- |
906
|
|
|
|
|
|
|
# Private methods |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
sub _init { |
909
|
|
|
|
|
|
|
my ($self, $url, $opts) = @_; |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
$self->{_url} = $url; |
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
$opts ||= {}; |
914
|
|
|
|
|
|
|
$opts->{ua} ||= {}; |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
# set up the UserAgent |
917
|
|
|
|
|
|
|
$self->{_ua} = LWP::UserAgent->new(%{$opts->{ua}}); |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
return $self; |
920
|
|
|
|
|
|
|
} |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
# -------------- |
923
|
|
|
|
|
|
|
# Public methods |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
sub request { |
926
|
|
|
|
|
|
|
my ($self, $method, @params) = @_; |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
# record the start time |
929
|
|
|
|
|
|
|
$self->{_t0} = [gettimeofday]; |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
# prepare the XML-RPC request |
932
|
|
|
|
|
|
|
$self->{_xmlrpc_request} = Geneos::API::XMLRPC::Request->new($method, @params); |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
# create an http request |
935
|
|
|
|
|
|
|
$self->{_http_request} = HTTP::Request->new("POST",$self->{_url}); |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
$self->{_http_request}->header('Content-Type' => 'text/xml'); |
938
|
|
|
|
|
|
|
$self->{_http_request}->add_content_utf8($self->{_xmlrpc_request}->content); |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
# send the http request |
941
|
|
|
|
|
|
|
$self->{_http_response} = $self->{_ua}->request($self->{_http_request}); |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
# parse the http response |
944
|
|
|
|
|
|
|
$self->{_xmlrpc_response} = Geneos::API::XMLRPC::Response->new($self->{_http_response}); |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
# the LWP::UserAgent object |
948
|
|
|
|
|
|
|
sub user_agent {shift->{_ua}} |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
# -------------------------------------- |
951
|
|
|
|
|
|
|
# These methods are useful for debugging |
952
|
|
|
|
|
|
|
# |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
# request start time |
955
|
|
|
|
|
|
|
sub t0 {shift->{_t0}} |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
# xmlrpc/http requests/responses |
958
|
|
|
|
|
|
|
sub xmlrpc_request {shift->{_xmlrpc_request}} |
959
|
|
|
|
|
|
|
sub xmlrpc_response {shift->{_xmlrpc_response}} |
960
|
|
|
|
|
|
|
sub http_request {shift->{_http_request}} |
961
|
|
|
|
|
|
|
sub http_response {shift->{_http_response}} |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
########################################################################### |
964
|
|
|
|
|
|
|
# package Geneos::Base # |
965
|
|
|
|
|
|
|
# # |
966
|
|
|
|
|
|
|
# This base class implements error handling and interface to # |
967
|
|
|
|
|
|
|
# Geneos::API::XMLRPC that is used by Geneos::API, Geneos::API::Sampler, # |
968
|
|
|
|
|
|
|
# Geneos::API::Sampler::View and Geneos::API::Sampler::Stream classes # |
969
|
|
|
|
|
|
|
# # |
970
|
|
|
|
|
|
|
########################################################################### |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
package Geneos::Base; |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
use Carp; |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
our $VERSION = '0.12'; |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
sub new {bless({_error=>undef,}, shift)->_init(@_)} |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
sub status_line { |
981
|
|
|
|
|
|
|
my $self = shift; |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
if ($self->{_error}) { |
984
|
|
|
|
|
|
|
my $code = $self->{_error}->{code} || '000'; |
985
|
|
|
|
|
|
|
my $message = $self->{_error}->{message} || 'Empty'; |
986
|
|
|
|
|
|
|
return "$code $message"; |
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
else { |
989
|
|
|
|
|
|
|
return undef; |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
sub call { |
994
|
|
|
|
|
|
|
my ($self, $method, @params) = @_; |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
$self->_reset_error; |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
# send the XMLRPC request to the NetProbe |
999
|
|
|
|
|
|
|
my $response = $self->api->request($self->_method($method), @params); |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
# debug handler is passed the xmlrpc object |
1002
|
|
|
|
|
|
|
$self->api->{_debug_handler}->($self->api->xmlrpc) if $self->api->{_debug_handler}; |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
# check the response |
1005
|
|
|
|
|
|
|
if ($response->is_success) { |
1006
|
|
|
|
|
|
|
$response->params->[0]; |
1007
|
|
|
|
|
|
|
} |
1008
|
|
|
|
|
|
|
else { |
1009
|
|
|
|
|
|
|
$self->_handle_error($response->error); |
1010
|
|
|
|
|
|
|
} |
1011
|
|
|
|
|
|
|
} |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
sub error {shift->{_error}} |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
sub _error { |
1016
|
|
|
|
|
|
|
my ($self, $error) = @_; |
1017
|
|
|
|
|
|
|
$self->{_error} = $error if $error; |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
return $self->{_error}; |
1020
|
|
|
|
|
|
|
} |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
sub _handle_error { |
1023
|
|
|
|
|
|
|
my ($self, $error) = @_; |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
# check if there is an error to handle |
1026
|
|
|
|
|
|
|
unless (ref($error) eq 'HASH') { |
1027
|
|
|
|
|
|
|
$error = { |
1028
|
|
|
|
|
|
|
class => '_INTERNAL', |
1029
|
|
|
|
|
|
|
code => '999', |
1030
|
|
|
|
|
|
|
message => "Expected hashref but received '$error' instead", |
1031
|
|
|
|
|
|
|
}; |
1032
|
|
|
|
|
|
|
} |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
# record the error |
1035
|
|
|
|
|
|
|
$self->_error($error); |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
# execute the error handler code |
1038
|
|
|
|
|
|
|
$self->api->{_error_handler}->($error, $self) if $self->api->{_error_handler}; |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
# always return undef |
1041
|
|
|
|
|
|
|
return; |
1042
|
|
|
|
|
|
|
} |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
sub _reset_error {shift->{_error} = undef} |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
####################################### |
1047
|
|
|
|
|
|
|
# |
1048
|
|
|
|
|
|
|
# package Geneos::API::Sampler::Stream |
1049
|
|
|
|
|
|
|
# |
1050
|
|
|
|
|
|
|
# Implements all Steam methods |
1051
|
|
|
|
|
|
|
# |
1052
|
|
|
|
|
|
|
####################################### |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
package Geneos::API::Sampler::Stream; |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
use base 'Geneos::Base'; |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
sub _init { |
1059
|
|
|
|
|
|
|
my ($self, $sampler, $stream) = @_; |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
$self->{_sampler} = $sampler; |
1062
|
|
|
|
|
|
|
$self->{_stream} = $stream; |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
return $self; |
1065
|
|
|
|
|
|
|
} |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
sub _method { |
1068
|
|
|
|
|
|
|
my $self = shift; |
1069
|
|
|
|
|
|
|
join(".", $self->{_sampler}->entity, $self->{_sampler}->sampler, "$self->{_stream}", @_); |
1070
|
|
|
|
|
|
|
} |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
sub api {shift->{_sampler}->api} |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
# API Streams Function Calls |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
sub add_message {shift->call("addMessage", @_)} |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
###################################### |
1079
|
|
|
|
|
|
|
# |
1080
|
|
|
|
|
|
|
# package Geneos::API::Sampler::View |
1081
|
|
|
|
|
|
|
# |
1082
|
|
|
|
|
|
|
# Implements all View methods |
1083
|
|
|
|
|
|
|
# |
1084
|
|
|
|
|
|
|
###################################### |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
package Geneos::API::Sampler::View; |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
use base 'Geneos::Base'; |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
sub _init { |
1091
|
|
|
|
|
|
|
my ($self, $sampler, $view, $group) = @_; |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
$self->{_sampler} = $sampler; |
1094
|
|
|
|
|
|
|
$self->{_view} = $view; |
1095
|
|
|
|
|
|
|
$self->{_group} = $group; |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
return $self; |
1098
|
|
|
|
|
|
|
} |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
sub _method { |
1101
|
|
|
|
|
|
|
my $self = shift; |
1102
|
|
|
|
|
|
|
join(".", $self->{_sampler}->entity, $self->{_sampler}->sampler, "$self->{_group}-$self->{_view}", @_); |
1103
|
|
|
|
|
|
|
} |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
sub api {shift->{_sampler}->api} |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
# API calls |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
# --------------------------------------------- |
1110
|
|
|
|
|
|
|
# Combines addTableRow and updateTableRow calls |
1111
|
|
|
|
|
|
|
# |
1112
|
|
|
|
|
|
|
sub add_table_row { |
1113
|
|
|
|
|
|
|
my ($self, $name, $data) = @_; |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
return unless $self->_add_table_row($name); |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
# if there is data - add it to the row |
1118
|
|
|
|
|
|
|
$data ? $self->update_table_row($name, $data) : 1; |
1119
|
|
|
|
|
|
|
} |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
# ----------------------------------------------------- |
1122
|
|
|
|
|
|
|
# Each method below is an XML-RPC call to the NetProbe |
1123
|
|
|
|
|
|
|
# |
1124
|
|
|
|
|
|
|
# The first argument passed to the call method is the |
1125
|
|
|
|
|
|
|
# XML-RPC method name. The rest are parameters passed |
1126
|
|
|
|
|
|
|
# with that call to the XML-RPC server |
1127
|
|
|
|
|
|
|
# |
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
sub _add_table_row {shift->call("addTableRow", @_)} |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
sub remove_table_row {shift->call("removeTableRow", @_)} |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
sub add_headline {shift->call("addHeadline", @_)} |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
sub remove_headline {shift->call("removeHeadline", @_)} |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
sub update_variable {shift->call("updateVariable", @_)} |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
sub update_headline {shift->call("updateHeadline", @_)} |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
sub update_table_cell {shift->call("updateTableCell", @_)} |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
sub update_table_row {shift->call("updateTableRow", @_)} |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
sub add_table_column {shift->call("addTableColumn", @_)} |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
sub update_entire_table {shift->call("updateEntireTable", @_)} |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
sub column_exists {shift->call("columnExists", @_)} |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
sub row_exists {shift->call("rowExists", @_)} |
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
sub headline_exists {shift->call("headlineExists", @_)} |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
sub get_column_count {shift->call("getColumnCount")} |
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
sub get_row_count {shift->call("getRowCount")} |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
sub get_headline_count {shift->call("getHeadlineCount")} |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
sub get_column_names {shift->call("getColumnNames")} |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
sub get_row_names {shift->call("getRowNames")} |
1164
|
|
|
|
|
|
|
|
1165
|
|
|
|
|
|
|
sub get_headline_names {shift->call("getHeadlineNames")} |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
sub get_row_names_older_than {shift->call("getRowNamesOlderThan", @_)} |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
################################## |
1170
|
|
|
|
|
|
|
# |
1171
|
|
|
|
|
|
|
# package Geneos::API::Sampler |
1172
|
|
|
|
|
|
|
# |
1173
|
|
|
|
|
|
|
# Implements all sampler methods |
1174
|
|
|
|
|
|
|
# |
1175
|
|
|
|
|
|
|
################################## |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
package Geneos::API::Sampler; |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
use base 'Geneos::Base'; |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
sub _init { |
1182
|
|
|
|
|
|
|
my ($self, $api, $entity, $sampler) = @_; |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
$self->{_api} = $api; |
1185
|
|
|
|
|
|
|
$self->{_entity} = $entity; |
1186
|
|
|
|
|
|
|
$self->{_sampler} = $sampler; |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
return $self; |
1189
|
|
|
|
|
|
|
} |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
# --------------------------------------------------------- |
1192
|
|
|
|
|
|
|
# XML-RPC methodName for the sampler calls looks like this: |
1193
|
|
|
|
|
|
|
# entity.sampler.action |
1194
|
|
|
|
|
|
|
# |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
sub _method { |
1197
|
|
|
|
|
|
|
my $self = shift; |
1198
|
|
|
|
|
|
|
join(".", $self->{_entity}, $self->{_sampler}, @_); |
1199
|
|
|
|
|
|
|
} |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
sub api {shift->{_api}} |
1202
|
|
|
|
|
|
|
sub sampler {shift->{_sampler}} |
1203
|
|
|
|
|
|
|
sub entity {shift->{_entity}} |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
# ------------------------------------- |
1206
|
|
|
|
|
|
|
# |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
sub get_stream { |
1209
|
|
|
|
|
|
|
my $self = shift; |
1210
|
|
|
|
|
|
|
$self->_reset_error; |
1211
|
|
|
|
|
|
|
Geneos::API::Sampler::Stream->new($self, @_) |
1212
|
|
|
|
|
|
|
} |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
# ------------------------------------- |
1215
|
|
|
|
|
|
|
# |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
sub get_view { |
1218
|
|
|
|
|
|
|
my $self = shift; |
1219
|
|
|
|
|
|
|
$self->_reset_error; |
1220
|
|
|
|
|
|
|
Geneos::API::Sampler::View->new($self, @_) |
1221
|
|
|
|
|
|
|
} |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
############# |
1224
|
|
|
|
|
|
|
# API calls # |
1225
|
|
|
|
|
|
|
############# |
1226
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
sub create_view { |
1228
|
|
|
|
|
|
|
my $self = shift; |
1229
|
|
|
|
|
|
|
$self->call("createView", @_) ? Geneos::API::Sampler::View->new($self, @_) : undef; |
1230
|
|
|
|
|
|
|
} |
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
# ------------------------------------------------------- |
1233
|
|
|
|
|
|
|
# Checks whether a particular view exists in this sampler |
1234
|
|
|
|
|
|
|
# |
1235
|
|
|
|
|
|
|
# Returns true if the view exists, false otherwise |
1236
|
|
|
|
|
|
|
# |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
sub view_exists { |
1239
|
|
|
|
|
|
|
my ($self, $view, $group) = @_; |
1240
|
|
|
|
|
|
|
$self->call("viewExists", "${group}-${view}"); |
1241
|
|
|
|
|
|
|
} |
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
sub remove_view {shift->call("removeView", @_)} |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
# ----------------------------------------------- |
1246
|
|
|
|
|
|
|
# Retrieves the value of a sampler parameter that |
1247
|
|
|
|
|
|
|
# has been defined in the gateway configuration |
1248
|
|
|
|
|
|
|
# |
1249
|
|
|
|
|
|
|
# Returns the parameter text written in the gateway configuration |
1250
|
|
|
|
|
|
|
# |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
sub get_parameter {shift->call("getParameter", @_)} |
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
sub sign_on {shift->call("signOn", @_)} |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
sub sign_off {shift->call("signOff")} |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
sub heartbeat {shift->call("heartbeat")} |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
###################################### |
1261
|
|
|
|
|
|
|
# |
1262
|
|
|
|
|
|
|
# package Geneos::API |
1263
|
|
|
|
|
|
|
# |
1264
|
|
|
|
|
|
|
# Implements the Geneos XML-RPC API |
1265
|
|
|
|
|
|
|
# |
1266
|
|
|
|
|
|
|
###################################### |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
package Geneos::API; |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
our $VERSION = '0.12'; |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
use base 'Geneos::Base'; |
1273
|
|
|
|
|
|
|
use Carp; |
1274
|
|
|
|
|
|
|
use Time::HiRes qw(tv_interval); |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
sub _init { |
1277
|
|
|
|
|
|
|
my ($self, $url, $opts) = @_; |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
# the url must be present |
1280
|
|
|
|
|
|
|
croak "Geneos::API->new was called without url!" unless $url; |
1281
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
# process the options |
1283
|
|
|
|
|
|
|
$opts ||= {}; |
1284
|
|
|
|
|
|
|
$opts->{ua} ||= {}; |
1285
|
|
|
|
|
|
|
$opts->{api} ||= {}; |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
$self->{_xmlrpc} = Geneos::API::XMLRPC->new($url, $opts); |
1288
|
|
|
|
|
|
|
$self->{_opts} = $opts; |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
# ---------------------- |
1291
|
|
|
|
|
|
|
# init the error handler |
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
if (ref($opts->{api}{error_handler}) eq 'CODE') { |
1294
|
|
|
|
|
|
|
$self->error_handler($opts->{api}{error_handler}); |
1295
|
|
|
|
|
|
|
} |
1296
|
|
|
|
|
|
|
elsif ($opts->{api}{raise_error}) { |
1297
|
|
|
|
|
|
|
$self->error_handler( |
1298
|
|
|
|
|
|
|
sub {croak("$_[0]->{code} $_[0]->{message}")} |
1299
|
|
|
|
|
|
|
); |
1300
|
|
|
|
|
|
|
} |
1301
|
|
|
|
|
|
|
elsif ($opts->{api}{print_error}) { |
1302
|
|
|
|
|
|
|
$self->error_handler( |
1303
|
|
|
|
|
|
|
sub {carp("$_[0]->{code} $_[0]->{message}")} |
1304
|
|
|
|
|
|
|
); |
1305
|
|
|
|
|
|
|
} |
1306
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
# ---------------------- |
1308
|
|
|
|
|
|
|
# init the debug handler |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
if ($opts->{api}{debug_handler}) { |
1311
|
|
|
|
|
|
|
$self->debug_handler($opts->{api}{debug_handler}); |
1312
|
|
|
|
|
|
|
} |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
return $self; |
1315
|
|
|
|
|
|
|
} |
1316
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
sub _method {shift;@_} |
1318
|
|
|
|
|
|
|
|
1319
|
|
|
|
|
|
|
# --------------------- |
1320
|
|
|
|
|
|
|
# get/set error handler |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
sub error_handler { |
1323
|
|
|
|
|
|
|
my ($self, $handler) = @_; |
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
if (ref($handler) eq 'CODE') { |
1326
|
|
|
|
|
|
|
$self->{_error_handler} = $handler; |
1327
|
|
|
|
|
|
|
} |
1328
|
|
|
|
|
|
|
elsif ($handler) { |
1329
|
|
|
|
|
|
|
carp("argument for error_handler must be a coderef but got: ", ref($handler)); |
1330
|
|
|
|
|
|
|
} |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
return $self->{_error_handler}; |
1333
|
|
|
|
|
|
|
} |
1334
|
|
|
|
|
|
|
|
1335
|
|
|
|
|
|
|
# -------------------- |
1336
|
|
|
|
|
|
|
# remove error handler |
1337
|
|
|
|
|
|
|
|
1338
|
|
|
|
|
|
|
sub remove_error_handler {shift->{_error_handler}=undef;} |
1339
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
# --------------------- |
1341
|
|
|
|
|
|
|
# get/set debug handler |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
sub debug_handler { |
1344
|
|
|
|
|
|
|
my ($self, $handler) = @_; |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
if (ref($handler) eq 'CODE') { |
1347
|
|
|
|
|
|
|
$self->{_debug_handler} = $handler; |
1348
|
|
|
|
|
|
|
} |
1349
|
|
|
|
|
|
|
elsif ($handler) { |
1350
|
|
|
|
|
|
|
carp("argument for debug_handler must be a coderef but got: ", ref($handler)); |
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
return $self->{_debug_handler}; |
1354
|
|
|
|
|
|
|
} |
1355
|
|
|
|
|
|
|
|
1356
|
|
|
|
|
|
|
# -------------------- |
1357
|
|
|
|
|
|
|
# remove debug handler |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
sub remove_debug_handler {shift->{_debug_handler}=undef;} |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
sub raise_error {shift->{_opts}{api}{raise_error}} |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
sub remove_raise_error {shift->{_opts}{api}{raise_error}=undef;} |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
sub print_error {shift->{_opts}{api}{print_error}} |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
sub remove_print_error {shift->{_opts}{api}{print_error}=undef;} |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
sub api{shift} |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
# send XMLRPC request |
1372
|
|
|
|
|
|
|
sub request {shift->{_xmlrpc}->request(@_)} |
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
# LWP::UserAgent object |
1375
|
|
|
|
|
|
|
sub user_agent {shift->{_xmlrpc}->user_agent} |
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
# Geneos::API::XMLPRC object |
1378
|
|
|
|
|
|
|
sub xmlrpc {shift->{_xmlrpc}} |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
############# |
1381
|
|
|
|
|
|
|
# API calls # |
1382
|
|
|
|
|
|
|
############# |
1383
|
|
|
|
|
|
|
|
1384
|
|
|
|
|
|
|
# ------------------------ |
1385
|
|
|
|
|
|
|
# Creates a sampler object |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
sub get_sampler { |
1388
|
|
|
|
|
|
|
my $self = shift; |
1389
|
|
|
|
|
|
|
$self->_reset_error; |
1390
|
|
|
|
|
|
|
Geneos::API::Sampler->new($self,@_) |
1391
|
|
|
|
|
|
|
} |
1392
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------ |
1394
|
|
|
|
|
|
|
# Checks whether a particular API or API-Streams sampler exists on this NetProbe |
1395
|
|
|
|
|
|
|
# |
1396
|
|
|
|
|
|
|
# Returns true if the sampler exists, false otherwise |
1397
|
|
|
|
|
|
|
# |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
sub sampler_exists { |
1400
|
|
|
|
|
|
|
my ($self, $me, $sampler) = @_; |
1401
|
|
|
|
|
|
|
$self->call("_netprobe.samplerExists", "$me.$sampler"); |
1402
|
|
|
|
|
|
|
} |
1403
|
|
|
|
|
|
|
|
1404
|
|
|
|
|
|
|
# --------------------------------------------------------- |
1405
|
|
|
|
|
|
|
# Checks whether the Gateway is connected to this NetProbe |
1406
|
|
|
|
|
|
|
# |
1407
|
|
|
|
|
|
|
# Returns true if the Gateway is connected, false otherwise |
1408
|
|
|
|
|
|
|
# |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
sub gateway_connected {shift->call("_netprobe.gatewayConnected")} |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
# ------------------------------------------------------ |
1413
|
|
|
|
|
|
|
# Adds the managed entity to the particular data section |
1414
|
|
|
|
|
|
|
# |
1415
|
|
|
|
|
|
|
# Returns true on success, false otherwise |
1416
|
|
|
|
|
|
|
# |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
sub add_managed_entity {shift->call("_gateway.addManagedEntity", @_)} |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
1421
|
|
|
|
|
|
|
# Checks whether a particular Managed Entity exists on this NetProbe |
1422
|
|
|
|
|
|
|
# containing any API or API-Streams samplers |
1423
|
|
|
|
|
|
|
# |
1424
|
|
|
|
|
|
|
# Returns true if the Managed Entity exists, false otherwise |
1425
|
|
|
|
|
|
|
# |
1426
|
|
|
|
|
|
|
|
1427
|
|
|
|
|
|
|
sub managed_entity_exists {shift->call("_netprobe.managedEntityExists", @_)} |
1428
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
1; |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
__END__ |