Command line settings should win out over settings in the config file
[working/Evergreen.git] / Open-ILS / src / support-scripts / eg_db_config.pl
1 #!/usr/bin/perl
2 # eg_db_config.pl -- configure Evergreen database settings and create schema
3 # vim:noet:ts=4:sw=4:
4 #
5 # Copyright (C) 2008 Equinox Software, Inc.
6 # Copyright (C) 2008 Laurentian University
7 # Author: Kevin Beswick <kevinbeswick00@gmail.com>
8 # Author: Dan Scott <dscott@laurentian.ca>
9 #
10 # This program is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU General Public License
12 # as published by the Free Software Foundation; either version 2
13 # of the License, or (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19
20 use strict; use warnings;
21 use XML::LibXML;
22 use File::Copy;
23 use Getopt::Long;
24 use File::Spec;
25 use File::Basename;
26
27 my ($dbhost, $dbport, $dbname, $dbuser, $dbpw, $help);
28 my $config_file = '';
29 my $build_db_sh = '';
30 my $bootstrap_file = '';
31 my $offline_file = '';
32 my $prefix = '';
33 my $sysconfdir = '';
34 my @services;
35
36 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
37
38 # Get the directory for this script
39 my $script_dir = dirname($0);
40
41 sub update_config {
42         # Puts command line specified settings into xml file
43         my ($services, $settings) = @_;
44
45         my $parser = XML::LibXML->new();
46         my $opensrf_config = $parser->parse_file($config_file);
47
48         if (@$services) {
49                 foreach my $service (@$services) {
50                         foreach my $key (keys %$settings) {
51                                 next unless $settings->{$key};
52                                 my(@node) = $opensrf_config->findnodes("//$service//database/$key/text()");
53                                 foreach(@node) {
54                                         $_->setData($settings->{$key});
55                                 }
56                         }
57
58                 }
59         }
60         else {
61                 foreach my $key (keys %$settings) {
62                         my(@node) = $opensrf_config->findnodes("//database/$key/text()");
63                         foreach(@node) {
64                                 $_->setData($settings->{$key});
65                         }
66                 }
67         }
68
69         my $timestamp = sprintf("%d.%d.%d.%d.%d.%d",
70                 $year + 1900, $mon +1, $mday, $hour, $min, $sec);
71         if (copy($config_file, "$config_file.$timestamp")) {
72                 print "Backed up original configuration file to '$config_file.$timestamp'\n";
73         } else {
74                 print STDERR "Unable to write to '$config_file.$timestamp'; bailed out.\n";
75     }
76
77         $opensrf_config->toFile($config_file) or
78                 die "ERROR: Failed to update the configuration file '$config_file'\n";
79 }
80
81 # write out the DB bootstrapping config
82 sub create_db_bootstrap {
83         my ($setup, $settings) = @_;
84
85     open(FH, '>', $setup) or die "Could not write database setup to $setup\n";
86
87         print "Writing database bootstrapping configuration to $setup\n";
88
89         printf FH "\$main::config{dsn} = 'dbi:Pg:host=%s;dbname=%s;port=%d';\n",
90                 $settings->{host}, $settings->{db}, $settings->{port};
91
92         printf FH "\$main::config{usr} = '%s';\n", $settings->{user};
93         printf FH "\$main::config{pw} = '%s';\n", $settings->{pw};
94         
95         print FH "\$main::config{index} = 'config.cgi';\n";
96     close(FH);
97 }
98
99 # write out the offline config
100 sub create_offline_config {
101         my ($setup, $settings) = @_;
102
103     open(FH, '>', $setup) or die "Could not write offline database setup to $setup\n";
104
105         print "Writing offline database configuration to $setup\n";
106
107         printf FH "\$main::config{base_dir} = '%s/var/data/offline/';\n", $prefix;
108         printf FH "\$main::config{bootstrap} = '%s/opensrf_core.xml';\n", $sysconfdir;
109
110         printf FH "\$main::config{dsn} = 'dbi:Pg:host=%s;dbname=%s;port=%d';\n",
111                 $settings->{host}, $settings->{db}, $settings->{port};
112
113         printf FH "\$main::config{usr} = '%s';\n", $settings->{user};
114         printf FH "\$main::config{pw} = '%s';\n", $settings->{pw};
115
116     close(FH);
117 }
118 # Extracts database settings from opensrf.xml
119 sub get_settings {
120         my $settings = shift;
121
122         my $host = "/opensrf/default/apps/open-ils.storage/app_settings/databases/database/host/text()";
123         my $port = "/opensrf/default/apps/open-ils.storage/app_settings/databases/database/port/text()";
124         my $dbname = "/opensrf/default/apps/open-ils.storage/app_settings/databases/database/db/text()";
125         my $user = "/opensrf/default/apps/open-ils.storage/app_settings/databases/database/user/text()";
126         my $pw = "/opensrf/default/apps/open-ils.storage/app_settings/databases/database/pw/text()";
127
128         my $parser = XML::LibXML->new();
129         my $opensrf_config = $parser->parse_file($config_file);
130
131         # If the user passed in settings at the command line,
132         # we don't want to override them
133         $settings->{host} = $settings->{host} || $opensrf_config->findnodes($host);
134         $settings->{port} = $settings->{port} || $opensrf_config->findnodes($port);
135         $settings->{db} = $settings->{db} || $opensrf_config->findnodes($dbname);
136         $settings->{user} = $settings->{user} || $opensrf_config->findnodes($user);
137         $settings->{pw} = $settings->{pw} || $opensrf_config->findnodes($pw);
138 }
139
140 # Creates the database schema by calling build-db.sh
141 sub create_schema {
142         my $settings = shift;
143
144         chdir(dirname($build_db_sh));
145         my $cmd = File::Spec->catfile('.', basename($build_db_sh)) . " " .
146                 $settings->{host} ." ".  $settings->{port} ." ". 
147                 $settings->{db} ." ".  $settings->{user} ." ". 
148                 $settings->{pw};
149         system($cmd);
150         chdir($script_dir);
151 }
152
153 my $bootstrap;
154 my $offline;
155 my $cschema;
156 my $uconfig;
157 my %settings;
158
159 GetOptions("create-schema" => \$cschema, 
160                 "create-bootstrap" => \$bootstrap,
161                 "create-offline" => \$offline,
162                 "update-config" => \$uconfig,
163                 "bootstrap-file=s" => \$bootstrap_file,
164                 "config-file=s" => \$config_file,
165                 "build-db-file=s" => \$build_db_sh,
166                 "service=s" => \@services,
167                 "user=s" => \$settings{'user'},
168                 "password=s" => \$settings{'pw'},
169                 "database=s" => \$settings{'db'},
170                 "hostname=s" => \$settings{'host'},
171                 "port=i" => \$settings{'port'}, 
172                 "help" => \$help
173 );
174
175 if (grep(/^all$/, @services)) {
176         @services = qw/reporter open-ils.cstore open-ils.storage open-ils.reporter-store/;
177 }
178
179 my $eg_config = File::Spec->catfile($script_dir, '../extras/eg_config');
180
181 if (!$config_file) { 
182         my @temp = `$eg_config --sysconfdir`;
183         chomp $temp[0];
184         $sysconfdir = $temp[0];
185         $config_file = File::Spec->catfile($sysconfdir, "opensrf.xml");
186 }
187
188 if (!$prefix) {
189         my @temp = `$eg_config --prefix`;
190         chomp $temp[0];
191         $prefix = $temp[0];
192 }
193
194 if (!$build_db_sh) {
195         $build_db_sh = File::Spec->catfile($script_dir, '../sql/Pg/build-db.sh');
196 }
197
198 if (!$bootstrap_file) {
199         $bootstrap_file = File::Spec->catfile($sysconfdir, 'live-db-setup.pl');
200 }
201
202 if (!$offline_file) {
203         $offline_file = File::Spec->catfile($sysconfdir, 'offline-config.pl');
204 }
205
206 unless (-e $build_db_sh) { die "Error: $build_db_sh does not exist. \n"; }
207 unless (-e $config_file) { die "Error: $config_file does not exist. \n"; }
208
209 if ($uconfig) { update_config(\@services, \%settings); }
210
211 # Get our settings from the config file
212 get_settings(\%settings);
213
214 if ($cschema) { create_schema(\%settings); }
215 if ($bootstrap) { create_db_bootstrap($bootstrap_file, \%settings); }
216 if ($offline) { create_offline_config($offline_file, \%settings); }
217
218 if ((!$cschema && !$uconfig && !$bootstrap && !$offline) || $help) {
219         print <<HERE;
220
221 SYNOPSIS
222     eg_db_config.pl [OPTION] ... [COMMAND] ... [CONFIG OPTIONS]
223
224 DESCRIPTION
225     Creates or recreates the Evergreen database schema based on the settings
226     in the opensrf.xml configuration file.
227
228     Manipulates the configuration file 
229
230 OPTIONS
231     --config-file
232         specifies the opensrf.xml file. Defaults to /openils/conf/opensrf.xml
233
234     --bootstrap-file
235         specifies the database bootstrap file required by the CGI setup
236         interface. Defaults to /openils/conf/live-db-setup.pl
237
238     --build-db-file
239         specifies the script that creates the database schema. Defaults to
240         Open-ILS/src/sql/pg/build-db.sh
241
242     --offline-file
243         specifies the offline database settings file required by the offline
244         data uploader. Defaults to /openils/conf/offline-config.pl
245
246 COMMANDS
247     --update-config
248         Configures Evergreen database settings in the file specified by
249         --build-db-file.  
250
251     --create-bootstrap
252         Creates the database bootstrap file required by the CGI setup interface
253
254     --create-offline
255         Creates the database setting file required by the offline data uploader
256
257     --create-schema
258         Creates the Evergreen database schema according to the settings in
259         the file specified by --config-file.  
260
261 SERVICE OPTIONS
262     --service
263         Specify "all" or one or more of the following services to update:
264             * reporter
265             * open-ils.cstore
266             * open-ils.storage
267             * open-ils.reporter-store
268     
269 DATABASE CONFIGURATION OPTIONS
270     --user            username for the database 
271
272     --password        password for the user 
273
274     --database        name of the database 
275
276     --hostname        name or address of the database host 
277
278     --port            port number for database access
279
280 EXAMPLES
281    This script is normally used during the initial installation and
282    configuration process.
283
284    For a single server install, or an install with one web/application
285    server and one database server, you will typically want to invoke this
286    script with a complete set of commands:
287
288    perl Open-ILS/src/support-scripts/eg_db_config.pl --update-config \
289        --service all --create-schema --create-bootstrap --create-offline \
290        --user evergreen --password evergreen --hostname localhost --port 5432 \
291        --database evergreen 
292
293    To update the configuration for a single service - for example, if you
294    replicated a database for reporting purposes - just issue the
295    --update-config command with the service identified and the changed
296    database parameters specified:
297
298    perl Open-ILS/src/support-scripts/eg_db_config.pl --update-config \
299        --service reporter --hostname foobar --password newpass
300
301 HERE
302 }