install.pl: Updated list of supported OSes and kernels
[~aditr/ofed_scripts.git] / uninstall.sh
1 #!/usr/bin/perl
2 #
3 # Copyright (c) 2014 Mellanox Technologies. All rights reserved.
4 #
5 # This Software is licensed under one of the following licenses:
6 #
7 # 1) under the terms of the "Common Public License 1.0" a copy of which is
8 #    available from the Open Source Initiative, see
9 #    http://www.opensource.org/licenses/cpl.php.
10 #
11 # 2) under the terms of the "The BSD License" a copy of which is
12 #    available from the Open Source Initiative, see
13 #    http://www.opensource.org/licenses/bsd-license.php.
14 #
15 # 3) under the terms of the "GNU General Public License (GPL) Version 2" a
16 #    copy of which is available from the Open Source Initiative, see
17 #    http://www.opensource.org/licenses/gpl-license.php.
18 #
19 # Licensee has the right to choose one of the above licenses.
20 #
21 # Redistributions of source code must retain the above copyright
22 # notice and one of the license notices.
23 #
24 # Redistributions in binary form must reproduce both the above copyright
25 # notice, one of the license notices in the documentation
26 # and/or other materials provided with the distribution.
27 #
28 # Description: OFED package uninstall script
29
30 use strict;
31 use warnings;
32 use Term::ANSIColor qw(:constants);
33 use File::Path;
34
35 my $PREREQUISIT = "2";
36 my $ERROR = "1";
37 my $NONOFEDRPMS = "3";
38
39 $ENV{"LANG"} = "en_US.UTF-8";
40
41 if ($<) {
42     print RED "Only root can run $0", RESET "\n";
43     exit $PREREQUISIT;
44 }
45
46 my $ofed_info = `which ofed_info 2> /dev/null`;
47 if (not $ofed_info) {
48     print "No OFED installation detected. Exiting ...\n";
49     exit $ERROR;
50 }
51
52 my @packages_to_uninstall = ();
53 my @dependant_packages_to_uninstall = ();
54 my %selected_for_uninstall = ();
55 my %non_ofed_for_uninstall = ();
56 my $unload_modules = 0;
57 my $force = 0;
58 my $verbose = 0;
59 my $quiet = 0;
60 my $dry_run = 0;
61 my $PACKAGE = `ofed_info -s | sed -e 's/://'`;
62 chomp $PACKAGE;
63 my $ofedlogs = "/tmp/$PACKAGE.$$.logs";
64 my $prefix = '/usr';
65 my $info = '/etc/infiniband/info';
66 my $rpm_flags = '';
67
68 sub usage
69 {
70    print GREEN;
71    print "\n Usage: $0 [--unload-modules] [-v|--verbose] [-q|--quiet] [--dry-run]\n";
72
73    print "\n           --unload-modules     Run /etc/init.d/openibd stop before uninstall";
74    print "\n           --force              Force uninstallation and remove packages that depends on OFED";
75    print "\n           -v|--verbose         Increase verbosity level";
76    print "\n           --dry-run            Print the list of packages to be uninstalled without actually uninstalling them";
77    print "\n           -q                   Set quiet - no messages will be printed";
78    print RESET "\n\n";
79 }
80
81 sub getch
82 {
83     my $c;
84     $c=getc(STDIN);
85
86     return $c;
87 }
88
89 sub log_and_exit
90 {
91     my $rc = shift @_;
92     if ($rc) {
93         print RED "See logs under $ofedlogs", RESET "\n";
94     }
95
96     exit $rc;
97 }
98
99 # Find in file $name line containing str1 and replace it with str2
100 # If str2 is empty the line with str1 will be removed
101 sub find_and_replace
102 {
103     my $name = shift @_;
104     my $str1 = shift @_;
105     my $str2 = shift @_;
106
107     my @lines;
108     open(FD, "$name");
109     while (<FD>) {
110         push @lines, $_;
111     }
112     close (FD);
113
114     open(FD, ">$name");
115     foreach my $line (@lines) {
116         chomp $line;
117         if ($line =~ /$str1/) {
118             print FD "$str2\n" if ($str2);
119         } else {
120             print FD "$line\n";
121         }
122     }
123     close (FD);
124 }
125
126 sub is_installed
127 {
128     my $res = 0;
129     my $name = shift @_;
130
131     system("rpm -q $name > /dev/null 2>&1");
132     $res = $? >> 8;
133
134     return not $res;
135 }
136
137 sub mark_for_uninstall
138 {
139     my $package = shift @_;
140     if (not $selected_for_uninstall{$package}) {
141         push (@dependant_packages_to_uninstall, "$package");
142         my $pname = $package;
143         $pname =~ s@-[0-9].*@@g;
144         $pname =~ s@-dev.*@@g;
145         $selected_for_uninstall{$package} = 1;
146         if ( `ofed_info 2>/dev/null | grep -i $pname 2>/dev/null` eq "" and $pname !~ /ofed-scripts/) {
147             $non_ofed_for_uninstall{$package} = 1;
148         }
149     }
150 }
151
152 sub get_requires
153 {
154     my $package = shift @_;
155
156     # Strip RPM version
157     $package = `rpm -q --queryformat "[%{NAME}]" $package`;
158     chomp $package;
159 warn("$package\n");
160     my @what_requires = `/bin/rpm -q --whatrequires $package 2>&1 | grep -v "no package requires" 2> /dev/null`;
161
162     for my $pack_req (@what_requires) {
163         chomp $pack_req;
164         print "get_requires: $package is required by $pack_req\n" if ($verbose);
165         get_requires($pack_req);
166         mark_for_uninstall($pack_req);
167     }
168 }
169
170 sub uninstall
171 {
172     my $res = 0;
173     my $sig = 0;
174     my $cnt = 0;
175     my @installed_rpms = `ofed_info | grep -A999 '^-' 2> /dev/null | grep -v '^-'`;
176     my @other_ofed_rpms = `rpm -qa 2> /dev/null | grep -E "libibverbs|libmlx|rdma|ofed|openib|kernel-ib|rds-tools|rds-devel|ib-bonding|infiniband|libfabric|fabtests|srp_daemon"`;
177     my $cmd = "rpm -e --allmatches --nodeps $rpm_flags";
178
179     for my $package (@other_ofed_rpms) {
180         chomp $package;
181         my $pname = $package;
182         $pname =~ s@-[0-9].*@@g;
183         $pname =~ s@-dev.*@@g;
184         if ( `ofed_info 2>/dev/null | grep -i $pname 2>/dev/null` eq "" and $pname !~ /ofed-scripts/ ) {
185             $non_ofed_for_uninstall{$package} = 1;
186         }
187     }
188
189     if (is_installed("ofed")) {
190         # W/A for SLES 10 SP4 in-box ofed RPM uninstall issue
191         $cmd .= " --noscripts";
192     }
193
194     for my $package (@installed_rpms, @other_ofed_rpms) {
195         chomp $package;
196         next if ($package eq "mpi-selector");
197         if (is_installed($package)) {
198             push (@packages_to_uninstall, $package);
199             $selected_for_uninstall{$package} = 1;
200         }
201     }
202
203     for my $package (@packages_to_uninstall) {
204         get_requires($package);
205     }
206
207     if (not $force and keys %non_ofed_for_uninstall) {
208         print "\nError: One or more packages depends on OFED.\nThose packages should be removed before uninstalling OFED:\n\n";
209         print join(" ", (keys %non_ofed_for_uninstall)) . "\n\n";
210         print "To force uninstallation use '--force' flag.\n";
211         exit $NONOFEDRPMS;
212     }
213
214     for my $package (@packages_to_uninstall, @dependant_packages_to_uninstall) {
215         if (is_installed("$package")) {
216             $cmd .= " $package";
217             $cnt ++;
218         }
219     }
220
221     if ($cnt) {
222         print "\n$cmd\n" if (not $quiet);
223         open (LOG, "+>$ofedlogs/ofed_uninstall.log");
224         print LOG "$cmd\n";
225         close LOG;
226
227         if (not $dry_run) {
228             system("$cmd >> $ofedlogs/ofed_uninstall.log 2>&1");
229             $res = $? >> 8;
230             $sig = $? & 127;
231             if ($sig or $res) {
232                 print RED "Failed to uninstall the previous installation", RESET "\n";
233                 print RED "See $ofedlogs/ofed_uninstall.log", RESET "\n";
234                 log_and_exit $ERROR;
235             }
236         }
237     }
238 }
239
240 ######### MAIN #########
241 while ( $#ARGV >= 0 ) {
242
243    my $cmd_flag = shift(@ARGV);
244
245     if ($cmd_flag eq "--unload-modules") {
246         $unload_modules = 1;
247     } elsif ($cmd_flag eq "--force") {
248         $force = 1;
249     } elsif ($cmd_flag eq "-v" or $cmd_flag eq "--verbose") {
250         $verbose = 1;
251     } elsif ($cmd_flag eq "-q" or $cmd_flag eq "--quiet") {
252         $quiet = 1;
253     } elsif ($cmd_flag eq "--dry-run") {
254         $dry_run = 1;
255     } elsif ($cmd_flag eq "-h" or $cmd_flag eq "--help") {
256         usage();
257         exit 0;
258     }
259 }
260
261 if (not $force) {
262     print "\nThis program will uninstall all $PACKAGE packages on your machine.\n\n";
263     print "Do you want to continue?[y/N]:";
264     my $ans = getch();
265     print "\n";
266
267     if ($ans !~ m/[yY]/) {
268         exit $ERROR;
269     }
270 }
271
272 mkpath([$ofedlogs]);
273
274 if (-e $info) {
275     open(INFO, "$info|") or die "Failed to run: $info. Error $!\n";;
276     while(<INFO>) {
277         if (/^prefix=/) {
278             $prefix = (split '=', $_)[1];
279             last;
280         }
281     }
282     close(INFO);
283 } else {
284     $prefix = $0;
285     $prefix =~ s/(\/sbin).*//g;
286 }
287
288 if ($unload_modules) {
289     print "Unloading kernel modules...\n" if (not $quiet);
290
291     if (not $dry_run) {
292         system("/etc/init.d/openibd stop >> $ofedlogs/openibd_stop.log 2>&1");
293         my $res = $? >> 8;
294         my $sig = $? & 127;
295         if ($sig or $res) {
296             print RED "Failed to unload kernel modules", RESET "\n";
297             log_and_exit $ERROR;
298         }
299     }
300 }
301
302 uninstall();
303
304 exit 0 if ($dry_run);
305
306 if (-e "/etc/modprobe.d/ipv6") {
307    find_and_replace ("/etc/modprobe.d/ipv6", "# install ipv6 /bin/true", "install ipv6 /bin/true");
308 }
309
310 print "Uninstall finished successfully\n" if (not $quiet);