source: obs_notify_generic/obs_notify_generic.pm@ 1189

Last change on this file since 1189 was 1188, checked in by joergs, on Jun 17, 2015 at 6:03:16 PM

run actions as daemon, to not block obs

File size: 6.9 KB
Line 
1#
2# obs_notify_generic
3#
4# Copyright (c) 2015 Jörg Steffens
5#
6# inspired of
7# https://build.opensuse.org/package/show/isv:B1-Systems:OBS/obs-notfy_email
8# Copyright (c) 2014 Christian Schneemann, B1 Systems GmbH
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License version 2 as
12# published by the Free Software Foundation.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program (see the file COPYING); if not, write to the
21# Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23#
24################################################################
25
26package obs_notify_generic;
27
28use strict;
29use warnings;
30
31#use BSConfig;
32use lib "/usr/lib/obs/server/plugins/";
33use obs_notify_generic_config;
34use Data::Dumper;
35use IPC::Run;
36use Proc::Daemon;
37use Time::Piece;
38
39#use XML::Simple;
40
41# stdout goes to /srv/obs/log/src_server.log
42
43sub new
44{
45 my $self = {
46 'cfg' => ${obs_notify_generic_config::cfg},
47 'logfile' => ${obs_notify_generic_config::logfile},
48 };
49 if ( not $self->{'logfile'} ) {
50 $self->{'logfile'} = "/srv/obs/log/notify_generic.log";
51 #$self->{'logfile'} = "/tmp/notify_generic.log";
52 }
53 bless $self, shift;
54 return $self;
55}
56
57sub notify
58{
59 my ( $self, $type, $paramRef ) = @_;
60
61 $type = "UNKNOWN" unless $type;
62
63 my $cfg_type;
64 if ( $self->{'cfg'}->{$type} ) {
65 $cfg_type = $self->{'cfg'}->{$type};
66 } elsif ( $self->{'cfg'}->{'UNKNOWN'} ) {
67 $cfg_type = $self->{'cfg'}->{'UNKNOWN'};
68 }
69
70 for my $entry ( @{$cfg_type} ) {
71 my $match = 1;
72 foreach my $key ( keys %{ $entry->{'filter'} } ) {
73 my $value = $entry->{'filter'}->{$key};
74
75 #print "key: $key\n";
76 #print "value: $value\n";
77 if ( not( exists($paramRef->{$key}) ) ) {
78 error_msg( "$type (". Data::Dumper->new( [$paramRef] )->Indent(0)->Dump ."): filter for '". $key ."' is invalid" );
79 $match = 0;
80 # exit loop
81 last;
82 } elsif ( not( $paramRef->{$key} =~ /$value/ ) ) {
83 $match = 0;
84 }
85 }
86 if ($match) {
87 my $extra = undef;
88 if ( $entry->{'action'} ) {
89
90 #print $entry->{'action'}, "\n";
91 if ( $paramRef->{'project'} ) {
92 my $project = $paramRef->{'project'};
93 $project =~ s/:/:\//g;
94 $paramRef->{'project_path'}="/srv/obs/repos/" . $project;
95 }
96 # create regex,
97 # test against longest string first to avoid partial replacement ($repo, $repository)
98 my $check = join '|', sort {
99 length($b) <=> length($a)
100 } keys %{$paramRef};
101 my $action = $entry->{'action'};
102 $action =~ s/\$($check)/$paramRef->{$1}/g;
103
104 $extra = {
105 'action_template' => $entry->{'action'},
106 'action' => $action,
107 };
108
109 #$self->run_wait( $action, $extra );
110 $self->run_daemon( $action, $extra );
111 }
112 if ( $entry->{'log'} ) {
113 $self->log( $type, $paramRef, $extra );
114 }
115 } else {
116
117 #print "no match\n";
118 }
119 }
120}
121
122sub run_wait
123{
124 my ( $self, $action, $extra ) = @_;
125
126 #print $action, "\n";
127 my $in = undef;
128 my $out;
129 my $err;
130 my $rc;
131 eval {
132 my $process =
133 IPC::Run::start( [ "sh", "--login", "-c", "HOME=/usr/lib/obs $action", "2>&1" ],
134 \$in, \$out, \$err );
135 $process->finish();
136 $rc = $process->result(0);
137 };
138 if ($@) {
139
140 #print "eval: ", $@;
141 $out = join( "\n", $@ );
142 $rc = 127;
143 }
144
145 #print "rc: ", $rc, "\n";
146 #print "out: ", $out, "\n";
147 chomp($out);
148
149 #print "err: ", $err, "\n";
150 $extra->{'returncode'} = $rc;
151 $extra->{'output'} = $out;
152}
153
154sub run_daemon
155{
156 my ( $self, $action, $extra ) = @_;
157
158 my $daemon=Proc::Daemon->new();
159 my $pid=$daemon->Init( {
160 exec_command => "date --rfc-3339=seconds; echo '$action'; $action",
161 child_STDOUT => "+>>" . $self->{'logfile'} . ".out.log",
162 child_STDERR => "+>>" . $self->{'logfile'} . ".out.log",
163 } );
164
165 #print $daemon->Status($pid);
166
167 $extra->{'pid'} = $pid;
168}
169
170sub error_msg
171{
172 print "FAILED: ", join( " ", @_ ) . "\n";
173}
174
175sub log
176{
177 my ( $self, $type, $paramRef, $extra ) = @_;
178
179 my $fh;
180 my $file_opened = 0;
181
182 if ( $self->{'logfile'} eq "STDOUT" ) {
183 $fh = *STDOUT;
184 } else {
185
186 if ( open( $fh, '>>', $self->{'logfile'} ) ) {
187 $file_opened = 1;
188 } else {
189 error_msg( "failed to open log file " . $self->{'logfile'} );
190 return 1;
191 }
192 }
193
194 print $fh localtime->strftime("%Y%m%d %H%M%S"), " TYPE=$type";
195
196 if ($extra) {
197 print $fh "\n";
198 print $fh Dumper( { 'param' => $paramRef, 'extra' => $extra } );
199 print $fh "\n";
200 } else {
201 print $fh " ";
202 print $fh Data::Dumper->new( [$paramRef] )->Indent(0)->Dump;
203 print $fh "\n";
204 }
205 if ($file_opened) {
206 close $fh;
207 }
208}
209
210# sub notify_setting {
211# my ($self, $project) = @_;
212# my ($xml, $attributes);
213#
214# $xml = $self->call_obs_api("/source/$project/_attribute/$notify_email_config::notify_attr");
215#
216# if ($xml) {
217# $attributes = XMLin($xml, KeyAttr => { }, ForceArray =>0);
218# }
219#
220# return $attributes->{attribute}->{'value'} || 0;
221# }
222
223# sub unique {
224# my ($self, @a) = @_;
225# return keys %{{ map { $_ => 1 } @a }};
226# }
227
228# sub get_obs_maintainer {
229# my ($self, $project, $package) = @_;
230# my ($request, @persons, $xml, $meta);
231# if ($package) {
232# $request = "/source/$project/$package/_meta";
233# $xml = $self->call_obs_api($request);
234# $meta = XMLin($xml, KeyAttr => {}, ForceArray => [ 'person'] );
235#
236# @persons = grep { $_->{'role'} =~ /$notify_email_config::notified_roles/i } @{$meta->{person}};
237# }
238# $request = "/source/$project/_meta";
239#
240# $xml = $self->call_obs_api($request);
241# $meta = XMLin($xml, KeyAttr => {}, ForceArray => ['person'] );
242#
243# push @persons, grep { $_->{'role'} =~ /$notify_email_config::notified_roles/i } @{$meta->{person}};
244#
245# @persons = $self->unique(map{ $_->{'userid'} } @persons);
246#
247# return @persons;
248# }
249#
250# sub get_obs_email {
251# my ($self, $user) = @_;
252#
253# my $xml = $self->call_obs_api("/person/$user");
254#
255# $xml = XMLin($xml, KeyAttr => {}, ForceArray => 0);
256#
257# return $xml->{'email'};
258# }
259
260# sub call_obs_api {
261# my ($self, $api_call) = @_;
262# return `$notify_email_config::curl_binary -k -s -u $notify_email_config::api_user:$notify_email_config::api_pass $notify_email_config::api_url/$api_call`;
263# }
264
2651;
Note: See TracBrowser for help on using the repository browser.