source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts.pm @ 2459

Last change on this file since 2459 was 2457, checked in by nanardon, 3 years ago

Test svn version

  • Property svn:keywords set to Id Rev
File size: 8.2 KB
Line 
1package LATMOS::Accounts;
2
3use 5.010000;
4use strict;
5use warnings;
6use base qw(Config::IniFiles);
7use LATMOS::Accounts::Bases;
8use LATMOS::Accounts::Synchro;
9use LATMOS::Accounts::SynchAccess;
10use LATMOS::Accounts::Log;
11use LATMOS::Accounts::Acls;
12use LATMOS::Accounts::I18N;
13
14our $VERSION = '6.1.2.0';
15
16binmode(STDOUT, ":utf8");
17binmode(STDERR, ":utf8");
18
19=head1 NAME
20
21LATMOS::Accounts - Core module for LATMOS account management tools
22
23=head1 DESCRITPTION
24
25=cut
26
27# Return the configuration directory according settings:
28#
29sub _configdir {
30   my ($self) = @_;
31   $ENV{LA_CONFIG} ||
32   ($self || {})->{_configdir} ||
33   '/etc/latmos-accounts'
34}
35
36=head1 FUNCTION
37
38=head2 new($configdir, %options)
39
40Instanciate a new LATMOS::Accounts object.
41
42C<$configdir> if defined is the directory containing files to use,
43default to F</etc/latmos-accounts/>.
44
45C<%options> can contains:
46
47=over 4
48
49=item noacl
50
51If true, acls configuration are not load and code act like everything is
52allowed.
53
54This flag is usefull for administrative tools, for which no acl must apply.
55
56=back
57
58=cut
59
60sub new {
61    my ($class, $config, %options) = @_;
62
63    $config ||= _configdir();
64
65    my $configfile = join('/', $config, 'latmos-accounts.ini');
66
67    my $self = Config::IniFiles->new(
68        -file => $configfile,
69        '-default' => '_default_',
70    ) or do {
71        la_log(LA_ERR, 'Can\'t open main config file %s', $configfile);
72        return;
73    };
74
75    $self->{_configdir} = $config;
76    $self->{_loguser} = $options{loguser};
77    bless($self, $class);
78
79    unless ($options{noacl}) {
80        if (-f (my $aclf = join('/', $self->_configdir, 'la-acls.ini'))) {
81            $self->{_acls} = LATMOS::Accounts::Acls->new($aclf) or do {
82                la_log(LA_ERR, 'Cannot load ACL file %s', $aclf);
83                return;
84            };
85        }
86    }
87
88    if (-f (my $allowf = join('/', $self->_configdir, 'la-allowed-values.ini'))) {
89        $self->{_allowed_values} = Config::IniFiles->new(
90            -file => $allowf,
91        ) or do {
92            la_log(LA_ERR, 'Cannot load ALLOWED VALUES %s', $allowf);
93            return;
94        };
95    }
96
97    $self
98}
99
100=head2 list_bases
101
102Return the base list found in config file
103
104=cut
105
106sub list_bases {
107    my ($self) = @_;
108    grep {
109        !m/^_.*_$/ &&
110        !m/^sync:/
111    } $self->Sections
112}
113
114=head2 default_base_name
115
116Return the default base name according config file
117
118=cut
119
120sub default_base_name {
121    my ($self) = @_;
122    $self->val('_default_', 'base', ($self->list_bases)[0]);
123}
124
125=head2 base($basename)
126
127Return a L<LATMOS::Accounts::Base> object over base named $basename
128defined in the config file.
129
130The base is loaded by this function.
131
132=cut
133
134sub base {
135    my ($self, $section) = @_;
136    # this method perform a cache
137
138    my $basename = $section || $self->default_base_name;
139
140    my $base = $self->_load_base($basename) or do {
141        la_log(LA_ERR, "%s didn't load", $basename);
142        return;
143    };
144
145    $base->load or do {
146        la_log(LA_ERR, "%s didn't load", $base->label);
147        return;
148    };
149    $base;
150}
151
152=head2 LogUser
153
154Return the username to use when no user is connected
155
156=cut
157
158sub LogUser {
159    my ( $self, $Login ) = @_;
160
161    my $name = $self->{_loguser} || '@Console';
162
163    if ($Login) {
164        $self->{_loguser} = $Login;
165    }
166
167    return $name;
168}
169
170# do the bad work
171sub _load_base {
172    my ($self, $section) = @_;
173    my $type = $self->val($section, 'type') or return;
174    la_log(LA_DEBUG, "Trying to load base %s", $section);
175
176    my %params = ();
177
178    foreach ( $self->Parameters($section), $self->Parameters('_default_') ) {
179        my ($val) = $self->val($section, $_);
180        $params{ $_ } = $val;
181    }
182 
183    my %defattr = ();
184
185    foreach ( $self->Parameters('_defattr_') ) {
186        my ($val) = $self->val( '_defattr_', $_ );
187        $defattr{ $_ } = $val;
188    }
189
190    $params{monitored} = {};
191    foreach my $item ($self->val($section, 'monitored')) {
192        $params{monitored}{lc($item)} = 1;
193    }
194
195    my $base = LATMOS::Accounts::Bases->new(
196        $type,
197        {
198            params => \%params,
199            label => $section,
200            acls => $self->{_acls},
201            allowed_values => $self->{_allowed_values},
202            configdir => $self->_configdir,
203            la => $self,
204            defattr => { %defattr },
205        },
206    ) or do {
207        la_log(LA_WARN, "Cannot instanciate base $section ($type)");
208        return;
209    };
210}
211
212=head2 list_synchro
213
214List synchronisation setup in L<latmos-accounts.ini>
215
216=cut
217
218sub list_synchro {
219    my ($self) = @_;
220    grep { $_ } map { /^sync:(.*)$/; $1 } $self->Sections
221}
222
223=head2 default_synchro_name
224
225Return de default synchronisation name
226
227=cut
228
229sub default_synchro_name {
230    my ($self) = @_;
231    $self->val('_default_', 'sync');
232}
233
234=head2 default_synchro
235
236Return a reference to default synchronisation object
237
238=cut
239
240sub default_synchro {
241    my ($self, %options) = @_;
242    my $syncname = $self->default_synchro_name or do {
243        la_log(LA_ERR, 'Cannot find default synchro in config');
244        return;
245    };
246    $self->create_synchro($syncname, %options);
247}
248
249=head2 create_synchro($name, %options)
250
251Return a reference to synchronisation object for C<$name> synchronisation.
252
253=cut
254
255sub create_synchro {
256    my ($self, $name, %options) = @_;
257
258    # taking options from config
259    if ($name) {
260        foreach my $param ($self->Parameters("sync:$name")) {
261            if (!defined($options{$param})) {
262                my @args = $self->val("sync:$name", $param);
263                $options{$param} = ($args[1] || $param eq 'to')
264                    ? [ @args ]
265                    : $args[0];
266            }
267        }
268    }
269
270    my $labfrom = $options{from} ? $self->base($options{from}) : $self->base;
271
272    my @labto =
273        grep { $_ }
274        map { $self->base($_) }
275        @{ $options{to} || []}
276        or do {
277        la_log(LA_ERR, "No destination base load in this synchro");
278        return;
279    };
280
281    my $sync = LATMOS::Accounts::Synchro->new(
282        $labfrom, [ @labto ],
283        state_dir => ($self->val('_default_', 'state_dir') || undef),
284        %options,
285        name => $name,
286    );
287}
288
289sub _sync_from_name {
290    my ($self, $syncname) = @_;
291    return if (!$syncname);
292    $self->val("sync:$syncname", 'from', $self->default_base_name);
293}
294
295=head2 sync_access($name, %options)
296
297Return a L<LATMOS::Accounts::SynchAccess> object over C<$name> synchronisation.
298
299=cut
300
301sub sync_access {
302    my ($self, $name, %options) = @_;
303
304    my @obases;
305    if ($name) {
306        @obases =
307        (map { $self->base($_) } ($self->_sync_from_name($name), $self->val("sync:$name", 'to')));
308    } elsif(@{ $options{bases} || []}) {
309        @obases = map { $self->base($_) } @{ $options{bases} || []};
310    } elsif (my $sname = $self->default_synchro_name) {
311        @obases = (map { $self->base($_) }
312            ($self->_sync_from_name($sname), $self->val("sync:$sname", 'to'))
313        );
314    }
315
316    if (!@obases) {
317        la_log(LA_ERR, "Cannot load any bases for syncronised action");
318        return;
319    }
320
321    la_log(LA_DEBUG, "Load databases: %s", join(', ', map { $_->label } @obases));
322
323    LATMOS::Accounts::SynchAccess->new([ @obases ]);
324}
325
326=head2 call_batch_sync
327
328Send signal to L<la-sync-manager> daemon to synchronize bases.
329
330=cut
331
332sub call_batch_sync {
333    my ($self) = @_;
334    if (my $sd = $self->val('_default_', 'state_dir')) {
335        if (open(my $fh, '<', $sd . '/sync-manager.pid')) {
336            my $pid = <$fh> || '';
337            chomp($pid);
338            close($fh);
339            if ($pid && kill 1, $pid) {
340                return 1; # \o/ we succeed
341            } else {
342                la_log(LA_ERR, "Can send signal -1 to la-sync-manager (pid: %s, %s)",
343                    $pid || 'none', $!);
344                return;
345            }
346        } else {
347            la_log(LA_ERR, 'Cannot open la-sync-manager pid file');
348            return;
349        }
350    } else {
351        la_log(LA_WARN, "No statedir setup, cannot find la-sync-manager pid file");
352        return;
353    }
354}
355
3561;
357
358__END__
359
360=head1 AUTHOR
361
362Thauvin Olivier, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
363
364=head1 COPYRIGHT AND LICENSE
365
366Copyright (C) 2009, 2010, 2011, 2012 by Thauvin Olivier
367
368This library is free software; you can redistribute it and/or modify
369it under the same terms as Perl itself, either Perl version 5.10.0 or,
370at your option, any later version of Perl 5 you may have available.
371
372=cut
Note: See TracBrowser for help on using the repository browser.