File Coverage

blib/lib/Ingres/Utility/Netutil.pm
Criterion Covered Total %
statement 12 274 4.3
branch 0 144 0.0
condition 0 27 0.0
subroutine 4 20 20.0
pod 12 12 100.0
total 28 477 5.8


line stmt bran cond sub pod time code
1             package Ingres::Utility::Netutil;
2              
3 1     1   46239 use warnings;
  1         3  
  1         33  
4 1     1   7 use strict;
  1         2  
  1         36  
5 1     1   6 use Carp;
  1         6  
  1         99  
6 1     1   6106 use Expect::Simple;
  1         85245  
  1         2506  
7              
8             =head1 NAME
9              
10             Ingres::Utility::Netutil - API to C Ingres RDBMS utility
11              
12              
13             =head1 VERSION
14              
15             Version 0.03
16              
17             =cut
18              
19             our $VERSION = '0.03';
20              
21             =head1 SYNOPSIS
22              
23             use Ingres::Utility::Netutil;
24            
25             # create a connection to NETUTIL utility
26            
27             $netu = Ingres::Utility::Netutil->new();
28            
29             # Attention: many arguments accept wildcard *
30            
31             # showLogin($type,$vnode) - prepare to provide info on login VNodes
32             # and return netutil ouput
33             print $netu->showLogin('global','*');
34            
35             #
36             # getLogin() - return one-by-one all login VNodes previously prepared
37             while ( ($type, $login, $vnode, $acct) = $netu->getLogin() ) {
38             print "Type: $type\tName: $vnode\tAccount: $acct\n";
39             }
40            
41             # showConn($type, $conn, $vnode, $addr, $proto, $listen)
42             # - prepare to provide info on connections of a VNode
43             # and return netutil ouput
44             print $netu->showConn('global','sample_vnode_name', '*', '*', '*');
45            
46             #
47             # getConn() - return one-by-one all connections of a VNodes previously prepared
48             while ( @conn = $netu->getConn() ) {
49             ($type, $conn, $vnode, $addr, $proto, $listen) = @conn;
50             print "Type: $type\tName: $vnode\tAddress: $addr\tProtocol: $proto";
51             print "\tListen Address: $listenAddr\n";
52             }
53            
54             # createLogin($type,$vnode,$acct, $passwd) - create a new VNode
55             $netu->createLogin('global', 'new_vnode_name', 'sample_login_account', 'secret_passwd');
56            
57             # createConn($type,$vnode,$addr,$proto,$listenAddr) - create a connection for a VNode
58             $netu->createConn('global', 'new_vnode_name', '192.168.0.1', 'tcp_ip', 'II');
59            
60             # destroyConn($type,$vnode,$acct, $passwd) - destroy a connection from a VNode
61             $netu->destroyConn('global', 'new_vnode_name', '192.168.0.1', 'tcp_ip', 'II');
62            
63             # destroyLogin($type,$vnode) - destroy a VNode and all connections
64             $netu->destroyLogin('global', 'new_vnode_name');
65            
66             # quiesceServer($serverId) - stop IIGCC server after all connections close (die gracefully)
67             # if no $serverId is given, then all IIGCC servers are affected (carefull).
68             $netu->quiesceServer('sample_server_id');
69            
70             # stopServer($serverId) - stop IIGCC server imediately (break connections)
71             # if no $serverId is given, then all IIGCC servers are affected (carefull).
72             $netu->stopServer('sample_server_id');
73              
74             The server id can be obtained through L module.
75            
76            
77             =head1 DESCRIPTION
78              
79             This module provides an API to netutil utility for Ingres RDBMS,
80             which provides local control of IIGCC servers for Ingres Net
81             inbound and outbound remote connections, and also manage logins
82             and connections to remote servers, a.k.a. VNodes.
83              
84             =over
85              
86             Notes:
87              
88             Ordinary user can create/destroy on his own private logins and connections.
89              
90             SECURITY privilege should be granted to have access to other user's private
91             entries.
92              
93             GCA privilege NET_ADMIN (generally a system administrator) needed to manage
94             global type login and connection entries.
95              
96             GCA privilege SERVER_CONTROL (generally a system administrator) needed to stop
97             a communications server.
98              
99             =back
100              
101             =head1 METHODS
102              
103             =over
104              
105             =item new(;('USER' => $user, 'VNODE' => $vnode})
106              
107             Start interaction with netutil utility.
108              
109             Takes an optional hash with the user id and remote vnode arguments to
110             identify which user's private VNodes to control and which remote's
111             machine Net configuration to manage. The VNode must be previously created.
112              
113             =cut
114              
115             sub new(;%) {
116 0     0 1   my $class = shift;
117 0           my $this = {};
118 0   0       $class = ref($class) || $class;
119 0           bless $this, $class;
120 0           my %params;
121 0 0         if (@_) {
122 0           (%params) = @_;
123             }
124 0           my $userId;
125 0 0         $userId = (exists $params{'USER'} ? $params{'USER'} : '');
126 0 0         $userId = (exists $params{'user'} ? $params{'user'} : $userId);
127 0           my $vnode;
128 0 0         $vnode = (exists $params{'VNODE'} ? $params{'VNODE'} : '');
129 0 0         $vnode = (exists $params{'vnode'} ? $params{'vnode'} : $vnode);
130 0 0         if (! defined($ENV{'II_SYSTEM'})) {
131 0           carp "Ingres environment variable II_SYSTEM not set";
132 0           return undef;
133             }
134 0           my $Netutil_file = $ENV{'II_SYSTEM'} . '/ingres/bin/netutil';
135 0 0         if (! -x $Netutil_file) {
136 0           carp "Ingres utility cannot be executed: $Netutil_file";
137 0           return undef;
138             }
139 0           my @cmdParams = ('-file-');
140 0 0         if ($userId) {
141 0           push @cmdParams, "-u $userId";
142             }
143 0 0         if ($vnode) {
144 0           push @cmdParams, "-vnode $vnode";
145             }
146             # $Netutil_file .= ' ' . join(' ',@cmdParams); Expect->spawn signature not equal Expect::Simple->new
147 0           $this->{cmd} = $Netutil_file;
148             # $this->{cmd} .= join(' ',@cmdParams);
149 0           $this->{cmdInject} = "_C_M_D_I_N_J_E_C_T_"; # injects a command do to induce "fake prompt"
150 0           $this->{prompt} = ['-re', "\\[.+\\].+" . $this->{cmdInject} . ".*\$"]; # error message in fact due to cmdInject
151             # $this->{cmdInject} = '';
152             # $this->{prompt} = ['-re', "^NETUTIL>"];
153             $this->{xpct} = new Expect
154 0 0         or do {
155 0           carp "Module Expect cannot be instanciated";
156 0           return undef;
157             };
158 0           my $obj = $this->{xpct};
159 0           $obj->debug(0);
160 0           $obj->exp_internal(0);
161 0           $obj->log_stdout(0);
162             $obj->spawn($Netutil_file, @cmdParams)
163 0 0         or do {
164 0           carp "Module Expect cannot be instanciated";
165 0           return undef;
166             };
167 0           $obj->log_stdout(0); # just to be shure!
168 0           $obj->restart_timeout_upon_receive(1);
169             #$obj->send("\n");
170 0           $obj->expect(1, '-re', '^.+$'); # gets first prompt
171 0           $obj->clear_accum(); # and wipe it
172 0           $this->{userId} = $userId;
173 0           $this->{vnode} = $vnode;
174 0           $this->{cmdParams} = \@cmdParams;
175 0           $this->{timeout} = 2;
176 0           return $this;
177             }
178              
179              
180             =item debug($debug_level)
181              
182             Activate Expect Module debuging.
183              
184             =cut
185              
186             sub debug( $$ ) {
187 0     0 1   my $this = shift;
188 0           my $obj = $this->{xpct};
189 0 0 0       if ($obj and @_) {
190 0           $obj->debug(shift);
191 0           $obj->exp_internal(1);
192             }
193             }
194             # Do the real interactions with netutil utility
195             sub _send() {
196 0     0     my $this = shift;
197 0           my $obj = $this->{xpct};
198 0           my @cmd = @_;
199 0 0         if ($this->{cmdInject}) {
200 0           push @cmd, $this->{cmdInject};
201             }
202 0           for (my $i =0; $i < (scalar @cmd); $i++) {
203 0           $cmd[$i] .= "\n";
204             }
205 0           $obj->clear_accum();
206 0           $obj->send(@cmd);
207 0           $obj->expect($this->{timeout}, @{$this->{prompt}})
208 0 0         or do {
209 0           carp "Cannot Expect::expect(): " . $obj->error();
210 0           return undef;
211             };
212             }
213              
214             # Filter double spaces, removes the input echo, injected command and return an
215             # array of output lines
216             sub _getCleanArray($$$$ ) {
217 0     0     my $this = shift;
218 0 0         return undef if ( (scalar @_) != 3);
219 0           my ($cmd, $cmdInject, $before) = @_;
220 0           while ($before =~ /\ \ /) {
221 0           $before =~ s/\ \ /\ /g;
222             }
223 0           my @lines = split /\r\n/,$before;
224 0 0         if (defined $lines[0]) {
225 0 0         if ($lines[0] eq $cmd) {
226 0           shift @lines;
227             }
228 0 0 0       if (defined $lines[0] and $cmdInject) { # removes injected command
229 0 0         if ($lines[0] eq $cmdInject) {
230 0           shift @lines;
231             }
232             }
233             }
234 0           return @lines;
235             }
236              
237             # Return line after line of the {stream} array in a sequential access
238             # each line is parsed into an array of words
239             sub _getLineArray($$ ) {
240 0     0     my $this = shift;
241 0 0         my $object = uc (@_ ? shift : '');
242 0           my $caller;
243 0 0         if ($object eq 'LOGIN') {
    0          
244 0           $caller = 'Login';
245             }
246             elsif ($object eq 'CONNECTION') {
247 0           $caller = 'Conn';
248             }
249             else {
250 0           carp "internal error in _getLineArray(): wrong parameter";
251 0           return undef;
252             }
253 0 0         if ($this->{streamType} ne $object) {
254 0           carp "show" . $caller . "() must be previously invoked";
255 0           return undef;
256             }
257 0 0         if (! $this->{stream}) {
258 0           return ();
259             }
260 0 0         if (! $this->{streamPtr}) {
261 0           $this->{streamPtr} = 0;
262             }
263 0           my @antes = @{$this->{stream}};
  0            
264 0 0         if ((scalar @antes) <= $this->{streamPtr}) {
265 0           $this->{streamPtr} = 0;
266 0           return ();
267             }
268 0           my $line = $antes[$this->{streamPtr}++];
269 0           my @linearr = split /\ /, $line;
270 0           return @linearr;
271             }
272              
273             =item showLogin(;$type, $vnode)
274              
275             Prepare to return VNode login info.
276              
277             Returns output from netutil.
278              
279             Takes the VNode type to filter and name
280              
281             $type - VNode type: GLOBAL/PRIVATE (no wildcard)
282             $vnode - VNode/*
283              
284             =cut
285              
286             sub showLogin ($;$){
287 0     0 1   my $this = shift;
288 0 0         my $type = uc (@_ ? shift : '*');
289 0 0         if ($type) {
290 0 0 0       if ($type ne 'GLOBAL' &&
291             $type ne 'PRIVATE') {
292 0           carp "invalid type: $type";
293 0           return undef;
294             }
295             }
296 0 0         my $vnode = uc (@_ ? shift : '*');
297 0           $this->{streamType} = 'LOGIN';
298 0           my $cmd = "SHOW $type ". $this->{streamType} . " $vnode";
299 0           $this->_send($cmd);
300 0           my $obj = $this->{xpct};
301 0           my $before = $obj->before();
302 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
303            
304 0           $this->{stream} = \@lines;
305 0           $this->{streamPtr} = 0;
306 0           $this->{streamType} = 'LOGIN';
307 0           return join("\n",@lines);
308             }
309              
310              
311             =item getLogin()
312              
313             Returns sequentially (call-after-call) each VNode info reported by showLogin() as an array of
314             4 elements:
315             @login = getlogin();
316             # $login[0] = VNode type (GLOBAL/PRIVATE)
317             # $login[1] = 'LOGIN'
318             # $login[2] = VNode
319             # $login[3] = User/*
320              
321             Password is not returned.
322              
323             =cut
324              
325             sub getLogin() {
326 0     0 1   my $this = shift;
327 0           return $this->_getLineArray('LOGIN');
328             }
329              
330              
331             =item showConn($type; $vnode, $addr, $proto, $listen)
332              
333             Prepare to return VNode connection info.
334              
335             Returns output from netutil.
336              
337             Takes the following parameters:
338             $type - VNode type: GLOBAL/PRIVATE (no wildcard)
339             $vnode - VNode/*
340             $addr - IP, hostname of the server/*
341             $proto - protocol name (tcp_ip, win_tcp, ipx, etc.)/*
342             $listen - remote server's listen address (generaly 'II')/*
343              
344             =cut
345              
346             sub showConn {
347 0     0 1   my $this = shift;
348 0 0         my $type = uc (@_ ? shift : '*');
349 0 0         if ($type) {
350 0 0 0       if ($type ne 'GLOBAL' &&
351             $type ne 'PRIVATE') {
352 0           carp "invalid type: $type";
353 0           return undef;
354             }
355             }
356 0 0         my $vnode = uc (@_ ? shift : '*');
357 0 0         my $addr = uc (@_ ? shift : '*');
358 0 0         my $proto = uc (@_ ? shift : '*');
359 0 0         my $listen = uc (@_ ? shift : '*');
360 0           $this->{streamType} = 'CONNECTION';
361 0           my $cmd = "SHOW $type " . $this->{streamType} . " $vnode $addr $proto $listen";
362 0           $this->_send($cmd);
363 0           my $obj = $this->{xpct};
364 0           my $before = $obj->before();
365 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
366 0           $this->{stream} = \@lines;
367 0           $this->{streamPtr} = 0;
368 0           return join("\n",@lines);
369             }
370              
371              
372             =item getConn()
373              
374             Returns sequentially (call-after-call) each VNode connection info reported by showConn() as an array of
375             6 elements:
376             @conn = getConn();
377             # $conn[0] = VNode type (GLOBAL/PRIVATE)
378             # $conn[1] = 'CONNECTION'
379             # $conn[2] = VNode
380             # $conn[3] = Network address
381             # $conn[4] = Protocol
382             # $conn[5] = Listen address
383              
384             =cut
385              
386             sub getConn() {
387 0     0 1   my $this = shift;
388 0           return $this->_getLineArray('CONNECTION');
389             }
390              
391              
392             =item createLogin($type, $vnode, $user, $passwd)
393              
394             Create a Login VNode.
395            
396             Returns output from netutil.
397              
398             Takes the following parameters:
399             $type - VNode type: GLOBAL/PRIVATE
400             $vnode - VNode name
401             $user - User account/*
402             $passwd - User/installation password
403              
404             The Installation Password can be created invoking this method as follows:
405              
406             $netu = Ingres::Utility::Netutil->new();
407            
408             my $local_vnode = 'myhost.mydomain'; # See note below about $local_vnode
409            
410             $netu->createLogin('GLOBAL', $local_vnode, '*', $installation_passwd);
411              
412             Note: The virtual node name must be identical to the name that has been
413             configured as LOCAL_VNODE on the Configure Name Server screen of the
414             cbf utility. No connection needed
415              
416             =cut
417              
418             sub createLogin($$$$) {
419 0     0 1   my $this = shift;
420 0 0         my $type = uc (@_ ? shift : '*');
421 0 0 0       if ($type ne 'GLOBAL' &&
422             $type ne 'PRIVATE') {
423 0           carp "invalid type: $type";
424 0           return undef;
425             }
426 0 0         my $vnode = uc (@_ ? shift : '');
427 0 0         if (! $vnode) {
428 0           carp "missing VNode name";
429 0           return undef;
430             }
431 0 0         my $user = @_ ? shift : '';
432 0 0         if (! $user) {
433 0           carp "missing User account or '*'";
434 0           return undef;
435             }
436 0 0         my $passwd = @_ ? shift : '';
437 0 0         if (! $passwd) {
438 0           carp "missing password";
439 0           return undef;
440             }
441             #my $before = $this->destroyLogin($type, $vnode);
442 0           my $cmd = "CREATE $type LOGIN $vnode $user $passwd";
443 0           $passwd = undef; # get rid of passwd
444 0           $this->_send($cmd);
445 0           my $obj = $this->{xpct};
446 0           my $before = $obj->before();
447 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
448 0           $cmd = undef; # get rid of passwd
449 0           $this->{stream} = {}; # no more getLogin()/getConn()
450 0           $this->{streamPtr} = 0;
451 0           $this->{streamType} = '';
452 0           return join("\n",@lines);
453             }
454              
455              
456             =item createConn($type, $vnode, $add, $proto, $listen)
457              
458             Create a connection for a Login VNode previously created.
459              
460             Returns output from netutil.
461              
462             Takes the following parameters:
463             $type - VNode type: GLOBAL/PRIVATE
464             $vnode - VNode name
465             $addr - IP, hostname of the server
466             $proto - protocol name (tcp_ip, win_tcp, ipx, etc.)
467             $listen - remote server's listen address (generaly 'II')
468              
469             =cut
470              
471             sub createConn($$$$$) {
472 0     0 1   my $this = shift;
473 0 0         my $type = uc (@_ ? shift : '*');
474 0 0 0       if ($type ne 'GLOBAL' &&
475             $type ne 'PRIVATE') {
476 0           carp "invalid type: $type";
477 0           return undef;
478             }
479 0 0         my $vnode = uc (@_ ? shift : '');
480 0 0         if (! $vnode) {
481 0           carp "missing VNode name";
482 0           return undef;
483             }
484 0 0         my $addr = uc (@_ ? shift : '');
485 0 0         if (! $addr) {
486 0           carp "missing network address";
487 0           return undef;
488             }
489 0 0         my $proto = @_ ? shift : '';
490 0 0         if (! $proto) {
491 0           carp "missing network protocol";
492 0           return undef;
493             }
494 0 0         my $listen = uc(@_ ? shift : '');
495 0 0         if (! $listen) {
496 0           carp "missing network protocol";
497 0           return undef;
498             }
499             #my $before = $this->destroyConn($type,$vnode,$addr,$proto,$listen );
500 0           my $cmd = "CREATE $type CONNECTION $vnode $addr $proto $listen";
501 0           $this->_send($cmd);
502 0           my $obj = $this->{xpct};
503 0           my $before = $obj->before();
504 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
505 0           $this->{stream} = {}; # no more getLogin()/getConn()
506 0           $this->{streamPtr} = 0;
507 0           $this->{streamType} = '';
508 0           return join("\n",@lines);
509             }
510              
511              
512             =item destroyLogin($type, $vnode)
513              
514             Delete a Login VNode and all its connections.
515              
516             Returns output from netutil.
517              
518             Takes the following parameters:
519             $type - VNode type: GLOBAL/PRIVATE
520             $vnode - VNode name/*
521              
522             =cut
523              
524             sub destroyLogin ($$) {
525 0     0 1   my $this = shift;
526 0 0         my $type = uc (@_ ? shift : '*');
527 0 0 0       if ($type ne 'GLOBAL' &&
528             $type ne 'PRIVATE') {
529 0           carp "invalid type: $type";
530 0           return undef;
531             }
532 0 0         my $vnode = @_ ? shift : '';
533 0 0         if (! $vnode) {
534 0           carp "missing VNode name";
535 0           return undef;
536             }
537 0           my $cmd = "DESTROY $type LOGIN $vnode";
538 0           $this->_send($cmd);
539 0           my $obj = $this->{xpct};
540 0           my $before = $obj->before();
541 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
542 0           $this->{stream} = {}; # no more getLogin()/getConn()
543 0           $this->{streamPtr} = 0;
544 0           $this->{streamType} = '';
545 0           return join("\n",@lines);
546             }
547              
548              
549             =item destroyConn($type, $vnode, $addr, $proto, $listen)
550              
551             Destroy (delete) a connection for a Login VNode.
552              
553             Returns output from netutil.
554              
555             Takes the following parameters:
556             $type - VNode type: GLOBAL/PRIVATE
557             $vnode - VNode name/*
558             $addr - IP, hostname of the server, or '*'
559             $proto - protocol name (tcp_ip, win_tcp, ipx, etc.), or '*'
560             $listen - remote server's listen address (generaly 'II'), or '*'
561              
562             =cut
563              
564             sub destroyConn($$$$$) {
565 0     0 1   my $this = shift;
566 0 0         my $type = uc (@_ ? shift : '*');
567 0 0 0       if ($type ne 'GLOBAL' &&
568             $type ne 'PRIVATE') {
569 0           carp "invalid type: $type";
570 0           return undef;
571             }
572 0 0         my $vnode = uc (@_ ? shift : '');
573 0 0         if (! $vnode) {
574 0           carp "missing VNode name";
575 0           return undef;
576             }
577 0 0         my $addr = uc (@_ ? shift : '');
578 0 0         if (! $addr) {
579 0           carp "missing network address";
580 0           return undef;
581             }
582 0 0         my $proto = @_ ? shift : '';
583 0 0         if (! $proto) {
584 0           carp "missing network protocol";
585 0           return undef;
586             }
587 0 0         my $listen = uc(@_ ? shift : '');
588 0 0         if (! $listen) {
589 0           carp "missing listen address";
590 0           return undef;
591             }
592 0           my $cmd = "DESTROY $type CONNECTION $vnode $addr $proto $listen";
593 0           $this->_send($cmd);
594 0           my $obj = $this->{xpct};
595 0           my $before = $obj->before();
596 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
597 0           $this->{stream} = {}; # no more getLogin()/getConn()
598 0           $this->{streamPtr} = 0;
599 0           $this->{streamType} = '';
600 0           return join("\n",@lines);
601             }
602              
603              
604             sub _quiesceStopServer($;$ ) {
605 0     0     my $this = shift;
606 0           my $cmd = shift;
607 0 0         my $serverId = @_ ? shift : '';
608 0           $cmd = "$cmd $serverId";
609 0           $this->_send($cmd);
610 0           my $obj = $this->{xpct};
611 0           my $before = $obj->before();
612 0           my @lines = $this->_getCleanArray($cmd,$this->{cmdInject},$before);
613 0           return join("\n",@lines);
614             }
615              
616             =item quiesceServer(;$serverId)
617              
618             Stops IIGCC server gracefully, i.e. after all connections are closed by clients.
619             No more connections are stablished.
620              
621             Takes optional parameter serverId, to specify which server, or '*' for all servers.
622             Default '*' (all).
623              
624             =cut
625              
626             sub quiesceServer($ ) {
627 0     0 1   my $this = shift;
628 0 0         my $serverId = @_ ? shift : '*';
629            
630 0           return $this->_quiesceStopServer('QUIESCE',$serverId);
631             }
632              
633              
634             =item stopServer($)
635              
636             Stops IIGCC server immediatly, breaking all connections.
637              
638             Takes optional parameter serverId, to specify which server, or '*' for all servers.
639             Default '*' (all).
640              
641             =cut
642              
643             sub stopServer(;$ ) {
644 0     0 1   my $this = shift;
645 0 0         my $serverId = @_ ? shift : '*';
646 0           return $this->_quiesceStopServer('STOP',$serverId);
647             }
648              
649             =back
650              
651              
652             =head1 DIAGNOSTICS
653              
654             =over
655              
656             =item C<< Ingres environment variable II_SYSTEM not set >>
657              
658             Ingres environment variables should be set in the user session running
659             this module.
660             II_SYSTEM provides the root install dir (the one before 'ingres' dir).
661             LD_LIBRARY_PATH too. See Ingres RDBMS docs.
662              
663             =item C<< Ingres utility cannot be executed: _COMMAND_FULL_PATH_ >>
664              
665             The Netutil command could not be found or does not permits execution for
666             the current user.
667              
668             =item C<< invalid type: _VNODE_TYPE_ >>
669              
670             Call to a VNode related method should be given a valid VNode type (GLOBAL/PRIVATE),
671             or a wildcard (*), when permitted.
672              
673             =item C<< showLogin() must be previously invoked >>
674              
675             A method call should be preceded by a preparatory call to showLogin().
676             If any call is made to createXxx() or deleteXxx(), (whichever Login or Conn), then showLogin()
677             should be called again.
678              
679             =item C<< showConn() must be previously invoked >>
680              
681             A method call should be preceded by a preparatory call to showConn().
682             If any call is made to createXxx() or deleteXxx(), (whichever Login or Conn), then showConn()
683             should be called again.
684              
685             =item C<< missing VNode name >>
686              
687             VNode name identifying a Login is required for this method.
688              
689             =item C<< missing _PARAMETER_ >>
690              
691             The method requires the mentioned parameter to perform an action.
692              
693             =back
694              
695              
696             =head1 CONFIGURATION AND ENVIRONMENT
697            
698             Requires Ingres environment variables, such as II_SYSTEM and LD_LIBRARY_PATH.
699              
700             See Ingres RDBMS documentation.
701              
702              
703             =head1 DEPENDENCIES
704              
705             L
706              
707              
708             =head1 INCOMPATIBILITIES
709              
710             None reported.
711              
712              
713             =head1 BUGS AND LIMITATIONS
714              
715             No bugs have been reported.
716              
717             Please report any bugs or feature requests to C,
718             or through the web interface at L.
719              
720              
721             =head1 SUPPORT
722              
723             You can find documentation for this module with the perldoc command.
724              
725             perldoc Ingres::Utility::Netutil
726              
727             You can also look for information at:
728              
729             =over 4
730              
731             =item * AnnoCPAN: Annotated CPAN documentation
732              
733             L
734              
735             =item * CPAN Ratings
736              
737             L
738              
739             =item * RT: CPAN's request tracker
740              
741             L
742              
743             =item * Search CPAN
744              
745             L
746              
747             =item * Ingres Documentation
748              
749             L
750              
751             L
752              
753             L
754              
755             =back
756              
757              
758             =head1 ACKNOWLEDGEMENTS
759              
760             Thanks to Computer Associates (CA) for licensing Ingres as
761             open source, and let us hope for Ingres Corp to keep it that way.
762              
763             =head1 AUTHOR
764              
765             Joner Cyrre Worm C<< >>
766              
767              
768             =head1 LICENSE AND COPYRIGHT
769              
770             Copyright (c) 2006, Joner Cyrre Worm C<< >>. All rights reserved.
771              
772             This module is free software; you can redistribute it and/or
773             modify it under the same terms as Perl itself. See L.
774              
775             Ingres is a registered brand of Ingres Corporation.
776              
777              
778             =head1 DISCLAIMER OF WARRANTY
779              
780             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
781             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
782             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
783             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
784             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
785             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
786             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
787             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
788             NECESSARY SERVICING, REPAIR, OR CORRECTION.
789              
790             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
791             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
792             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
793             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
794             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
795             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
796             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
797             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
798             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
799             SUCH DAMAGES.
800              
801             =cut
802              
803             1; # End of Ingres::Utility::Netutil
804             __END__