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

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