source: tags/5.0.7/LATMOS-Accounts/lib/LATMOS/Accounts.pm @ 1450

Last change on this file since 1450 was 1450, checked in by nanardon, 9 years ago
  • 5.0.7
  • 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;
12
13our $VERSION = '5.0.7';
14
15=head1 NAME
16
17LATMOS::Accounts - Core module for LATMOS account management tools
18
19=head1 DESCRITPTION
20
21=cut
22
23# Return the configuration directory according settings:
24#
25sub _configdir {
26   my ($self) = @_;
27   $ENV{LA_CONFIG} ||
28   ($self || {})->{_configdir} ||
29   '/etc/latmos-accounts'
30}
31
32=head1 FUNCTION
33
34=head2 new($configdir, %options)
35
36Instanciate a new LATMOS::Accounts object.
37
38C<$configdir> if defined is the directory containing files to use,
39default to F</etc/latmos-accounts/>.
40
41C<%options> can contains:
42
43=over 4
44
45=item noacl
46
47If true, acls configuration are not load and code act like everything is
48allowed.
49
50This flag is usefull for administrative tools, for which no acl must apply.
51
52=back
53
54=cut
55
56sub new {
57    my ($class, $config, %options) = @_;
58
59    $config ||= _configdir();
60
61    my $configfile = join('/', $config, 'latmos-accounts.ini');
62
63    my $self = Config::IniFiles->new(
64        -file => $configfile,
65        '-default' => '_default_',
66    ) or do {
67        la_log(LA_ERR, 'Can\'t open main config file %s', $configfile);
68        return;
69    };
70
71    $self->{_configdir} = $config;
72    bless($self, $class);
73
74    unless ($options{noacl}) {
75        if (-f (my $aclf = join('/', $self->_configdir, 'la-acls.ini'))) {
76            $self->{_acls} = LATMOS::Accounts::Acls->new($aclf) or do {
77                la_log(LA_ERR, 'Cannot load ACL file %s', $aclf);
78                return;
79            };
80        }
81    }
82
83    if (-f (my $allowf = join('/', $self->_configdir, 'la-allowed-values.ini'))) {
84        $self->{_allowed_values} = Config::IniFiles->new(
85            -file => $allowf,
86        ) or do {
87            la_log(LA_ERR, 'Cannot load ALLOWED VALUES %s', $allowf);
88            return;
89        };
90    }
91
92    $self
93}
94
95=head2 list_bases
96
97Return the base list found in config file
98
99=cut
100
101sub list_bases {
102    my ($self) = @_;
103    grep {
104        !m/^_.*_$/ &&
105        !m/^sync:/
106    } $self->Sections
107}
108
109=head2 default_base_name
110
111Return the default base name according config file
112
113=cut
114
115sub default_base_name {
116    my ($self) = @_;
117    $self->val('_default_', 'base', ($self->list_bases)[0]);
118}
119
120=head2 base($basename)
121
122Return a L<LATMOS::Accounts::Base> object over base named $basename
123defined in the config file.
124
125The base is loaded by this function.
126
127=cut
128
129sub base {
130    my ($self, $section) = @_;
131    # this method perform a cache
132    $self->_load_base($section || $self->default_base_name);
133}
134
135# do the bad work
136sub _load_base {
137    my ($self, $section) = @_;
138    my $type = $self->val($section, 'type') or return;
139    la_log(LA_DEBUG, "Trying to load base %s", $section);
140
141    my %params =
142        map { $_ => ($self->val($section, $_)) }
143        $self->Parameters($section);
144 
145    my %defattr =
146        map { $_ => ($self->val('_defattr_', $_)) }
147        $self->Parameters('_defattr_');
148
149    my $base = LATMOS::Accounts::Bases->new(
150        $type,
151        {
152            params => \%params,
153            label => $section,
154            acls => $self->{_acls},
155            allowed_values => $self->{_allowed_values},
156            configdir => $self->_configdir,
157            la => $self,
158            defattr => { %defattr },
159        },
160    ) or do {
161        la_log(LA_WARN, "Cannot instanciate base $section ($type)");
162        return;
163    };
164    $base->load or do {
165        la_log(LA_ERR, "%s didn't load", $base->label);
166        return;
167    };
168    $base;
169}
170
171=head2 list_synchro
172
173List synchronisation setup in L<latmos-accounts.ini>
174
175=cut
176
177sub list_synchro {
178    my ($self) = @_;
179    grep { $_ } map { /^sync:(.*)$/; $1 } $self->Sections
180}
181
182=head2 default_synchro_name
183
184Return de default synchronisation name
185
186=cut
187
188sub default_synchro_name {
189    my ($self) = @_;
190    $self->val('_default_', 'sync');
191}
192
193=head2 default_synchro
194
195Return a reference to default synchronisation object
196
197=cut
198
199sub default_synchro {
200    my ($self, %options) = @_;
201    my $syncname = $self->default_synchro_name or do {
202        la_log(LA_ERR, 'Cannot find default synchro in config');
203        return;
204    };
205    $self->create_synchro($syncname, %options);
206}
207
208=head2 create_synchro($name, %options)
209
210Return a reference to synchronisation object for C<$name> synchronisation.
211
212=cut
213
214sub create_synchro {
215    my ($self, $name, %options) = @_;
216
217    # taking options from config
218    if ($name) {
219        foreach my $param ($self->Parameters("sync:$name")) {
220            if (!defined($options{$param})) {
221                my @args = $self->val("sync:$name", $param);
222                $options{$param} = ($args[1] || $param eq 'to')
223                    ? [ @args ]
224                    : $args[0];
225            }
226        }
227    }
228
229    my $labfrom = $options{from} ? $self->base($options{from}) : $self->base;
230
231    my @labto =
232        grep { $_ }
233        map { $self->base($_) }
234        @{ $options{to} || []}
235        or do {
236        la_log(LA_ERR, "No destination base load in this synchro");
237        return;
238    };
239
240    my $sync = LATMOS::Accounts::Synchro->new(
241        $labfrom, [ @labto ],
242        state_dir => ($self->val('_default_', 'state_dir') || undef),
243        %options,
244        name => $name,
245    );
246}
247
248sub _sync_from_name {
249    my ($self, $syncname) = @_;
250    return if (!$syncname);
251    $self->val("sync:$syncname", 'from', $self->default_base_name);
252}
253
254=head2 sync_access($name, %options)
255
256Return a L<LATMOS::Accounts::SynchAccess> object over C<$name> synchronisation.
257
258=cut
259
260sub sync_access {
261    my ($self, $name, %options) = @_;
262
263    my @obases;
264    if ($name) {
265        @obases =
266        (map { $self->base($_) } ($self->_sync_from_name($name), $self->val("sync:$name", 'to')));
267    } elsif(@{ $options{bases} || []}) {
268        @obases = map { $self->base($_) } @{ $options{bases} || []};
269    } elsif (my $sname = $self->default_synchro_name) {
270        @obases = (map { $self->base($_) }
271            ($self->_sync_from_name($sname), $self->val("sync:$sname", 'to'))
272        );
273    }
274    warn @obases;
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.