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