File Coverage

blib/lib/Metabrik/Client/Openssh.pm
Criterion Covered Total %
statement 9 89 10.1
branch 0 40 0.0
condition 0 12 0.0
subroutine 3 10 30.0
pod 2 7 28.5
total 14 158 8.8


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # client::openssh Brik
5             #
6             package Metabrik::Client::Openssh;
7 1     1   847 use strict;
  1         3  
  1         30  
8 1     1   6 use warnings;
  1         3  
  1         30  
9              
10 1     1   5 use base qw(Metabrik);
  1         2  
  1         1027  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable ssh) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             hostname => [ qw(hostname) ],
20             port => [ qw(integer) ],
21             username => [ qw(username) ],
22             password => [ qw(password) ],
23             pid => [ qw(master_pid) ],
24             slave_pids => [ qw(slave_pids) ],
25             forward_agent => [ qw(0|1) ],
26             ssh => [ qw(INTERNAL) ],
27             },
28             attributes_default => {
29             hostname => 'localhost',
30             port => 22,
31             forward_agent => 1,
32             slave_pids => {},
33             },
34             commands => {
35             connect => [ qw(hostname|OPTIONAL port|OPTIONAL username|OPTIONAL password|OPTIONAL) ],
36             is_connected => [ ],
37             disconnect => [ ],
38             open_tunnel => [ qw(hostname port) ],
39             close_tunnel => [ qw(hostname port) ],
40             },
41             require_modules => {
42             'Net::OpenSSH' => [ ],
43             'Metabrik::System::Process' => [ ],
44             },
45             };
46             }
47              
48             sub is_connected {
49 0     0 0   my $self = shift;
50              
51 0 0         if (defined($self->ssh)) {
52 0           return 1;
53             }
54              
55 0           return 0;
56             }
57              
58             sub connect {
59 0     0 0   my $self = shift;
60 0           my ($hostname, $port, $username, $password) = @_;
61              
62 0 0         if ($self->is_connected) {
63 0           return $self->log->verbose("connect: already connected");
64             }
65              
66 0   0       $hostname ||= $self->hostname;
67 0   0       $port ||= $self->port;
68 0   0       $username ||= $self->username;
69 0   0       $password ||= $self->password;
70              
71 0           my %opts = (
72             timeout => 5,
73             );
74 0 0         if (length($username)) {
75 0           $opts{user} = $username;
76             }
77 0 0         if (length($password)) {
78 0           $opts{password} = $password;
79             }
80 0 0         if ($port) {
81 0           $opts{port} = $port;
82             }
83 0 0         if ($self->forward_agent) {
84 0           $opts{forward_agent} = 1;
85             }
86              
87 0           my $ssh = Net::OpenSSH->new($hostname, %opts);
88 0 0         if ($ssh->error) {
89 0           return $self->log->error("connect: cannot connect to [$hostname]:$port: ".$ssh->error);
90             }
91              
92 0           $self->log->verbose("connect: connected to [$hostname]:$port");
93              
94 0           $self->pid($ssh->get_master_pid);
95              
96 0           return $self->ssh($ssh);
97             }
98              
99             sub disconnect {
100 0     0 0   my $self = shift;
101              
102 0 0         if (! $self->is_connected) {
103 0           return $self->log->verbose("disconnect: not connected");
104             }
105              
106 0           my $ssh = $self->ssh;
107              
108 0 0         my $sp = Metabrik::System::Process->new_from_brik_init($self) or return;
109              
110 0           my @pids = ( $self->pid, keys %{$self->slave_pids} );
  0            
111 0           for (@pids) {
112 0           $sp->kill($_);
113             }
114 0           $self->pid(undef);
115 0           $self->slave_pids({});
116 0           $self->ssh(undef);
117              
118 0           return 1;
119             }
120              
121             sub open_tunnel {
122 0     0 0   my $self = shift;
123 0           my ($hostname, $port) = @_;
124              
125 0 0         if (! $self->is_connected) {
126 0           return $self->log->verbose("open_tunnel: not connected");
127             }
128 0 0         $self->brik_help_run_undef_arg('open_tunnel', $hostname) or return;
129 0 0         $self->brik_help_run_undef_arg('open_tunnel', $port) or return;
130              
131 0           my $ssh = $self->ssh;
132 0           my $slave_pids = $self->slave_pids;
133              
134 0           my ($tunnel, $pid) = $ssh->open_tunnel({}, $hostname, $port);
135 0 0         if ($ssh->error) {
136 0           return $self->log->error("open_tunnel: failed for [$hostname]:$port: ".$ssh->error);
137             }
138              
139 0           $tunnel->blocking(0);
140 0           $tunnel->autoflush(1);
141              
142 0           $slave_pids->{$pid} = { uid => "$hostname:$port" };
143              
144 0           return $tunnel;
145             }
146              
147             sub close_tunnel {
148 0     0 0   my $self = shift;
149 0           my ($hostname, $port) = @_;
150              
151 0 0         if (! $self->is_connected) {
152 0           return $self->log->verbose("close_tunnel: not connected");
153             }
154 0 0         $self->brik_help_run_undef_arg('close_tunnel', $hostname) or return;
155 0 0         $self->brik_help_run_undef_arg('close_tunnel', $port) or return;
156              
157 0           my $ssh = $self->ssh;
158 0           my $slave_pids = $self->slave_pids;
159              
160 0 0         my $sp = Metabrik::System::Process->new_from_brik_init($self) or return;
161              
162 0           my $found = 0;
163 0           for my $k (keys %$slave_pids) {
164 0 0         if ($slave_pids->{$k}{uid} eq "$hostname:$port") {
165 0           $sp->kill($k);
166 0           delete $slave_pids->{$k};
167 0           $found++;
168 0           last;
169             }
170             }
171              
172 0 0         if (! $found) {
173 0           $self->log->verbose("close_tunnel: tunnel [$hostname]:$port not connected");
174             }
175              
176 0           return 1;
177             }
178              
179             sub brik_fini {
180 0     0 1   my $self = shift;
181              
182 0           my $ssh = $self->ssh;
183 0 0         if (defined($ssh)) {
184 0           $ssh->disconnect;
185             }
186              
187 0           return 1;
188             }
189              
190             1;
191              
192             __END__