source: branches/4.0/LATMOS-Accounts/lib/LATMOS/Accounts.pm @ 1299

Last change on this file since 1299 was 1299, checked in by nanardon, 9 years ago

backport fix

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