File Coverage

install_util/GBrowseInstall.pm
Criterion Covered Total %
statement 57 579 9.8
branch 0 174 0.0
condition 1 135 0.7
subroutine 19 63 30.1
pod 1 45 2.2
total 78 996 7.8


line stmt bran cond sub pod time code
1             package GBrowseInstall;
2              
3 1     1   646375 use base 'Module::Build';
  1         2  
  1         107  
4 1     1   5 use strict;
  1         2  
  1         24  
5 1     1   4 use warnings;
  1         16  
  1         34  
6 1     1   479 use ExtUtils::CBuilder;
  1         34309  
  1         28  
7 1     1   725 use ExtUtils::MakeMaker 'prompt';
  1         75365  
  1         53  
8 1     1   7 use Cwd;
  1         1  
  1         45  
9 1     1   3 use File::Basename 'dirname','basename';
  1         1  
  1         35  
10 1     1   4 use File::Path 'rmtree','mkpath';
  1         1  
  1         35  
11 1     1   3 use File::Temp 'tempdir';
  1         1  
  1         36  
12 1     1   3 use File::Spec;
  1         1  
  1         14  
13 1     1   3 use IO::File;
  1         1  
  1         118  
14 1     1   419 use IO::Dir;
  1         6131  
  1         43  
15 1     1   4 use File::Compare 'compare';
  1         2  
  1         50  
16 1     1   3 use File::Copy 'copy','cp';
  1         2  
  1         45  
17 1     1   330 use GBrowseGuessDirectories;
  1         2  
  1         26  
18 1     1   4 use Carp 'cluck';
  1         41  
  1         61  
19              
20 1         5 use overload '""' => 'asString',
21 1     1   5 fallback => 1;
  1         1  
22              
23 1     1   61 use constant REGISTRATION_SERVER => 'http://modencode.oicr.on.ca/cgi-bin/gbrowse_registration';
  1         1  
  1         5018  
