# Agent.pm: Class Used for Objects to Interface with a Remote Agent package RDA::Agent::Remote; # $Id: Remote.pm,v 1.4 2015/10/19 05:16:43 RDA Exp $ # ARCS: $Header: /home/cvs/cvs/RDA_8/src/scripting/lib/RDA/Agent/Remote.pm,v 1.4 2015/10/19 05:16:43 RDA Exp $ # # Change History # 20151019 MSC Add driver type control. =head1 NAME RDA::Agent::Remote - Class Used for Objects to Interface with a Remote Agent =head1 SYNOPSIS require RDA::Agent::Remote; =head1 DESCRIPTION The objects of the C class are used to interface with a remote agent. It is a subclass of L. The following methods are available: =cut use strict; BEGIN { use Exporter; use RDA::Text qw(get_string); use RDA::Agent; use RDA::Driver::Agent; use RDA::Handle::Agent; use RDA::Local::Unix; use RDA::Object::Message; use RDA::Object::Rda qw($CREATE $FIL_PERMS); } # Define the global public variables use vars qw($STRINGS $VERSION @ISA); $VERSION = sprintf('%d.%02d', q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/); @ISA = qw(RDA::Agent Exporter); # Define the global private constants # Define the global private variables # Report the package version sub Version { return $VERSION; } =head2 S<$h = RDA::Agent::Remote-Enew($agt,$oid)> The object constructor. This method enables you to specify the reference to the agent object and the control object identifier as parameters. C is represented by a blessed hash reference. The following special keys are used: =over 16 =item S< B<'brk' > > Treatment break request =item S< B<'drv' > > Reference to the communication driver object =item S< B<'ifh' > > Communication channel input file handle =item S< B<'loc' > > Do local usage tracking =item S< B<'lvl' > > Trace level =item S< B<'nod' > > Node name =item S< B<'ofh' > > Communication channel output file handle =item S< B<'oid' > > Agent identifier =item S< B<'par' > > Reference to the parent agent =item S< B<'pid' > > Execution agent process identifier =item S< B<'pre' > > Trace prefix =item S< B<'upd' > > Usage update command =item S< B<'use' > > Agent usage overview =item S< B<'_kil'> > Kill indicator =item S< B<'_ses'> > Reference to the session object =back Internal keys are prefixed by an underscore. =cut sub new { my ($cls, $agt, $oid) = @_; # Create the remote control agent and return its reference return bless { brk => 'AGENT.EXIT', lvl => $agt->{'lvl'}, nod => uc($oid), oid => $oid, par => $agt, pre => "C:$oid", upd => 'AGENT.GET_USAGE', use => {}, _kil => 0, }, ref($cls) || $cls; } =head2 S<$h-Edelete_object> This method deletes the control agent. =cut sub delete_object { $_[0]->close_session; $_[0]->SUPER::delete_object; return; } =head2 S<$h-Estart($def,$att)> This method starts the remote agent and returns a reference to the initialization response message. =cut sub start ## no critic (Complex) { my ($slf, $def, $att) = @_; my ($agt, $drv, $dsc, $oid, $opt, $req, $rsp, $val); # Determine the usage directives if ($att->{'no_usage'}) { delete($slf->{'upd'}); $slf->{'loc'} = 1; } elsif ($val = delete($att->{'usage_request'})) { $slf->{'upd'} = $val; } # Start the child process $agt = $slf->{'par'}; $oid = $slf->{'oid'}; $dsc = {opt => ["-XAgent,AGENT,$oid"], trc => $agt->is_slave ? '>&=2' : '>&=1', }; unshift(@{$dsc->{'opt'}}, '-u'.$agt->{'str'}) if $agt->{'str'}; unshift(@{$dsc->{'opt'}}, '-t'.$agt->{'lvl'}) if $agt->{'lvl'}; $opt = q{}; $opt .= 'b' unless $agt->{'bkp'}; $opt .= 'n' if $agt->{'new'}; $opt .= 'q' if $agt->{'out'}; $opt .= 'v' if $agt->{'vrb'}; $opt .= 'y' if $agt->{'yes'}; unshift(@{$dsc->{'opt'}}, "-$opt") if $opt; $dsc->{'cmd'} = (!exists($att->{'rda'})) ? [$agt->{'cfg'}->get_value('T_SELF')] : (!exists($att->{'perl'})) ? [RDA::Local::Unix->cat_file($att->{'rda'}, 'sdci.sh')] : $att->{'taint'} ? [$att->{'perl'}, '-T', RDA::Local::Unix->cat_file($att->{'rda'}, 'sdci.pl')] : [$att->{'perl'}, RDA::Local::Unix->cat_file($att->{'rda'}, 'sdci.pl')]; $dsc->{'ses'} = $slf->{'_ses'} = $agt->get_remote->add_remote($slf->{'nod'}, delete($att->{'host'}), delete($att->{'user'}), delete($att->{'password'})); $slf->{'_ses'}->set_type($val) if defined($val = $att->{'driver'}); $dsc->{'wrk'} = $att->{'work'} if exists($att->{'work'}); eval { $slf->{'ifh'} = $slf->{'ofh'} = $val = RDA::Handle::Agent->new($dsc); $slf->{'pid'} = $val->getinfo('pid') or die get_string('NOT_STARTED', $oid); }; if ($@ =~ m/^exec_command: Cannot (exec|spawn) /) { syswrite(STDOUT, $@, length($@)); exit(0); } $agt->add_error($slf->{'_ses'}->get_message, $@)->abort if $@; # Initialize the agent $agt->add_changes($slf->{'nod'}); $slf->{'drv'} = $drv = RDA::Driver::Agent->new($slf, $slf->{'ifh'}, $slf->{'ofh'}); $req = RDA::Object::Message->new('AGENT.INIT', %{$att}); $req->set_id($agt); $req->add_lines($agt->get_collector->get_access->get_input($val)) if defined($val = delete($att->{'transfer'})); $rsp = $drv->exec_request($req); # Stop the agent in case of initialisation error if ($rsp->is_error($agt, get_string('ERR_START', $oid))) { $slf->kill_agent; $slf->merge_usage; $agt->trace(get_string('Stopped', $oid)) unless $slf->{'lvl'} < 10; ## no critic (Unless) $slf->delete_object; $agt->abort; } # Modify agent behavior $slf->{'_kil'} = 1 if $rsp->set_value('no_exit'); delete($agt->{'_chg'}->{uc($oid)}) if $rsp->set_value('no_proxy'); $drv->set_eol($val) if defined($val = $rsp->set_value('eol')); if ($rsp->set_value('no_usage')) { delete($slf->{'upd'}); $slf->{'loc'} = 1; } elsif ($val = $rsp->set_value('usage_request')) { $slf->{'upd'} = $val; } $slf->{'_ses'}->set_family($rsp->get_first('family')); # Return a reference to the response message return $rsp; } 1; __END__ =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, L, L, L =head1 COPYRIGHT NOTICE Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. =head1 TRADEMARK NOTICE Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. =cut