diff --git a/ACU/Process.pm b/ACU/Process.pm new file mode 100644 index 0000000..1d1e361 --- /dev/null +++ b/ACU/Process.pm @@ -0,0 +1,291 @@ +#! /usr/bin/env perl + +package Process; + +use v5.10.1; +use strict; +use warnings; +use Carp; +use Gearman::Worker; +use XML::LibXML; +use XML::SAX::ParserFactory; +use List::Util "reduce"; +use Scalar::Util qw(looks_like_number); + +use constant COEFF_OLD => 25; +use constant WAITING_LOAD => 2; + +open(my $cpuinfo, "<", "/proc/cpuinfo"); +our $nb_cpus = 0; +$nb_cpus = grep {/^processor\s/} <$cpuinfo>; +close $cpuinfo; + +sub check_load ($) +{ + my $priority = shift; + my $load = 0; + + # Get load by parsing uptime command output + open my $fh, '-|', 'uptime'; + $load = $1 if <$fh> =~ /load average: (.+?),/; + close $fh; + + return (($load * 4 / $nb_cpus) < $priority); +} + +sub do_work ($$$@) +{ + my $subref = shift; + my $given_args = shift; + my $priority = shift; + + my $old = 0; + # Check the load isn't to high for this process + sleep WAITING_LOAD while ! check_load ($priority + (++$old / COEFF_OLD)); + + # Parse arguments + my $args = { + id => undef, + priority => 10, + auth => undef, + param => {}, + unamed => 0, + files => {}, + subtree => undef + }; + + my $sax_handler = ProcessHandler->new($args); + my $parser = XML::SAX::ParserFactory->parser( Handler => $sax_handler ); + + $parser->parse_string(${ $_[0]{argref} }); + + return $subref->($given_args, $args); +} + +sub register ($$;$$) +{ + my $funcname = shift; + my $subref = shift; + my $given_arg = shift; + my $priority = shift // 1; + + my $worker = Gearman::Worker->new; + + $worker->job_servers('gearmand:4730'); + $worker->register_function($funcname => sub { return do_work($subref, $given_arg, $priority, @_); }); + + say "$funcname registered"; + + $worker->work while 1; +} + + +package SubtreeItem; + +sub new ($$) +{ + my $class = shift; + my $self = { + nodeName => shift, + attributes => {}, + nodeValue => "", + children => [] + }; + + bless $self, $class; + + return $self; +} + +sub getAttribute ($$) +{ + my ($self, $name) = @_; + + return $self->{attributes}->{$name}; +} + +sub hasAttribute ($$) +{ + my ($self, $name) = @_; + + return exists $self->{attributes}->{$name}; +} + +sub getAllChildren($) +{ + my $self = shift; + + my @queue; + my @elements; + + for my $child (@{ $self->{children} }) { + push @queue, $child; + } + + while (@queue) { + my $child = shift @queue; + + for my $child2 (@{ $child->{children} }) { + push @queue, $child2; + } + + push @elements, $child; + } + + return @elements; +} + +sub hasChildNodes ($) +{ + my $self = shift; + + return @{ $self->{children} } > 0; +} + +sub getData ($) +{ + my $self = shift; + + return $self->nodeValue; +} + +sub getElementsByTagName ($$) +{ + my ($self, $name) = @_; + + return grep { $name eq "*" or $_->{nodeName} eq $name } getAllChildren($self); +} + +sub getElementById ($$) +{ + my ($self, $name) = @_; + + return grep { $_->{attributes}->{id} eq $name } getAllChildren($self); +} + +sub getFirstChild ($) +{ + my $self = shift; + + return $self->{children}[0]; +} + + +package ProcessHandler; + +use Carp; + +sub new ($$) +{ + my $class = shift; + my $self = { + parsed => shift, + fileEnc => "", + inFile => "", + inParam => "", + subtreeStack => [], + values => "" + }; + + bless $self, $class; + + return $self; +} + +sub start_element +{ + my ($self, $element) = @_; + + if (@{ $self->{subtreeStack} } > 0 || $element->{Name} eq "subtree") { + my $item = SubtreeItem->new($element->{Name}); + + for my $attribute (keys %{ $element->{Attributes} }) { + my $attr = $attribute; + $attr =~ s/{}//; + $item->{attributes}->{$attr} = $element->{Attributes}{$attribute}{Value}; + } + + if (@{ $self->{subtreeStack} } > 0) { + $self->{subtreeStack}[-1]->{nodeValue} .= $self->{values}; + } + push @{ $self->{subtreeStack} }, $item; + $self->{values} = ""; + } + elsif ($element->{Name} eq "process") { + $self->{parsed}{auth} = $element->{Attributes}{"{}auth"}{Value}; + $self->{parsed}{id} = $element->{Attributes}{"{}id"}{Value}; + $self->{parsed}{priority} = $element->{Attributes}{"{}priority"}{Value}; + } + elsif ($element->{Name} eq "file") { + $self->{inFile} = $element->{Attributes}{"{}name"}{Value}; + $self->{fileEnc} = $element->{Attributes}{"{}encoding"}{Value} // "base64"; + $self->{values} = ""; + } + elsif ($element->{Name} eq "param") { + if ($element->{Attributes}{"{}name"}{Value}) { + $self->{inParam} = $element->{Attributes}{"{}name"}{Value}; + } else { + $self->{inParam} = ++$self->{parsed}{unamed}; + } + + $self->{values} = ""; + } +} + +sub characters +{ + my ($self, $characters) = @_; + + if ($self->{inFile} || $self->{inParam} || @{ $self->{subtreeStack} } > 0) { + $self->{values} .= $characters->{Data}; + } +} + +sub end_element +{ + my ($self, $element) = @_; + + if (@{ $self->{subtreeStack} } > 0) + { + my $item = pop @{ $self->{subtreeStack} }; + $item->{nodeValue} .= $self->{values}; + $item->{nodeValue} =~ s/\n+/ /g; + $item->{nodeValue} =~ s/ +/ /g; + if (@{ $self->{subtreeStack} } > 0) { + push @{ $self->{subtreeStack}[-1]->{children} }, $item; + } + else { + $self->{parsed}{subtree} = $item; + } + $self->{values} = ""; + } + elsif ($element->{Name} eq "param") { + $self->{parsed}{param}{ $self->{inParam} } = $self->{values}; + $self->{inParam} = ""; + $self->{values} = ""; + } + elsif ($element->{Name} eq "file") { + $self->{parsed}{files}{ $self->{inFile} } = decode_file($self->{values}, $self->{fileEnc}); + $self->{values} = ""; + $self->{inFile} = ""; + $self->{fileEnc} = ""; + } +} + +sub decode_file ($$) +{ + my $content = shift; + my $encoding = shift; + + if ($encoding eq "base64") + { + use MIME::Base64; + + return decode_base64($content); + } + else { + croak "$encoding is not a known encoding." + } +} + +1; diff --git a/process/ldap/update_group.pl b/process/ldap/update_group.pl new file mode 100644 index 0000000..b4d01b7 --- /dev/null +++ b/process/ldap/update_group.pl @@ -0,0 +1,133 @@ +#! /usr/bin/env perl + +use v5.10.1; +use strict; +use warnings; +use Pod::Usage; + +BEGIN { + push @INC, "../../"; +} + +use ACU::LDAP; +use ACU::Process; + +our $ou = "intra"; + +my %actions = +( + "new" => \&group_new, + "add" => \&group_add, + "delete" => \&group_delete, + "flush" => \&group_flush, + "remove" => \&group_remove, + "update" => \&group_update, +); + +sub group_new($$) +{ + my $dn = shift; + my $args = shift; + + # Add group + if (LDAP::add_group($args->{param}{cn}, LDAP::get_year) eq $dn) + { + if ($args->{param}{type}) { + group_add $dn, $args + } + } +} + +sub group_add($$) +{ + my $dn = shift; + my $args = shift; + + my $cnt_type = group_get_type $args->{param}; + + # Add content if any + for (my $i = $args->{unamed}; $i > 0; $i--) { + LDAP::add_attribute($dn, $cnt_type, $args->{param}{$i}); + } +} + +sub group_delete($$) +{ + return LDAP::delete_entry(shift); +} + +sub group_flush($$) +{ + my $dn = shift; + my $args = shift; + + my $cnt_type = group_get_type $args->{param}; + + return LDAP::flush_attribute($dn, $cnt_type); +} + +sub group_remove($$) +{ + my $dn = shift; + my $args = shift; + + my $cnt_type = group_get_type $args->{param}; + + my @data; + for (my $i = $args->{unamed}; $i > 0; $i--) { + push @data, $i; + } + + return LDAP::delete_attributes($dn, $cnt_type, \@data); +} + +sub group_update($$) +{ + my $dn = shift; + my $args = shift; + + my $cnt_type = group_get_type $args->{param}; + + my @data; + for (my $i = $args->{unamed}; $i > 0; $i--) { + push @data, $i; + } + + LDAP::update_attribute($dn, $cnt_type, \@data); +} + + +sub group_get_type($) +{ + my $param = shift; + + # Extract data type + if ($param{type} eq "members") { + return "memberUid"; + } + elsif ($param{type} eq "rights") { + return "intraRights" ; + } + else { + die ("Unknown type to add: ".$param{type}); + } +} + + +sub process +{ + my ($given_args, $args) = @_; + + my $year = $param{year} // LDAP::get_year; + my $dn = "cn=".$param{cn}."ou=$year,ou=$ou,ou=groups,dc=acu,dc=epita,dc=fr"; + my $action = $param{type} // "update"; + + # Read action + if (! exists $actions{$action}) { + return "Unknown command for update_group: ". $action; + } + + return $actions{$action}($dn, $args); +} + +Process::register("update_group", \&process);