24              
25             my @OK_PROPS = (conf => 'Directory for GBrowse\'s config and support files?',
26             htdocs => 'Directory for GBrowse\'s static images & HTML files?',
27             tmp => 'Directory for GBrowse\'s temporary data',
28             persistent => 'Directory for GBrowse\'s sessions, uploaded tracks and other persistent data',
29             databases => 'Directory for GBrowse\'s example databases',
30             cgibin => 'Directory for GBrowse\'s CGI script executables?',
31             portdemo => 'Internet port to run demo web site on (for demo)?',
32             apachemodules => 'Apache loadable module directory (for demo)?',
33             wwwuser => 'User account under which Apache daemon runs?',
34             installconf => 'Automatically update Apache config files to run GBrowse?',
35             installetc => 'Automatically update system config files to run gbrowse-slave?',
36             );
37             my %OK_PROPS = @OK_PROPS;
38              
39             # TO FIX: this contains much of the same code as in the non-demo build
40             # and should be refactored.
41             sub ACTION_demo {
42 0     0 0 0 my $self = shift;
43 0         0 $self->depends_on('config_data');
44 0         0 $self->depends_on('build');
45              
46 0         0 my $dir = tempdir(
47             'GBrowse_demo_XXXX',
48             TMPDIR=>1,
49             CLEANUP=>0,
50             );
51 0   0     0 my $port = $self->config_data('portdemo')
52             || GBrowseGuessDirectories->portdemo();
53 0   0     0 my $modules = $self->config_data('apachemodules')
54             || GBrowseGuessDirectories->apachemodules;
55 0   0     0 my $db = $self->config_data('databases')
56             || GBrowseGuessDirectories->databases;
57 0         0 my $cgiurl = $self->cgiurl;
58 0         0 my $persistent = $self->config_data('persistent');
59              
60 0         0 mkdir "$dir/conf";
61 0         0 mkdir "$dir/htdocs";
62 0         0 mkdir "$dir/logs";
63 0         0 mkdir "$dir/locks";
64 0         0 mkdir "$dir/tmp";
65              
66             # make copies of htdocs and conf
67 0         0 open my $saveout,">&STDOUT";
68 0         0 open STDOUT,">/dev/null";
69              
70 0         0 my $f = IO::File->new('MANIFEST');
71 0         0 while (<$f>) {
72 0         0 chomp;
73 0 0       0 if (m!^(conf|htdocs)!) {
    0          
    0          
74 0         0 $self->copy_if_modified($_ => $dir);
75             } elsif (m!cgi-bin!) {
76 0         0 $self->copy_if_modified(from => $_,to_dir => "$dir/cgi-bin/gb2",flatten=>1);
77 0         0 chmod 0755,$_ foreach (glob "$dir/cgi-bin/gb2/*");
78             } elsif (m!^sample_data!) {
79 0         0 chdir $self->base_dir();
80 0         0 my ($subdir) = m!^sample_data/([^/]+)/!;
81 0         0 $self->copy_if_modified(from => $_,
82             to_dir => "$dir/htdocs/databases/$subdir",
83             flatten => 1,
84             );
85             }
86             }
87 0         0 close $f;
88 0         0 chdir $self->base_dir;
89 0         0 open STDOUT,"<&",$saveout;
90              
91             # fix GBrowse.conf to point to correct directories
92 0         0 for my $f ("$dir/conf/GBrowse.conf",
93             "$dir/conf/yeast_simple.conf",
94             "$dir/conf/yeast_chr1+2.conf",
95             "$dir/conf/pop_demo.conf",
96             "$dir/conf/yeast_renderfarm.conf",
97             "$dir/htdocs/index.html") {
98 0 0       0 my $in = IO::File->new($f) or die "$dir/conf/$f: $!";
99 0 0       0 my $out = IO::File->new("$f.new",'>') or die $!;
100 0         0 while (<$in>) {
101 0         0 s!\$CONF!$dir/conf!g;
102 0         0 s!\$HTDOCS!$dir/htdocs!g;
103 0         0 s!\$DATABASES!$dir/htdocs/databases!g;
104 0         0 s!\$PERSISTENT!$dir/$persistent!g;
105 0         0 s!\$TMP!$dir/tmp!g;
106 0         0 s/\$CGIURL/$cgiurl/g;
107 0         0 s!\$VERSION!$self->dist_version!eg;
  0         0  
108 0         0 s/\$CAN_USER_ACCOUNTS_OPENID/$self->has_openid/eg;
  0         0  
109 0         0 s/\$CAN_USER_ACCOUNTS_REG/$self->has_smtp/eg;
  0         0  
110 0         0 s/\$CAN_USER_ACCOUNTS/$self->has_mysql_or_sqlite/eg;
  0         0  
111 0         0 s/\$USER_ACCOUNT_DB/$self->guess_user_account_db/eg;
  0         0  
112 0         0 s/\$SMTP_GATEWAY/$self->guess_smtp_gateway/eg;
  0         0  
113 0         0 s!^url_base\s*=.+!url_base = /!g;
114 0         0 s!^user_accounts[^=]+=.*!user_accounts = 0!;
115 0         0 $out->print($_);
116             }
117 0         0 close $out;
118 0         0 rename "$f.new",$f;
119             }
120            
121 0         0 my $conf_data = $self->httpd_conf($dir,$port);
122 0 0       0 my $conf = IO::File->new("$dir/conf/httpd.conf",'>')
123             or die "$dir/conf/httpd.conf: $!";
124 0         0 $conf->print($conf_data);
125 0         0 $conf->close;
126              
127 0         0 $conf_data = $self->gbrowse_demo_conf($port,$dir);
128 0 0       0 $conf = IO::File->new("$dir/conf/apache_gbrowse.conf",'>')
129             or die "$dir/conf/apache_gbrowse.conf: $!";
130 0         0 $conf->print($conf_data);
131 0         0 $conf->close;
132              
133 0         0 $conf_data = $self->mime_conf();
134 0 0       0 my $mime = IO::File->new("$dir/conf/mime.types",'>')
135             or die "$dir/conf/mime.types: $!";
136 0         0 $mime->print($conf_data);
137 0         0 $mime->close;
138              
139 0 0       0 my $apache = GBrowseGuessDirectories->apache
140             or die "Could not find apache executable on this system. Can't run demo";
141              
142 0         0 system "$apache -k start -f $dir/conf/httpd.conf";
143 0         0 sleep 3;
144 0 0       0 if (-e "$dir/logs/apache2.pid") {
145 0         0 print STDERR "Demo config and log files have been written to $dir\n";
146 0         0 print STDERR "Demo is now running on http://localhost:$port\n";
147 0         0 print STDERR "Run \"./Build demostop\" to stop it.\n";
148 0         0 $self->config_data(demodir=>$dir);
149             } else {
150 0         0 print STDERR "Apache failed to start. Perhaps the demo is already running?\n";
151 0 0       0 if (-e "$dir/logs/error.log") {
152 0         0 print STDERR "==Apache Error Log==\n";
153 0         0 my $f = IO::File->new("$dir/logs/error.log");
154 0         0 print STDERR while <$f>;
155             }
156 0         0 rmtree([$dir]);
157             }
158             }
159              
160             sub ACTION_demostop {
161 0     0 0 0 my $self = shift;
162 0         0 my $dir = $self->config_data('demodir');
163 0         0 my $home = $self->base_dir();
164 0 0 0     0 unless ($dir && -e $dir) {
165 0         0 print STDERR "Demo doesn't seem to be running.\n";
166 0         0 return;
167             }
168 0 0       0 my $apache = GBrowseGuessDirectories->apache
169             or die "Could not find apache executable on this system. Can't stop demo";
170              
171 0         0 system "$apache -k stop -f $dir/conf/httpd.conf";
172 0         0 rmtree([$dir,"$home/htdocs/tmp"]);
173 0         0 $self->config_data('demodir'=>undef);
174 0         0 print STDERR "Demo stopped.\n";
175             }
176              
177             sub ACTION_clean {
178 0     0 0 0 my $self = shift;
179 0         0 $self->SUPER::ACTION_clean;
180 0         0 unlink 'INSTALL.SKIP';
181             }
182              
183             sub ACTION_realclean {
184 0     0 0 0 my $self = shift;
185 0         0 $self->SUPER::ACTION_realclean;
186 0         0 foreach ('CAlign.xs','CAlign.pm') {
187 0         0 unlink "./lib/Bio/Graphics/Browser/$_";
188             }
189             }
190              
191             sub ACTION_build {
192 0     0 0 0 my $self = shift;
193 0         0 $self->depends_on('config');
194 0 0       0 $self->depends_on('register') unless $self->registration_done;
195 0         0 $self->SUPER::ACTION_build;
196 0         0 mkdir './htdocs/tmp';
197 0         0 chmod 0777,'./htdocs/tmp';
198             }
199              
200             sub ACTION_reconfig {
201 0     0 0 0 my $self = shift;
202 0         0 $self->config_done(0);
203 0 0       0 unless (Module::Build->y_n("Reuse previous configuration as defaults?",'y')) {
204 0         0 for (keys %{$self->private_props}) {
  0         0  
205 0         0 $self->config_data($_=>undef);
206             }
207             }
208 0         0 $self->depends_on('config_data');
209 0         0 warn "\n**Paths reconfigured. Running \"Build clean\".\n";
210 0         0 $self->ACTION_clean;
211             }
212              
213             sub ACTION_test {
214 0     0 0 0 my $self = shift;
215 0         0 $self->depends_on('config_data');
216 0         0 $self->SUPER::ACTION_test;
217             }
218              
219             sub ACTION_distclean {
220 0     0 0 0 my $self = shift;
221 0         0 $self->SUPER::ACTION_distclean;
222 0         0 rmtree(['debian/libgbrowse-perl']);
223             }
224              
225             sub ACTION_config {
226 0     0 0 0 my $self = shift;
227 0         0 local $^W = 0;
228              
229 0   0     0 my $prefix = $self->install_base || $self->prefix || '';
230 0         0 GBrowseGuessDirectories->prefix($prefix);
231              
232             # $self->depends_on('build');
233 0 0       0 return if $self->config_done;
234              
235 0         0 print STDERR "\n**Beginning interactive configuration**\n";
236              
237 0         0 my $props = $self->private_props;
238             my %opts = map {
239 0         0 $_=>$self->config_data($_)
  0         0  
240             } keys %$props;
241              
242 0         0 my $dire_warning = 0;
243 0         0 my @keys = @OK_PROPS;
244 0         0 while (@keys) {
245 0         0 my $key = shift @keys;
246 0         0 my $val = shift @keys; # not used
247              
248             # next if $self->config_data($key);
249 0         0 my $conf_dir = $props->{$key} =~ /directory/i;
250              
251             $opts{$key} = prompt($props->{$key},
252             $opts{$key} ||
253             ($conf_dir
254             ? File::Spec->canonpath(
255             File::Spec->catfile(GBrowseGuessDirectories->$key($opts{apache})))
256 0   0     0 : GBrowseGuessDirectories->$key($opts{apache})));
257 0 0       0 if ($conf_dir) {
258 0         0 my ($volume,$dir) = File::Spec->splitdir($opts{$key});
259 0         0 my $top_level = File::Spec->catfile($volume,$dir);
260              
261 0 0       0 if ($opts{$key} =~ m!(/usr/local/apache2*)!) {
262             #it looks like there is no apache installed; let the user know
263 0         0 my $apachedir = $1;
264 0 0 0     0 if (!-d $apachedir and !$dire_warning) {
265 0         0 print STDERR <
266              
267             ******************************WARNING***********************************
268             GBrowse is being configured to install in $apachedir, but that
269             directory doesn't exist, which means either Apache isn\'t installed
270             or the installer couldn't find it. If you continue with this
271             installation there is a good chance it won't work if Apache isn't
272             installed.
273             ******************************WARNING***********************************
274              
275             END
276             ;
277 0         0 $dire_warning = 1;
278             }
279             }
280              
281 0 0       0 unless (-d $top_level) {
282 0 0       0 next if Module::Build->y_n("The directory $top_level does not exist. Use anyway?",'n');
283 0         0 redo;
284             }
285             }
286             }
287              
288 0         0 for my $key (keys %opts) {
289 0         0 $self->config_data($key=>$opts{$key});
290             }
291              
292 0         0 $self->config_done(1);
293              
294 0         0 print STDERR "\n**Interactive configuration done. Run './Build reconfig' to reconfigure**\n";
295             }
296              
297             sub ACTION_register {
298 0     0 0 0 my $self = shift;
299 0 0       0 return unless -t STDIN;
300 0         0 print STDERR "\n**Registration**\nGBrowse2 registration is optional, but will help us maintain funding for this project.\n";
301 0 0       0 if (Module::Build->y_n("Do you wish to register your installation?",'y')) {
302 0         0 print STDERR "All values are optional, but appreciated.\n";
303 0         0 my $user = prompt('Your name:');
304 0         0 my $email = prompt('Your email address:');
305 0         0 my $org = prompt('Your organization:');
306 0         0 my $organism = prompt('Organisms you will be using GBrowse for (one line):');
307 0         0 my $site = prompt('If GBrowse will be public, the URL of your web site:');
308 0         0 my $result = eval {
309 0         0 eval "use HTTP::Request::Common";
310 0         0 eval "use LWP::UserAgent";
311 0         0 my $ua = LWP::UserAgent->new;
312 0         0 my $response = $ua->request(POST(REGISTRATION_SERVER,
313             [user=>$user,email=>$email,
314             org=>$org,organism=>$organism,
315             site=>$site]
316             ));
317 0 0       0 die $response->status_line unless $response->is_success;
318 0         0 my $content = $response->decoded_content;
319 0         0 $content eq 'ok';
320             };
321 0 0       0 if ($@) {
322 0         0 print STDERR "An error occurred during registration: $@\n";
323 0         0 print STDERR "If you are able to fix the error, you can register later ";
324 0         0 print STDERR "using \"./Build register\"\n";
325             } else {
326 0 0       0 print STDERR $result ? "Thank you. Your registration was sent successfully.\n"
327             : "An error occurred during registration. Thanks anyway.\n";
328             }
329             } else {
330 0         0 print STDERR "If you wish to register at a later time please \"./Build register\"\n";
331 0         0 print STDERR "Press any key to continue\n";
332 0         0 my $h = ;
333             }
334 0         0 $self->registration_done(1);
335             }
336              
337              
338             sub ACTION_config_data {
339 0     0 0 0 my $self = shift;
340 0         0 $self->depends_on('config');
341 0         0 $self->SUPER::ACTION_config_data;
342             }
343              
344             sub ACTION_apache_conf {
345 0     0 0 0 my $self = shift;
346 0         0 $self->depends_on('config');
347              
348 0         0 my $docs = basename($self->config_data('htdocs'));
349 0         0 print STDERR <
350              
351             INSTRUCTIONS: Paste the following into your Apache configuration
352             file. You may wish to save it separately and include it using the
353             Apache "Include /path/to/file" directive. Then restart Apache and
354             point your browser to http://your.site/$docs/ to start browsing the
355             sample genomes.
356              
357             >>>>>> cut here <<<<<
358             END
359             ;
360 0         0 print $self->apache_conf;
361             }
362              
363             sub apache_conf {
364 0     0 1 0 my $self = shift;
365 0         0 my $dir = $self->config_data('htdocs');
366 0         0 my $conf = $self->config_data('conf');
367 0         0 my $cgibin = $self->config_data('cgibin');
368 0         0 my $tmp = $self->config_data('tmp');
369 0         0 my $databases = $self->config_data('databases');
370 0         0 my $cgiroot = basename($cgibin);
371 0         0 my $perl5lib= $self->added_to_INC;
372 0 0       0 my $inc = $perl5lib ? "SetEnv PERL5LIB \"$perl5lib\"" : '';
373 0 0       0 my $fcgi_inc = $perl5lib ? "-initial-env PERL5LIB=$perl5lib" : '';
374 0 0       0 my $fcgid_inc= $perl5lib ? "FcgidInitialEnv PERL5LIB $perl5lib" : '';
375             my $modperl_switches = $perl5lib
376 0 0       0 ? "PerlSwitches ".join ' ',map{"-I$_"} split ':',$perl5lib
  0         0  
377             : '';
378              
379 0         0 my ($allow_all,$deny_all) = $self->auth_conf;
380              
381 0         0 return <
382             Alias "/gbrowse2/i/" "$tmp/images/"
383             Alias "/gbrowse2" "$dir"
384             ScriptAlias "/gb2" "$cgibin"
385              
386            
387             AllowOverride Options
388             Options -Indexes -MultiViews +FollowSymLinks
389             $allow_all
390            
391              
392            
393             Options +Indexes
394            
395              
396            
397             $allow_all
398            
399              
400            
401             $deny_all
402            
403              
404            
405             ${inc}
406             Options ExecCGI
407             SetEnv GBROWSE_CONF "$conf"
408            
409              
410            
411             Alias /fgb2 "$cgibin"
412            
413             SetHandler fcgid-script
414            
415             FcgidInitialEnv GBROWSE_CONF $conf
416             # these directives prevent idle/busy timeouts and may need to be
417             # adjusted up or down
418             FcgidMinProcessesPerClass 6
419             FcgidConnectTimeout 30
420             FcgidIOTimeout 600
421             FcgidBusyTimeout 600
422             # allow larger file uploads up to 128M under FastCGI (default is 128K)
423             FcgidMaxRequestLen 134217728
424             $fcgid_inc
425            
426              
427            
428             Alias /fast "$cgibin"
429            
430             SetHandler fastcgi-script
431            
432             # Note: you may need to increase -idle-timeout if file uploads are timing out and returning server
433             # errors.
434             FastCgiConfig -startDelay 30 -appConnTimeout 30 -idle-timeout 600 -maxClassProcesses 20 $fcgi_inc -initial-env GBROWSE_CONF=$conf
435            
436              
437             # Use of mod_perl is no longer supported. Use at your own risk.
438            
439             Alias /mgb2 "$cgibin"
440             $modperl_switches
441            
442             SetHandler perl-script
443             PerlResponseHandler ModPerl::Registry
444             PerlOptions +ParseHeaders
445            
446            
447             END
448             }
449              
450             sub ACTION_install {
451 0     0 0 0 my $self = shift;
452 0   0     0 my $prefix = $self->install_base || $self->prefix || '';
453 0         0 GBrowseGuessDirectories->prefix($prefix);
454              
455 0         0 $self->depends_on('config_data');
456             $self->install_path->{conf}
457 0   0     0 ||= $self->config_data('conf') || GBrowseGuessDirectories->conf;
      0        
458             $self->install_path->{htdocs}
459 0   0     0 ||= $self->config_data('htdocs')
      0        
460             || GBrowseGuessDirectories->htdocs;
461 0   0     0 $self->install_path->{'cgi-bin'}
      0        
462             ||= $self->config_data('cgibin')
463             || GBrowseGuessDirectories->cgibin;
464 0   0     0 $self->install_path->{'etc'}
465             ||= GBrowseGuessDirectories->etc;
466 0   0     0 $self->install_path->{'databases'}
      0        
467             ||= $self->config_data('databases')
468             || GBrowseGuessDirectories->databases;
469 0   0     0 $self->install_path->{'persistent'}
      0        
470             ||= $self->config_data('persistent')
471             || GBrowseGuessDirectories->persistent;
472            
473 0         0 $self->SUPER::ACTION_install();
474              
475 0   0     0 my $user = $self->config_data('wwwuser') || GBrowseGuessDirectories->wwwuser;
476              
477             # fix some directories so that www user can write into them
478 0   0     0 my $tmp = $self->config_data('tmp') || GBrowseGuessDirectories->tmp;
479 0         0 mkpath($tmp);
480            
481 0         0 my ($uid,$gid) = (getpwnam($user))[2,3];
482              
483             # taint check issues
484 0         0 $uid =~ /^(\d+)$/;
485 0         0 $uid = $1;
486 0         0 $gid =~ /^(\d+)$/;
487 0         0 $gid = $1;
488            
489 0 0       0 unless (chown $uid,$gid,$tmp) {
490 0         0 $self->ownership_warning($tmp,$user);
491             }
492              
493 0         0 my $htdocs_i = File::Spec->catfile($self->install_path->{htdocs},'i');
494 0         0 my $images = File::Spec->catfile($tmp,'images');
495 0         0 my $gbs_tmp = File::Spec->catfile($self->install_path->{htdocs},'tmp');
496 0         0 my $htdocs = $self->install_path->{htdocs};
497 0         0 chown $uid,-1,$htdocs;
498             {
499 0         0 local $> = $uid;
  0         0  
500 0         0 symlink($images,$htdocs_i); # so symlinkifowner match works!
501 0         0 symlink($tmp,$gbs_tmp);
502             }
503 0         0 chown $>,-1,$self->install_path->{htdocs};
504              
505 0         0 my $persistent = $self->install_path->{'persistent'};
506 0         0 my $sessions = File::Spec->catfile($persistent,'sessions');
507 0         0 my $userdata = File::Spec->catfile($persistent,'userdata');
508 0         0 mkpath([$sessions,$userdata],0711);
509              
510 0         0 my $databases = $self->install_path->{'databases'};
511            
512 0 0       0 unless (chown $uid,$gid,glob(File::Spec->catfile($databases,'').'*')) {
513 0         0 $self->ownership_warning($databases,$user);
514             }
515              
516 0         0 chmod 0755,File::Spec->catfile($self->install_path->{'etc'},'init.d','gbrowse-slave');
517 0         0 chmod 0755,File::Spec->catfile($self->install_path->{'etc'},'init.d','gbrowse-aws-balancer');
518 0         0 $self->fix_selinux;
519              
520 0         0 my $base = basename($self->install_path->{htdocs});
521              
522             # Configure the databases, if needed.
523 0         0 print STDERR "Updating user account database...\n";
524 0         0 my $metadb_script = File::Spec->catfile("bin", "gbrowse_metadb_config.pl");
525 0         0 my $perl = $self->perl;
526 0         0 my @inc = map{"-I$_"} split ':',$self->added_to_INC;
  0         0  
527 0         0 system $perl,@inc,$metadb_script;
528 0         0 system 'sudo','chown','-R',"$uid.$gid",$sessions,$userdata;
529              
530             # make the gbrowse-aws-balancer file, which might contain secret keys, read-only to root
531 0 0       0 if ($self->config_data('installetc') =~ /^[yY]/) {
532 0   0     0 my $install_path = $self->install_path->{'etc'} || GBrowseGuessDirectories->etc;
533 0         0 system 'sudo','chmod','go-rwx',File::Spec->catfile($install_path,'default','gbrowse-aws-balancer');
534             }
535              
536             # enable CGI scripts on 2.4 systems
537 0 0       0 if ($self->apache_version =~ /2\.4/) {
538 0         0 print STDERR "Enabling CGI scripts on your Apache2 system...\n";
539 0         0 system 'sudo','a2enmod','cgi';
540             }
541              
542 0 0       0 if (Module::Build->y_n(
543             "It is recommended that you restart Apache. Shall I try this for you?",'y'
544             )) {
545 0         0 system "sudo /etc/init.d/apache2 restart";
546             }
547            
548 0         0 print STDERR "\n***INSTALLATION COMPLETE***\n";
549 0         0 print STDERR "Load http://localhost/$base for demo and documentation.\n";
550 0         0 print STDERR "Visit the http://gmod.org for more information on setting up databases for users and custom tracks.\n";
551             }
552              
553             sub ACTION_install_slave {
554 0     0 0 0 my $self = shift;
555 0   0     0 my $prefix = $self->install_base || $self->prefix ||'';
556 0         0 GBrowseGuessDirectories->prefix($prefix);
557 0   0     0 $self->install_path->{'etc'} ||= GBrowseGuessDirectories->etc;
558 0         0 $self->SUPER::ACTION_install();
559             }
560              
561             sub ACTION_debian {
562 0     0 0 0 my $self = shift;
563 0         0 system "debuild";
564             }
565              
566             sub fix_selinux {
567 0     0 0 0 my $self = shift;
568 0 0       0 return unless -e '/proc/filesystems';
569 0 0       0 my $f = IO::File->new('/proc/filesystems') or return;
570 0 0       0 return unless grep /selinux/i,<$f>;
571              
572 0 0       0 my $enabled = IO::File->new('/selinux/enforce') or return;
573 0 0       0 return unless grep /1/,<$enabled>;
574              
575 0         0 print STDERR "\n*** SELinux detected -- fixing permissions ***\n";
576              
577 0         0 my $htdocs = $self->config_data('htdocs');
578 0         0 my $conf = $self->config_data('conf');
579 0         0 my $tmp = $self->config_data('tmp');
580 0         0 my $db = $self->config_data('databases');
581 0         0 system "/usr/bin/chcon -R -t httpd_sys_content_t $conf";
582 0         0 system "/usr/bin/chcon -R -t httpd_sys_content_t $htdocs";
583 0         0 system "/usr/bin/chcon -R -t httpd_sys_content_rw_t $tmp";
584 0         0 system "/usr/bin/chcon -R -t httpd_sys_content_rw_t $db";
585             }
586              
587             sub process_conf_files {
588 0     0 0 0 my $self = shift;
589 0         0 my $f = IO::File->new('MANIFEST');
590              
591 0   0     0 my $prefix = $self->install_base || $self->prefix || '';
592 0         0 GBrowseGuessDirectories->prefix($prefix);
593 0   0     0 my $install_path = $self->config_data('conf') || GBrowseGuessDirectories->conf;
594              
595 0         0 while (<$f>) {
596 0 0       0 next unless m!^conf/!;
597 0         0 chomp;
598 0         0 my $base = $_;
599              
600 0         0 my $copied = $self->copy_if_modified($_=>'blib');
601 0 0 0     0 if ($copied || !$self->up_to_date('_build/config_data',"blib/$_")) {
602 0         0 $self->substitute_in_place("blib/$_");
603 0         0 $self->check_installed($install_path,$base);
604             }
605             }
606              
607             }
608              
609             sub check_installed {
610 0     0 0 0 my $self = shift;
611 0         0 my ($install_path,$blib_file) = @_;
612 0 0 0     0 my $skip = $self->{skip} ||= IO::File->new('>>INSTALL.SKIP') or die "INSTALL.SKIP: $!";
613 0         0 (my $base = $blib_file) =~ s!^[^/]+/!!;
614 0         0 my $staged = File::Spec->catfile('./blib',$blib_file);
615 0         0 my $installed = File::Spec->catfile($install_path,$base);
616              
617 0 0 0     0 if (-e $installed && (compare($staged,$installed) != 0)) {
618 0         0 my ($confirmed,$keep);
619              
620 0 0 0     0 if ($ENV{AUTOMATED_TESTING} || !(-t STDIN)) {
621 0         0 $confirmed++;
622 0         0 $keep++;
623             }
624              
625 0         0 while (!$confirmed) {
626 0         0 print STDERR "$installed has changed. Should \"Build install\" [R]eplace with new version or [K]eep currently installed version [K]? ";
627 0         0 my $line = <>;
628 0         0 chomp($line);
629 0   0     0 $line ||= '';
630 0 0       0 if ($line =~ /^[Kk]/) {
    0          
    0          
631 0         0 $keep++;
632 0         0 $confirmed++;
633             } elsif ($line =~ /^[Rr]/) {
634 0         0 $confirmed++;
635             } elsif ($line =~ /^$/) {
636 0         0 $keep++;
637 0         0 $confirmed++;
638             }
639             }
640            
641 0 0       0 if ($keep) {
642 0         0 print STDERR "\"Build install\" will keep original $installed. New version can be found in ${installed}.new\n\n";
643 0         0 cp($staged,"${staged}.new");
644 0         0 print $skip '^',"blib/",quotemeta($blib_file),'$',"\n";
645             } else {
646 0         0 print STDERR "\"Build install\" will replace original $installed. Original version can be found in ${installed}.orig\n\n";
647 0         0 cp($installed,"${staged}.orig");
648             }
649             }
650             }
651              
652             sub process_htdocs_files {
653 0     0 0 0 my $self = shift;
654 0         0 my $f = IO::File->new('MANIFEST');
655 0   0     0 my $install_path = $self->install_path->{'htdocs'} || GBrowseGuessDirectories->htdocs;
656              
657 0         0 my %doneit;
658 0         0 while (<$f>) {
659 0 0       0 next unless m!^htdocs/!;
660 0         0 chomp;
661 0         0 my $base = $_;
662 0         0 my $copied = $self->copy_if_modified($base=>'blib');
663 0 0 0     0 if ($copied or !$self->up_to_date('_build/config_data',"blib/$base")) {
664 0         0 $self->substitute_in_place("blib/$base");
665 0 0       0 $self->check_installed($install_path,$base) if $copied;
666             }
667             }
668              
669             # hacky thing for getting the cloud index.html right
670 0 0       0 if (eval "require Bio::Graphics::Browser2::Render::Slave::AWS_Balancer;1") {
671 0 0       0 if (Bio::Graphics::Browser2::Render::Slave::AWS_Balancer->running_as_instance) {
672 0         0 warn "Cloud instance detected; renaming index.html";
673 0         0 rename "blib/htdocs/index.html","blib/htdocs/index_default.html";
674 0         0 rename "blib/htdocs/cloud_index.html","blib/htdocs/index.html";
675             }
676             }
677             }
678              
679             sub process_cgibin_files {
680 0     0 0 0 my $self = shift;
681 0         0 my $f = IO::File->new('MANIFEST');
682 0         0 while (<$f>) {
683 0 0       0 next unless m!^cgi-bin/!;
684 0         0 chomp;
685 0         0 my $copied = $self->copy_if_modified($_=>'blib');
686 0         0 my $path = File::Spec->catfile('blib',$_);
687 0 0       0 if ($copied) {
688 0         0 $self->fix_shebang_line($path);
689 0         0 chmod 0755,$path;
690             }
691             }
692             }
693              
694             sub process_etc_files {
695 0     0 0 0 my $self = shift;
696              
697 0   0     0 my $prefix = $self->install_base || $self->prefix || '';
698 0         0 GBrowseGuessDirectories->prefix($prefix);
699 0   0     0 my $install_path = $self->install_path->{'etc'} || GBrowseGuessDirectories->etc;
700              
701 0 0       0 if ($self->config_data('installetc') =~ /^[yY]/) {
702 0         0 my $f = IO::File->new('MANIFEST');
703 0         0 while (<$f>) {
704 0 0       0 next unless m!^etc/!;
705 0         0 chomp;
706              
707 0         0 my $base = $_;
708              
709 0         0 my $copied = $self->copy_if_modified($_=>'blib');
710 0 0 0     0 if ($copied or !$self->up_to_date('_build/config_data',"blib/$_")) {
711 0         0 $self->substitute_in_place("blib/$_");
712 0         0 $self->check_installed($install_path,$base);
713             }
714             }
715             }
716              
717             # generate the apache config data
718 0   0     0 my $includes = GBrowseGuessDirectories->apache_includes || '';
719              
720             # the following workaround checks for perl.conf (which must load before gbrowse.conf on modperl envs)
721             # and renames the file so that it is loaded after perl.conf
722 0 0       0 my $file = -e "${includes}/perl.conf"
723             ? 'z_gbrowse2.conf'
724             : 'gbrowse2.conf';
725              
726 0         0 my $target = "blib${includes}/$file";
727 0 0 0     0 if ($includes && !$self->up_to_date('_build/config_data',$target)) {
728 0 0 0     0 if ($self->config_data('installconf') =~ /^[yY]/ && !-e "${includes}/$file") {
729 0         0 warn "Creating include file for Apache config: $target\n";
730 0         0 my $dir = dirname($target);
731 0         0 mkpath([$dir]);
732 0 0       0 if (my $f = IO::File->new("blib${includes}/$file",'>')) {
733 0         0 $f->print($self->apache_conf);
734 0         0 $f->close;
735             }
736             } else {
737 0 0       0 print STDERR
738             -e "${includes}/$file"
739             ? "${includes}/$file is already installed. "
740             : "Automatic Apache config disabled. ";
741 0         0 print STDERR "Please run ./Build apache_conf to see this file's recommended contents.\n";
742             }
743              
744             }
745 0 0       0 if (!$self->config_data('installetc') =~ /^[yY]/) {
746 0         0 warn "Not configuring your system to run gbrowse-slave automatically. Please reconfigure with this option enabled if you wish to do this.";
747             }
748             }
749              
750             sub process_database_files {
751 0     0 0 0 my $self = shift;
752 0         0 my $f = IO::File->new('MANIFEST');
753 0         0 while (<$f>) {
754 0 0       0 next unless m!^sample_data/!;
755 0         0 chomp;
756 0         0 my $dest = $_; $dest =~ s|^sample_data/||;
  0         0  
757 0         0 $self->copy_if_modified(from => $_,
758             to => "blib/databases/$dest",
759             );
760             }
761             }
762              
763             sub substitute_in_place {
764 0     0 0 0 my $self = shift;
765 0         0 my $path = shift;
766 0 0 0     0 return if $path =~ /\.\w+$/ && $path !~ /\.(html|txt|conf)$/;
767 0 0       0 my $in = IO::File->new($path) or return;
768 0 0       0 my $out = IO::File->new("$path.$$",'>') or return;
769              
770 0         0 print STDERR "Performing variable substitutions in $path\n";
771              
772 0         0 my $htdocs = $self->config_data('htdocs');
773 0         0 my $conf = $self->config_data('conf');
774 0         0 my $cgibin = $self->config_data('cgibin');
775 0         0 my $persistent = $self->config_data('persistent');
776 0         0 my $databases = $self->config_data('databases');
777 0         0 my $tmp = $self->config_data('tmp');
778 0         0 my $wwwuser = $self->config_data('wwwuser');
779 0   0     0 my $perl5lib = $self->perl5lib || '';
780 0         0 my $installscript = $self->install_destination('script');
781 0   0     0 my $etc = $self->install_path->{'etc'} ||= GBrowseGuessDirectories->etc;
782 0         0 my $cgiurl = $self->cgiurl;
783              
784 0   0     0 $persistent ||= $databases;
785              
786 0         0 while (<$in>) {
787 0         0 s/\$INSTALLSCRIPT\b/$installscript/g;
788 0         0 s/\$ETC\b/$etc/g;
789 0         0 s/\$PERL5LIB\b/$perl5lib/g;
790 0         0 s/\$HTDOCS\b/$htdocs/g;
791 0         0 s/\$CONF\b/$conf/g;
792 0         0 s/\$CGIBIN\b/$cgibin/g;
793 0         0 s/\$CGIURL\b/$cgiurl/g;
794 0         0 s/\$WWWUSER\b/$wwwuser/g;
795 0         0 s/\$DATABASES\b/$databases/g;
796 0         0 s/\$PERSISTENT\b/$persistent/g;
797 0         0 s/\$VERSION\b/$self->dist_version/eg;
  0         0  
798 0         0 s/\$CAN_USER_ACCOUNTS_OPENID\b/$self->has_openid/eg;
  0         0  
799 0         0 s/\$CAN_USER_ACCOUNTS_REG\b/$self->has_smtp/eg;
  0         0  
800 0         0 s/\$CAN_USER_ACCOUNTS\b/$self->has_mysql_or_sqlite/eg;
  0         0  
801 0         0 s/\$USER_ACCOUNT_DB\b/$self->guess_user_account_db/eg;
  0         0  
802 0         0 s/\$SMTP_GATEWAY\b/$self->guess_smtp_gateway/eg;
  0         0  
803 0         0 s/\$TMP\b/$tmp/g;
804 0         0 $out->print($_);
805             }
806 0         0 $in->close;
807 0         0 $out->close;
808 0         0 rename("$path.$$",$path);
809             }
810              
811             sub has_mysql_or_sqlite {
812 0     0 0 0 my $self = shift;
813 0   0     0 return eval "require DBD::mysql; 1" || eval "require DBD::SQLite; 1" || 0;
814             }
815              
816             sub has_smtp {
817 0     0 0 0 my $self = shift;
818 0   0     0 return eval "require Net::SMTP; 1" || 0;
819             }
820              
821             sub has_openid {
822 0     0 0 0 my $self = shift;
823 0   0     0 return eval "require Net::OpenID::Consumer; require LWP::UserAgent; 1" || 0;
824             }
825              
826             sub guess_user_account_db {
827 0     0 0 0 my $self = shift;
828 0 0       0 if (eval "require DBD::SQLite; 1") {
    0          
829 0         0 my $databases = $self->config_data('databases');
830 0         0 return "DBI:SQLite:$databases/users.sqlite";
831             } elsif (eval "require DBD::mysql; 1") {
832 0         0 return 'DBI:mysql:gbrowse_login;user=gbrowse;password=gbrowse';
833             } else {
834 0         0 return "no database defined # please correct this";
835             }
836             }
837              
838             sub guess_smtp_gateway {
839 0     0 0 0 my $self = shift;
840 0         0 return 'localhost # this assumes that a correctly configured smtp server is running on current machine; change if necessary';
841             }
842              
843             sub private_props {
844 0     0 0 0 return \%OK_PROPS;
845             }
846              
847             sub valid_property {
848 8     8 0 265622 my $self = shift;
849 8         14 my $prop = shift;
850 8   33     54 return $OK_PROPS{$prop} || $self->SUPER::valid_property($prop);
851             }
852              
853             sub httpd_conf {
854 0     0 0   my $self = shift;
855 0           my ($dir,$port) = @_;
856              
857 0   0       my $modules = $self->config_data('apachemodules')
858             || GBrowseGuessDirectories->apachemodules;
859              
860 0           my $user = $>;
861 0           my ($group) = $) =~ /^(\d+)/;
862 0 0         my $lockfile = $self->apache_version =~ /2\.4/ ? '' : "LockFile \"$dir/locks/accept.lock\"";
863              
864 0           return <
865             ServerName "localhost"
866             ServerRoot "$dir/conf"
867             $lockfile
868             PidFile "$dir/logs/apache2.pid"
869             ErrorLog "$dir/logs/error.log"
870             LogFormat "%h %l %u %t \\"%r\\" %>s %b" common
871             CustomLog "$dir/logs/access.log" common
872             LogLevel warn
873             User #$user
874             Group #$group
875              
876             Timeout 300
877             KeepAlive On
878             MaxKeepAliveRequests 100
879             KeepAliveTimeout 15
880             DefaultType text/plain
881             HostnameLookups Off
882              
883            
884              
885            
886             LoadModule log_config_module $modules/mod_log_config.so
887            
888              
889            
890             LoadModule cgid_module $modules/mod_cgid.so
891             ScriptSock "$dir/logs/cgisock"
892            
893              
894            
895             LoadModule authz_host_module $modules/mod_authz_host.so
896            
897              
898            
899             LoadModule env_module $modules/mod_env.so
900            
901              
902            
903             LoadModule alias_module $modules/mod_alias.so
904            
905              
906            
907             LoadModule dir_module $modules/mod_dir.so
908            
909              
910            
911             LoadModule mime_module $modules/mod_mime.so
912            
913              
914            
915              
916             TypesConfig "$dir/conf/mime.types"
917              
918             Listen $port
919             Include "$dir/conf/apache_gbrowse.conf"
920             END
921             }
922              
923             sub auth_conf {
924 0     0 0   my $self = shift;
925 0           my $new_auth = $self->apache_version =~ /2\.4/;
926 0 0         my $allow_all = $new_auth ? "Require all granted" : "Order allow,deny\n Allow from all";
927 0 0         my $deny_all = $new_auth ? "Require all denied" : "Order allow,deny\n Deny from all";
928 0           return ($allow_all,$deny_all);
929             }
930              
931             sub apache_version {
932 0 0   0 0   my $apache = GBrowseGuessDirectories->apache
933             or die "Could not find apache executable on this system. Can't figure out version number for config file.";
934 0           my $version = `$apache -v`;
935 0           my ($v) = $version =~ m!Apache/(\S+)!;
936 0           return $v;
937             }
938              
939             sub gbrowse_demo_conf {
940 0     0 0   my $self = shift;
941 0           my ($port,$dir) = @_;
942 0           my $blib = File::Spec->catfile($self->base_dir(),$self->blib);
943 0           my $inc = "$blib/lib:$blib/arch";
944 0           my $more = $self->added_to_INC;
945 0 0         $inc .= ":$more" if $more;
946              
947 0           my ($allow_all,$deny_all) = $self->auth_conf;
948              
949 0           my $additional_config = '';
950 0           my $namevirtualhost = "NameVirtualHost *:$port";
951              
952 0 0         if ($self->apache_version =~ /2\.4/) {
953 0           $namevirtualhost = '';
954 0           $additional_config = <
955             LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so
956             LoadModule mpm_prefork_module /usr/lib/apache2/modules/mod_mpm_prefork.so
957            
958             StartServers 5
959             MinSpareServers 5
960             MaxSpareServers 10
961             MaxRequestWorkers 150
962             MaxConnectionsPerChild 0
963            
964             END
965             }
966              
967 0           return <
968             $namevirtualhost
969             $additional_config
970            
971             ServerAdmin webmaster\@localhost
972             Alias "/i/" "$dir/tmp/images/"
973             ScriptAlias "/cgi-bin/" "$dir/cgi-bin/"
974            
975             DocumentRoot "$dir/htdocs/"
976            
977             Options FollowSymLinks
978             AllowOverride None
979            
980            
981             Options Indexes FollowSymLinks MultiViews
982             AllowOverride None
983             $allow_all
984            
985              
986            
987             SetEnv PERL5LIB $inc
988             SetEnv GBROWSE_MASTER GBrowse.conf
989             SetEnv GBROWSE_CONF $dir/conf
990             SetEnv GBROWSE_DOCS $dir/htdocs
991             SetEnv GBROWSE_ROOT /
992             AllowOverride None
993             Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
994             $allow_all
995            
996            
997             END
998             }
999              
1000             sub mime_conf {
1001 0     0 0   my $self = shift;
1002 0           return <
1003             image/gif gif
1004             image/jpeg jpeg jpg jpe
1005             image/png png
1006             image/svg+xml svg svgz
1007             text/css css
1008             text/html html htm shtml
1009             END
1010             }
1011              
1012             sub config_done {
1013 0     0 0   my $self = shift;
1014 0           my $done = $self->config_data('config_done');
1015 0 0         $self->config_data(config_done=>shift) if @_;
1016 0 0         warn "NOTE: Run ./Build reconfig to change existing configuration.\n" if $done;
1017 0           return $done;
1018             }
1019              
1020             sub registration_done {
1021 0     0 0   my $self = shift;
1022 0           my $done = $self->config_data('registration_done');
1023 0 0         $self->config_data(registration_done=>shift) if @_;
1024 0           return $done;
1025             }
1026              
1027             sub added_to_INC {
1028 0     0 0   my $self = shift;
1029 0           my @inc = grep {!/install_util/} eval {$self->_added_to_INC}; # not in published API
  0            
  0            
1030 0           my $lib_base = $self->install_destination('lib');
1031 0           my $arch_base = $self->install_destination('arch');
1032 0           my %standard = map {$_=>1} @INC;
  0            
1033 0 0         push @inc,$lib_base unless $standard{$lib_base};
1034 0 0         push @inc,$arch_base unless $standard{$arch_base};
1035 0 0         return @inc ? join(':',@inc) : '';
1036             }
1037              
1038             sub perl5lib {
1039 0     0 0   my $self = shift;
1040 0   0       return $self->added_to_INC || undef;
1041             }
1042              
1043             sub scriptdir {
1044 0     0 0   my $self = shift;
1045 0           my $id = $self->installdirs;
1046 0 0         my $scriptdir = $id eq 'core' ? 'installscript'
    0          
    0          
1047             :$id eq 'site' ? 'installsitebin'
1048             :$id eq 'vendor' ? 'installvendorbin'
1049             :'installsitebin';
1050 0           return $Config::Config{$scriptdir};
1051             }
1052              
1053             sub ownership_warning {
1054 0     0 0   my $self = shift;
1055 0           my ($path,$owner) = @_;
1056 0           warn "*** WARNING: Using sudo to change ownership of $path to '$owner'. You may be prompted for your login password ***\n";
1057 0           system "sudo chown -R $owner $path";
1058             }
1059              
1060             sub cgiurl {
1061 0     0 0   my $self = shift;
1062 0           my $cgibin = $self->config_data('cgibin');
1063 0           (my $cgiurl = $cgibin) =~ s!^.+/cgi-bin!/cgi-bin!;
1064 0           $cgiurl =~ s!^.+/CGI-Executables!/cgi-bin!; #Macs and their crazy paths
1065 0           return $cgiurl;
1066             }
1067              
1068             sub check_prereq {
1069 0     0 0   my $self = shift;
1070 0           my $result = $self->SUPER::check_prereq(@_);
1071 0 0         unless ($result) {
1072 0           $self->log_warn(<
1073             * Do not worry if some "recommended" prerequisites are missing. You can install *
1074             * them later if you need the features they provide. Do not proceed with the *
1075             * install if any of "REQUIRED" prerequisites are missing. *
1076             * *
1077             * The optional Safe::World module does not currently run on Perl 5.10 or *
1078             * higher, and so cannot be installed. *
1079              
1080             END
1081             }
1082 0           return $result;
1083             }
1084              
1085 0     0 0   sub asString { return 'GBrowse installer' }
1086              
1087             1;
1088              
1089             __END__