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

Last change on this file since 2260 was 2260, checked in by nanardon, 5 years ago

Allow to set in config monitored attributes

  • Property svn:keywords set to Id Rev
File size: 7.7 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.0.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    bless($self, $class);
77
78    unless ($options{noacl}) {
79        if (-f (my $aclf = join('/', $self->_configdir, 'la-acls.ini'))) {
80            $self->{_acls} = LATMOS::Accounts::Acls->new($aclf) or do {
81                la_log(LA_ERR, 'Cannot load ACL file %s', $aclf);
82                return;
83            };
84        }
85    }
86
87    if (-f (my $allowf = join('/', $self->_configdir, 'la-allowed-values.ini'))) {
88        $self->{_allowed_values} = Config::IniFiles->new(
89            -file => $allowf,
90        ) or do {
91            la_log(LA_ERR, 'Cannot load ALLOWED VALUES %s', $allowf);
92            return;
93        };
94    }
95
96    $self
97}
98
99=head2 list_bases
100
101Return the base list found in config file
102
103=cut
104
105sub list_bases {
106    my ($self) = @_;
107    grep {
108        !m/^_.*_$/ &&
109        !m/^sync:/
110    } $self->Sections
111}
112
113=head2 default_base_name
114
115Return the default base name according config file
116
117=cut
118
119sub default_base_name {
120    my ($self) = @_;
121    $self->val('_default_', 'base', ($self->list_bases)[0]);
122}
123
124=head2 base($basename)
125
126Return a L<LATMOS::Accounts::Base> object over base named $basename
127defined in the config file.
128
129The base is loaded by this function.
130
131=cut
132
133sub base {
134    my ($self, $section) = @_;
135    # this method perform a cache
136    my $base = $self->_load_base($section || $self->default_base_name);
137
138    $base->load or do {
139        la_log(LA_ERR, "%s didn't load", $base->label);
140        return;
141    };
142    $base;
143}
144
145# do the bad work
146sub _load_base {
147    my ($self, $section) = @_;
148    my $type = $self->val($section, 'type') or return;
149    la_log(LA_DEBUG, "Trying to load base %s", $section);
150
151    my %params =
152        map { $_ => ($self->val($section, $_)) }
153        ($self->Parameters($section), $self->Parameters('_default_'));
154 
155    my %defattr =
156        map { $_ => ($self->val('_defattr_', $_)) }
157        $self->Parameters('_defattr_');
158
159    $params{monitored} = {};
160    foreach my $item ($self->val($section, 'monitored')) {
161        $params{monitored}{lc($item)} = 1;
162    }
163
164    my $base = LATMOS::Accounts::Bases->new(
165        $type,
166        {
167            params => \%params,
168            label => $section,
169            acls => $self->{_acls},
170            allowed_values => $self->{_allowed_values},
171            configdir => $self->_configdir,
172            la => $self,
173            defattr => { %defattr },
174        },
175    ) or do {
176        la_log(LA_WARN, "Cannot instanciate base $section ($type)");
177        return;
178    };
179}
180
181=head2 list_synchro
182
183List synchronisation setup in L<latmos-accounts.ini>
184
185=cut
186
187sub list_synchro {
188    my ($self) = @_;
189    grep { $_ } map { /^sync:(.*)$/; $1 } $self->Sections
190}
191
192=head2 default_synchro_name
193
194Return de default synchronisation name
195
196=cut
197
198sub default_synchro_name {
199    my ($self) = @_;
200    $self->val('_default_', 'sync');
201}
202
203=head2 default_synchro
204
205Return a reference to default synchronisation object
206
207=cut
208
209sub default_synchro {
210    my ($self, %options) = @_;
211    my $syncname = $self->default_synchro_name or do {
212        la_log(LA_ERR, 'Cannot find default synchro in config');
213        return;
214    };
215    $self->create_synchro($syncname, %options);
216}
217
218=head2 create_synchro($name, %options)
219
220Return a reference to synchronisation object for C<$name> synchronisation.
221
222=cut
223
224sub create_synchro {
225    my ($self, $name, %options) = @_;
226
227    # taking options from config
228    if ($name) {
229        foreach my $param ($self->Parameters("sync:$name")) {
230            if (!defined($options{$param})) {
231                my @args = $self->val("sync:$name", $param);
232                $options{$param} = ($args[1] || $param eq 'to')
233                    ? [ @args ]
234                    : $args[0];
235            }
236        }
237    }
238
239    my $labfrom = $options{from} ? $self->base($options{from}) : $self->base;
240
241    my @labto =
242        grep { $_ }
243        map { $self->base($_) }
244        @{ $options{to} || []}
245        or do {
246        la_log(LA_ERR, "No destination base load in this synchro");
247        return;
248    };
249
250    my $sync = LATMOS::Accounts::Synchro->new(
251        $labfrom, [ @labto ],
252        state_dir => ($self->val('_default_', 'state_dir') || undef),
253        %options,
254        name => $name,
255    );
256}
257
258sub _sync_from_name {
259    my ($self, $syncname) = @_;
260    return if (!$syncname);
261    $self->val("sync:$syncname", 'from', $self->default_base_name);
262}
263
264=head2 sync_access($name, %options)
265
266Return a L<LATMOS::Accounts::SynchAccess> object over C<$name> synchronisation.
267
268=cut
269
270sub sync_access {
271    my ($self, $name, %options) = @_;
272
273    my @obases;
274    if ($name) {
275        @obases =
276        (map { $self->base($_) } ($self->_sync_from_name($name), $self->val("sync:$name", 'to')));
277    } elsif(@{ $options{bases} || []}) {
278        @obases = map { $self->base($_) } @{ $options{bases} || []};
279    } elsif (my $sname = $self->default_synchro_name) {
280        @obases = (map { $self->base($_) }
281            ($self->_sync_from_name($sname), $self->val("sync:$sname", 'to'))
282        );
283    }
284
285    if (!@obases) {
286        la_log(LA_ERR, "Cannot load any bases for syncronised action");
287        return;
288    }
289
290    la_log(LA_DEBUG, "Load databases: %s", join(', ', map { $_->label } @obases));
291
292    LATMOS::Accounts::SynchAccess->new([ @obases ]);
293}
294
295=head2 call_batch_sync
296
297Send signal to L<la-sync-manager> daemon to synchronize bases.
298
299=cut
300
301sub call_batch_sync {
302    my ($self) = @_;
303    if (my $sd = $self->val('_default_', 'state_dir')) {
304        if (open(my $fh, '<', $sd . '/sync-manager.pid')) {
305            my $pid = <$fh> || '';
306            chomp($pid);
307            close($fh);
308            if ($pid && kill 1, $pid) {
309                return 1; # \o/ we succeed
310            } else {
311                la_log(LA_ERR, "Can send signal -1 to la-sync-manager (pid: %s, %s)",
312                    $pid || 'none', $!);
313                return;
314            }
315        } else {
316            la_log(LA_ERR, 'Cannot open la-sync-manager pid file');
317            return;
318        }
319    } else {
320        la_log(LA_WARN, "No statedir setup, cannot find la-sync-manager pid file");
321        return;
322    }
323}
324
3251;
326
327__END__
328
329=head1 AUTHOR
330
331Thauvin Olivier, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
332
333=head1 COPYRIGHT AND LICENSE
334
335Copyright (C) 2009, 2010, 2011, 2012 by Thauvin Olivier
336
337This library is free software; you can redistribute it and/or modify
338it under the same terms as Perl itself, either Perl version 5.10.0 or,
339at your option, any later version of Perl 5 you may have available.
340
341=cut
Note: See TracBrowser for help on using the repository browser.