| 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__ |