#!/usr/bin/perl # # Automated Course Creation script # # $Id: Autocreate.pl,v 1.14 2010/08/13 16:37:30 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # Run as www. Called from an entry in /etc/cron.d/loncapa # either with command line args: # # www /home/httpd/perl/Autocreate.pl $dom $uname:$udom # # where $dom is the name of the course domain, $uname and $udom are the # username and domain of a Domain Coordinator in the domain. # # or without args (default) controlled by domain configuration settings: # # www /home/httpd/perl/Autocreate.pl # use strict; use lib '/home/httpd/lib/perl'; use Apache::lonnet; use Apache::lonlocal; use Apache::loncoursequeueadmin; use LONCAPA::batchcreatecourse; use LONCAPA::Configuration; use LONCAPA(); my $perlvarref = &LONCAPA::Configuration::read_conf('loncapa.conf'); my $logfile = $$perlvarref{'lonDaemons'}.'/logs/autocreate.log'; my @machinedoms = sort(&Apache::lonnet::current_machine_domains()); my @ids=&Apache::lonnet::current_machine_ids(); my (@libids,@domains); foreach my $id (@ids) { if (&Apache::lonnet::is_library($id)) { push(@libids,$id); } } exit if (!@libids); foreach my $dom (@machinedoms) { my $primary = &Apache::lonnet::domain($dom,'primary'); if (grep(/^\Q$primary\E$/,@libids)) { unless (grep(/^\Q$dom\E$/,@domains)) { push(@domains,$dom); } } } exit if (!@domains); open (my $fh,">>$logfile"); print $fh "********************\n".localtime(time)." Autocreation messages start --\n"; my $wwwid=getpwnam('www'); if ($wwwid!=$<) { my $emailto=$$perlvarref{'lonAdmEMail'}; my $subj="LON: $$perlvarref{'lonHostID'} User ID mismatch"; my $requestmail = "To: $emailto\n"; $requestmail .= "Subject: LON: $$perlvarref{'lonHostID'} User ID mismatch\n". "User ID mismatch. Autocreate.pl must be run as user www\n"; if ($emailto =~ /^[^\@]+\@[^\@]+$/) { if (open(MAIL, "|/usr/lib/sendmail -oi -t -odb")) { print MAIL $requestmail; close(MAIL); print $fh "Autocreate.pl must be run as user www\n\n"; } else { print $fh "Could not send notification e-mail to $emailto\n\n"; } } else { print $fh "Notification e-mail address for Administrator is not a valid e-mail address\n\n"; } close($fh); exit; } if (@ARGV) { # check if specified course domain is a domain hosted on this library server. if (!grep(/^\Q$ARGV[0]\E$/,@domains)) { print $fh "The domain you supplied is not a valid domain for this server\n"; close($fh); exit; } elsif (@ARGV < 2) { print $fh "usage: ./Autocreate .\nPlease provide the username and domain of a Domain Coordinator, if you provide a coursedomain.\nThe script can also be called without any arguments, in which case domain configuration data for domains hosted on this server will be used.\n"; close($fh); exit; } else { my $defdom = $ARGV[0]; my ($dcname,$dcdom) = ($ARGV[1] =~ /^([^:]+):([^:]+)$/); # check if user is an active domain coordinator. if (!&check_activedc($dcdom,$dcname,$defdom)) { print $fh "The username you supplied for domain $defdom does not have an active domain coordinator role in the domain\n\n"; close($fh); exit; } $env{'user.name'} = $dcname; $env{'user.domain'} = $dcdom; $env{'request.role.domain'} = $defdom; my @permissions = ('mau','ccc','cin','cta','cep','ccr','cst'); my %permissionflags = (); &set_permissions(\%permissionflags,\@permissions); my $output = &process_xml($fh,$defdom,$dcname,$dcdom); print $output; &unset_permissions(\%permissionflags); } } else { my @permissions = ('mau','ccc','cin','cta','cep','ccr','cst'); my %permissionflags = (); &set_permissions(\%permissionflags,\@permissions); foreach my $dom (@domains) { my %domconfig = &Apache::lonnet::get_dom('configuration', ['autocreate'],$dom); #only run if configured to my $xml_update = 0; my $settings; if (ref($domconfig{'autocreate'}) eq 'HASH') { $settings = $domconfig{'autocreate'}; if ($settings->{'xml'}) { if ($settings->{'xmldc'}) { my ($dcname,$dcdom) = split(':',$settings->{'xmldc'}); $env{'user.name'} = $dcname; $env{'user.domain'} = $dcdom; $env{'request.role.domain'} = $dom; if (!&check_activedc($dcdom,$dcname,$dom)) { print $fh "Autocreate.pl in domain $dom configured to run under the auspices of a user without an active domain coordinator role in the domain - course creation will be skipped.\n\n"; next; } else { &process_xml($fh,$dom,$dcname,$dcdom); } } else { print $fh "Autocreate.pl in domain $dom - no specified DC under whose identity course creation will occur - domain skipped.\n\n"; } } if ($settings->{'req'}) { my $output = &Apache::process_official_reqs('auto',$dom); if ($output) { print $fh $output; } } } } &unset_permissions(\%permissionflags); } print $fh "-- ".localtime(time)." Autocreation messages end\n*******************\n\n"; close($fh); sub process_xml { my ($fh,$dom,$dcname,$dcdom) = @_; $env{'user.name'} = $dcname; $env{'user.domain'} = $dcdom; $env{'request.role.domain'} = $dom; # Initialize language handler &Apache::lonlocal::get_language_handle(); my $batchdir = $$perlvarref{'lonDaemons'}.'/tmp/addcourse/'.$dom.'/auto'; opendir(DIR,"$batchdir/pending"); my @requests = grep(!/^\.\.?$/,readdir(DIR)); closedir(DIR); my %courseids = (); print $fh "Sending to batch - auto,$dom,$dcname,$dcdom ".join(":",@requests)."\n"; my ($result,$logmsg) = &LONCAPA::batchcreatecourse::create_courses(\@requests,\%courseids,'auto',$dom,$dcname,$dcdom); my $outcome; if ($result ne '') { $outcome = $result."\n"; } if ($logmsg ne '') { $outcome .= $logmsg."\n"; } print $fh $outcome; my $output; # Copy requests from pending directory to processed directory and unlink. foreach my $request (@requests) { if ((-e "$batchdir/pending/$request") && $request !~ /\.\./ && $request ne '' &&$request ne './') { open(FILE,"<$batchdir/pending/$request"); my @buffer = ; close(FILE); if (!-e "$batchdir/processed") { mkdir("$batchdir/processed", 0755); } open(FILE,">$batchdir/processed/$request"); print FILE @buffer; close(FILE); if (-e "$batchdir/processed/$request") { unlink("$batchdir/pending/$request"); } } } foreach my $key (sort(keys(%courseids))) { print $fh "created course: $key - $courseids{$key}\n"; my $newcourse = &LONCAPA::escape($key.':'.$courseids{$key}); $output .= $newcourse.':'; } $output =~ s/:$//; delete($env{'user.name'}); delete($env{'user.domain'}); delete($env{'request.role.domain'}); return $output; } sub check_activedc { my ($dcdom,$dcname,$defdom) = @_; my %dumphash= &Apache::lonnet::dump('roles',$dcdom,$dcname); my $now=time; my $activedc = 0; foreach my $item (keys %dumphash) { my ($domain,$role) = ($item =~ m-^/([^/]+)/[^_]*_(\w+)$-); if ($role eq 'dc' && $domain eq $defdom) { my ($trole,$tend,$tstart)=split(/_/,$dumphash{$item}); if (($tend) && ($tend<$now)) { next; } if (($tstart) && ($now<$tstart)) { next; } $activedc = 1; last; } } return $activedc; } sub set_permissions { my ($permissionflags,$permissions) = @_; foreach my $allowtype (@{$permissions}) { unless($env{"allowed.$allowtype"}) { $env{"allowed.$allowtype"} = 'F'; $permissionflags->{$allowtype} = 1; } } } sub unset_permissions { my ($permissionflags) = @_; foreach my $allowtype (keys(%{$permissionflags})) { delete($env{"allowed.$allowtype"}); } }