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

Last change on this file since 2204 was 2202, checked in by latmossys, 5 years ago
  • 6.0.0
  • Property svn:keywords set to Id Rev
File size: 7.6 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    $self->_load_base($section || $self->default_base_name);
137}
138
139# do the bad work
140sub _load_base {
141    my ($self, $section) = @_;
142    my $type = $self->val($section, 'type') or return;
143    la_log(LA_DEBUG, "Trying to load base %s", $section);
144
145    my %params =
146        map { $_ => ($self->val($section, $_)) }
147        ($self->Parameters($section), $self->Parameters('_default_'));
148 
149    my %defattr =
150        map { $_ => ($self->val('_defattr_', $_)) }
151        $self->Parameters('_defattr_');
152
153    my $base = LATMOS::Accounts::Bases->new(
154        $type,
155        {
156            params => \%params,
157            label => $section,
158            acls => $self->{_acls},
159            allowed_values => $self->{_allowed_values},
160            configdir => $self->_configdir,
161            la => $self,
162            defattr => { %defattr },
163        },
164    ) or do {
165        la_log(LA_WARN, "Cannot instanciate base $section ($type)");
166        return;
167    };
168    $base->load or do {
169        la_log(LA_ERR, "%s didn't load", $base->label);
170        return;
171    };
172    $base;
173}
174
175=head2 list_synchro
176
177List synchronisation setup in L<latmos-accounts.ini>
178
179=cut
180
181sub list_synchro {
182    my ($self) = @_;
183    grep { $_ } map { /^sync:(.*)$/; $1 } $self->Sections
184}
185
186=head2 default_synchro_name
187
188Return de default synchronisation name
189
190=cut
191
192sub default_synchro_name {
193    my ($self) = @_;
194    $self->val('_default_', 'sync');
195}
196
197=head2 default_synchro
198
199Return a reference to default synchronisation object
200
201=cut
202
203sub default_synchro {
204    my ($self, %options) = @_;
205    my $syncname = $self->default_synchro_name or do {
206        la_log(LA_ERR, 'Cannot find default synchro in config');
207        return;
208    };
209    $self->create_synchro($syncname, %options);
210}
211
212=head2 create_synchro($name, %options)
213
214Return a reference to synchronisation object for C<$name> synchronisation.
215
216=cut
217
218sub create_synchro {
219    my ($self, $name, %options) = @_;
220
221    # taking options from config
222    if ($name) {
223        foreach my $param ($self->Parameters("sync:$name")) {
224            if (!defined($options{$param})) {
225                my @args = $self->val("sync:$name", $param);
226                $options{$param} = ($args[1] || $param eq 'to')
227                    ? [ @args ]
228                    : $args[0];
229            }
230        }
231    }
232
233    my $labfrom = $options{from} ? $self->base($options{from}) : $self->base;
234
235    my @labto =
236        grep { $_ }
237        map { $self->base($_) }
238        @{ $options{to} || []}
239        or do {
240        la_log(LA_ERR, "No destination base load in this synchro");
241        return;
242    };
243
244    my $sync = LATMOS::Accounts::Synchro->new(
245        $labfrom, [ @labto ],
246        state_dir => ($self->val('_default_', 'state_dir') || undef),
247        %options,
248        name => $name,
249    );
250}
251
252sub _sync_from_name {
253    my ($self, $syncname) = @_;
254    return if (!$syncname);
255    $self->val("sync:$syncname", 'from', $self->default_base_name);
256}
257
258=head2 sync_access($name, %options)
259
260Return a L<LATMOS::Accounts::SynchAccess> object over C<$name> synchronisation.
261
262=cut
263
264sub sync_access {
265    my ($self, $name, %options) = @_;
266
267    my @obases;
268    if ($name) {
269        @obases =
270        (map { $self->base($_) } ($self->_sync_from_name($name), $self->val("sync:$name", 'to')));
271    } elsif(@{ $options{bases} || []}) {
272        @obases = map { $self->base($_) } @{ $options{bases} || []};
273    } elsif (my $sname = $self->default_synchro_name) {
274        @obases = (map { $self->base($_) }
275            ($self->_sync_from_name($sname), $self->val("sync:$sname", 'to'))
276        );
277    }
278
279    if (!@obases) {
280        la_log(LA_ERR, "Cannot load any bases for syncronised action");
281        return;
282    }
283
284    la_log(LA_DEBUG, "Load databases: %s", join(', ', map { $_->label } @obases));
285
286    LATMOS::Accounts::SynchAccess->new([ @obases ]);
287}
288
289=head2 call_batch_sync
290
291Send signal to L<la-sync-manager> daemon to synchronize bases.
292
293=cut
294
295sub call_batch_sync {
296    my ($self) = @_;
297    if (my $sd = $self->val('_default_', 'state_dir')) {
298        if (open(my $fh, '<', $sd . '/sync-manager.pid')) {
299            my $pid = <$fh> || '';
300            chomp($pid);
301            close($fh);
302            if ($pid && kill 1, $pid) {
303                return 1; # \o/ we succeed
304            } else {
305                la_log(LA_ERR, "Can send signal -1 to la-sync-manager (pid: %s, %s)",
306                    $pid || 'none', $!);
307                return;
308            }
309        } else {
310            la_log(LA_ERR, 'Cannot open la-sync-manager pid file');
311            return;
312        }
313    } else {
314        la_log(LA_WARN, "No statedir setup, cannot find la-sync-manager pid file");
315        return;
316    }
317}
318
3191;
320
321__END__
322
323=head1 AUTHOR
324
325Thauvin Olivier, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
326
327=head1 COPYRIGHT AND LICENSE
328
329Copyright (C) 2009, 2010, 2011, 2012 by Thauvin Olivier
330
331This library is free software; you can redistribute it and/or modify
332it under the same terms as Perl itself, either Perl version 5.10.0 or,
333at your option, any later version of Perl 5 you may have available.
334
335=cut
Note: See TracBrowser for help on using the repository browser.