commit before sqlradius upgrade so sqlradius upgrade errors from permissions can...
[freeside.git] / FS / bin / freeside-upgrade
1 #!/usr/bin/perl -w
2
3 use strict;
4 use vars qw($opt_d $opt_s $opt_q $opt_v $opt_r);
5 use vars qw($DEBUG $DRY_RUN);
6 use Getopt::Std;
7 use DBIx::DBSchema 0.31;
8 use FS::UID qw(adminsuidsetup checkeuid datasrc );  #getsecrets);
9 use FS::CurrentUser;
10 use FS::Schema qw( dbdef dbdef_dist reload_dbdef );
11 use FS::Misc::prune qw(prune_applications);
12 use FS::Conf;
13 use FS::Record qw(qsearch);
14 use FS::Upgrade qw(upgrade upgrade_sqlradius);
15
16 my $start = time;
17
18 die "Not running uid freeside!" unless checkeuid();
19
20 getopts("dqrs");
21
22 $DEBUG = !$opt_q;
23 #$DEBUG = $opt_v;
24
25 $DRY_RUN = $opt_d;
26
27 my $user = shift or die &usage;
28 $FS::CurrentUser::upgrade_hack = 1;
29 $FS::UID::callback_hack = 1;
30 my $dbh = adminsuidsetup($user);
31 $FS::UID::callback_hack = 0;
32
33 #needs to match FS::Schema...
34 my $dbdef_file = "%%%FREESIDE_CONF%%%/dbdef.". datasrc;
35
36 dbdef_create($dbh, $dbdef_file);
37
38 delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
39 reload_dbdef($dbdef_file);
40
41 warn "Upgrade startup completed in ". (time-$start). " seconds\n"; # if $DEBUG;
42 $start = time;
43
44 $DBIx::DBSchema::DEBUG = $DEBUG;
45 $DBIx::DBSchema::Table::DEBUG = $DEBUG;
46 $DBIx::DBSchema::Index::DEBUG = $DEBUG;
47
48 my @bugfix = ();
49
50 if (dbdef->table('cust_main')->column('agent_custid') && ! $opt_s) { 
51   push @bugfix,
52     "UPDATE cust_main SET agent_custid = NULL where agent_custid = ''";
53
54   push @bugfix,
55     "UPDATE h_cust_main SET agent_custid = NULL where agent_custid = ''"
56       if (dbdef->table('h_cust_main')); 
57 }
58
59 #you should have run fs-migrate-part_svc ages ago, when you upgraded
60 #from 1.3 to 1.4... if not, it needs to be hooked into -upgrade here or
61 #you'll lose all the part_svc settings it migrates to part_svc_column
62
63 if ( $DRY_RUN ) {
64   print
65     join(";\n", @bugfix, dbdef->sql_update_schema( dbdef_dist(datasrc), $dbh ) ). ";\n";
66   exit;
67 } else {
68   foreach my $statement ( @bugfix ) {
69     $dbh->do( $statement )
70       or die "Error: ". $dbh->errstr. "\n executing: $statement";
71   }
72
73   warn "Pre-schema change upgrades completed in ". (time-$start). " seconds\n"; # if $DEBUG;
74   $start = time;
75
76   dbdef->update_schema( dbdef_dist(datasrc), $dbh );
77 }
78
79 warn "Schema upgrade completed in ". (time-$start). " seconds\n"; # if $DEBUG;
80 $start = time;
81
82 my $hashref = {};
83 $hashref->{dry_run} = 1 if $DRY_RUN;
84 $hashref->{debug} = 1 if $DEBUG && $DRY_RUN;
85 prune_applications($hashref) unless $opt_s;
86
87 warn "Application pruning completed in ". (time-$start). " seconds\n"; # if $DEBUG;
88 $start = time;
89
90 print "\n" if $DRY_RUN;
91
92 if ( $dbh->{Driver}->{Name} =~ /^mysql/i && ! $opt_s ) {
93
94   foreach my $table (qw( svc_acct svc_phone )) {
95
96     my $sth = $dbh->prepare(
97       "SELECT COUNT(*) FROM duplicate_lock WHERE lockname = '$table'"
98     ) or die $dbh->errstr;
99
100     $sth->execute or die $sth->errstr;
101
102     unless ( $sth->fetchrow_arrayref->[0] ) {
103
104       $sth = $dbh->prepare(
105         "INSERT INTO duplicate_lock ( lockname ) VALUES ( '$table' )"
106       ) or die $dbh->errstr;
107
108       $sth->execute or die $sth->errstr;
109
110     }
111
112   }
113
114   warn "Duplication lock creation completed in ". (time-$start). " seconds\n"; # if $DEBUG;
115   $start = time;
116
117 }
118
119 $dbh->commit or die $dbh->errstr;
120
121 dbdef_create($dbh, $dbdef_file);
122
123 $dbh->disconnect or die $dbh->errstr;
124
125 delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
126 $FS::UID::AutoCommit = 0;
127 $FS::UID::callback_hack = 1;
128 $dbh = adminsuidsetup($user);
129 $FS::UID::callback_hack = 0;
130 unless ( $DRY_RUN || $opt_s ) {
131   my $dir = "%%%FREESIDE_CONF%%%/conf.". datasrc;
132   if (!scalar(qsearch('conf', {}))) {
133     my $error = FS::Conf::init_config($dir);
134     if ($error) {
135       warn "CONFIGURATION UPGRADE FAILED\n";
136       $dbh->rollback or die $dbh->errstr;
137       die $error;
138     }
139   }
140 }
141 $dbh->commit or die $dbh->errstr;
142 $dbh->disconnect or die $dbh->errstr;
143
144 $dbh = adminsuidsetup($user);
145
146 warn "Re-initialization with updated schema completed in ". (time-$start). " seconds\n"; # if $DEBUG;
147 $start = time;
148
149 upgrade()
150   unless $DRY_RUN || $opt_s;
151
152 $dbh->commit or die $dbh->errstr;
153
154 warn "Table updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
155 $start = time;
156
157 upgrade_sqlradius()
158   unless $DRY_RUN || $opt_s || $opt_r;
159
160 warn "SQL RADIUS updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
161 $start = time;
162
163 $dbh->commit or die $dbh->errstr;
164 $dbh->disconnect or die $dbh->errstr;
165
166 warn "Final commit and disconnection completed in ". (time-$start). " seconds; upgrade done!\n"; # if $DEBUG;
167
168 ###
169
170 sub dbdef_create { # reverse engineer the schema from the DB and save to file
171   my( $dbh, $file ) = @_;
172   my $dbdef = new_native DBIx::DBSchema $dbh;
173   $dbdef->save($file);
174 }
175
176 sub usage {
177   die "Usage:\n  freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ] user\n"; 
178 }
179
180 =head1 NAME
181
182 freeside-upgrade - Upgrades database schema for new freeside verisons.
183
184 =head1 SYNOPSIS
185
186   freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ]
187
188 =head1 DESCRIPTION
189
190 Reads your existing database schema and updates it to match the current schema,
191 adding any columns or tables necessary.
192
193 Also performs other upgrade functions:
194
195 =over 4
196
197 =item Calls FS:: Misc::prune::prune_applications (probably unnecessary every upgrade, but simply won't find any records to change)
198
199 =item If necessary, moves your configuration information from the filesystem in /usr/local/etc/freeside/conf.<datasrc> to the database.
200
201 =back
202
203   [ -d ]: Dry run; output SQL statements (to STDOUT) only, but do not execute
204           them.
205
206   [ -q ]: Run quietly.  This may become the default at some point.
207
208   [ -r ]: Skip sqlradius updates.  Useful for occassions where the sqlradius
209           databases may be inaccessible.
210
211   [ -v ]: Run verbosely, sending debugging information to STDERR.  This is the
212           current default.
213
214   [ -s ]: Schema changes only.  Useful for Pg/slony slaves where the data
215           changes will be replicated from the Pg/slony master.
216
217 =head1 SEE ALSO
218
219 =cut
220