[Fedora-directory-commits] adminserver/admserv/cgi-src40 ds_remove.in, 1.8, 1.9

Richard Allen Megginson rmeggins at fedoraproject.org
Fri Feb 27 14:33:30 UTC 2009


Author: rmeggins

Update of /cvs/dirsec/adminserver/admserv/cgi-src40
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv21602/adminserver/admserv/cgi-src40

Modified Files:
	ds_remove.in 
Log Message:
Resolves: bug 480869
Bug Description: DS console: Can not delete DS instance
Reviewed by: nkinder (Thanks!)
Fix Description: As it turns out, my assumption that ds_remove in CGI mode also did the unregistration was false.  It is the console that does the unregistration, only after the ds_remove CGI returns success.  So, ds_remove needs to run with AdminSDK off, just like the other "special" CGI programs.  In addition, ds_remove needs to be more robust - if there is an error during ds_remove, you should be allowed to try again after fixing something.  However, the way the error handling worked did not differentiate between fatal errors and errors that could be ignored.  In order to do this properly, we need to propagate the errors back up to the top level (oh how I wish perl had real exception handling . . .).  The main type of error we need to ignore is file not found or process not found.  If we attempted to remove before and that attempt failed for some reason, and left a partial instance, we need to be able to run the remove command again, skipping over the things we shutdown or
  removed already, and clean up the stuff we need to remove.  This can also happen if you use the console to create a ds instance, and remove-ds.pl to remove the instance.  The instance will still show up in the console.  We need to be able to use the Remove Server in the console to remove the instance from the console, even through there is no physical instance on disk any more.  Since the console will only do the unregistration if the CGI returns success, we need to make sure the CGI returns success even though there is no instance on disk.  When ds_remove is run via ds_removal, it will do the unregistration.
I also took this opportunity to refactor the remove code, creating a removeDSInstance method in DSCreate.pm, and moving some of the other removal helper functions to Util.pm.  That simplified the code in both ds_remove and remove-ds.pl.
I added a remove-ds-admin.pl script - one of the problems that users have is that they run setup-ds-admin.pl, then hit some error (e.g. bad DNS setup), then find that they cannot restore the system to the state before they ran setup-ds-admin.pl.  remove-ds-admin.pl does this.
Finally, I added some man pages to the admin package for those commonly used commands.
Platforms tested: RHEL4
Flag Day: no
Doc impact: no 



Index: ds_remove.in
===================================================================
RCS file: /cvs/dirsec/adminserver/admserv/cgi-src40/ds_remove.in,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ds_remove.in	24 Feb 2009 14:25:42 -0000	1.8
+++ ds_remove.in	27 Feb 2009 14:33:28 -0000	1.9
@@ -24,106 +24,15 @@
 use File::Basename;
 use File::Path;
 use CGI qw(:cgi :oldstyle_urls);
+use POSIX qw(:errno_h);
+
 use Inf;
 use AdminUtil;
 use Util;
-use FileConn;
 use Resource;
+use DSCreate qw(removeDSInstance);
 
-# remove_tree($centry, $key, $instname, [$isparent, [$dontremove]])
-#     $centry: entry to look for the path to be removed
-#     $key: key to look for the path in the entry
-#     $instname: instance name "slapd-<ID>" to check the path
-#     $isparent: specify 1 to remove from the parent dir
-#     $dontremove: pattern not to be removed (e.g., ".db$")
-sub remove_tree
-{
-    my $centry = shift;
-    my $key = shift;
-    my $instname = shift;
-    my $isparent = shift;
-    my $dontremove = shift;
-
-    foreach my $path ( @{$centry->{$key}} )
-    {
-        my $rmdir = "";
-        my $rc = 0;
-        if ( 1 == $isparent )
-        {
-            $rmdir = dirname($path);
-        }
-        else
-        {
-            $rmdir = $path;
-        }
-        if ( -d $rmdir && $rmdir =~ /$instname/ )
-        {
-            if ( "" eq "$dontremove" )
-            {
-                $rc = rmtree($rmdir);
-                if ( 0 == $rc )
-                {
-                    print "Content-type: text/plain\n\n";
-                    print "NMC_ErrInfo: $rmdir was not removed.\n";
-                    print STDERR "Warning: $rmdir was not removed.\n";
-                }
-            }
-            else
-            {
-                # Skip the dontremove files
-                $rc = opendir(DIR, $rmdir);
-                if ($rc)
-                {
-                    while (defined(my $file = readdir(DIR)))
-                    {
-                        next if ( "$file" =~ /$dontremove/ );
-                        next if ( "$file" eq "." );
-                        next if ( "$file" eq ".." );
-                        my $rmfile = $rmdir . "/" . $file;
-                        my $rc0 = rmtree($rmfile);
-                        if ( 0 == $rc0 )
-                        {
-                            print "Content-type: text/plain\n\n";
-                            print "NMC_ErrInfo: $rmfile was not removed.\n";
-                            print STDERR "Warning: $rmfile was not removed.\n";
-                        }
-                    }
-                    closedir(DIR);
-                }
-                my $newrmdir = $rmdir . ".removed";
-                my $rc1 = 1;
-                if ( -d $newrmdir )
-                {
-                    $rc1 = rmtree($newrmdir);
-                    if ( 0 == $rc1 )
-                    {
-                        print "Content-type: text/plain\n\n";
-                        print "NMC_ErrInfo: $newrmdir was not removed.\n";
-                        print STDERR "Warning: $newrmdir was not removed.\n";
-                    }
-                }
-                if ( 0 < $rc1 )
-                {
-                    rename($rmdir, $newrmdir);
-                }
-            }
-        }
-    }
-}
-
-sub remove_pidfile
-{
-    my ($type, $instdir, $instname) = @_;
-
-    my $pattern = "^" . $type . ".*=";
-    my $pidline = `grep $pattern $instdir/start-slapd`;
-    chomp($pidline);
-    my ($key, $pidfile) = split(/=/, $pidline);
-    if ( -e $pidfile && $pidfile =~ /$instname/ )
-    {
-        unlink($pidfile);
-    }
-}
+print "Content-type: text/plain\n\n";
 
 my $res = new Resource("@propertydir@/ds_remove.res",
                        "@propertydir@/setup-ds-admin.res",
@@ -131,156 +40,105 @@
 
 # parse the input parameters
 my $query = new CGI;
-
-# call ds_newinst as a GET (GET or POST works, GET is simpler)
-$ENV{REQUEST_METHOD} = "GET";
-$ENV{QUERY_STRING} = $query->query_string();
-
+my @errs;
 my $force = $query->param('force');
+if (!defined($force) || (length($force) == 0)) {
+    $force = 1; # force use of force for CGI
+}
 my $instname = $query->param('InstanceName');
 my ($slapd, $inst) = split(/-/, $instname, 2);
-my $configdir = "@instconfigdir@/slapd-$inst";
+my $baseconfigdir = $ENV{DS_CONFIG_DIR} || "@instconfigdir@";
+my $configdir = "$baseconfigdir/slapd-$inst";
+my $status = 0;
 if ( ! -d $configdir )
 {
-    print "Content-type: text/plain\n\n";
-    print "NMC_ErrInfo: $configdir does not exist\n";
-    print "NMC_Status: 1\n";
-    print STDERR "Error: $configdir does not exist\n";
-    exit 1;
+    print "NMC_ErrInfo: could not read $configdir - Error: $!\n";
+    print STDERR "Error: could not read $configdir - Error: $!\n";
+    # look for error other than "not found"
+    if ($! != ENOENT) { # not found is ok
+        $status = 1;
+    }
+    if (!$force) {
+        exit 1;
+    }
 }
-my @errs;
+
+# NOTE about @errs - the return value will be an array
+# or an array of array refs - usually the last element
+# of the array will be the errno
+# first, gather the information needed by unregister
 my $inf = createInfFromConfig($configdir, $inst, \@errs);
 if (@errs)
 {
-    print "Content-type: text/plain\n\n";
     print "NMC_ErrInfo: ", $res->getText(@errs), "\n";
-    print "NMC_Status: 1\n";
     print STDERR "Error: ", $res->getText(@errs), "\n";
-    exit 1;
+    # look for error other than "not found"
+    if ($errs[-1] != ENOENT) { # not found is ok
+        $status = 1;
+    } 
+    if (!$force) {
+        exit 1;
+    }
+}
+if (!$inf) {
+    $inf = new Inf; # create empty one
+}
+
+# next, remove the instance
+ at errs = removeDSInstance($inst, $force);
+if (@errs) {
+    my $realerror;
+    for (@errs) {
+        my $text = $res->getText($_);
+        print "NMC_ErrInfo: $text\n";
+        print STDERR "Error: $text\n";
+        if ($_->[-1] != ENOENT) { # not found is ok
+            $realerror = 1;
+        }
+    }
+    if ($realerror) {
+        $status = 1;
+    }
+    if (!$force) {
+        exit 1;
+    }
 }
 
 # add the parmeters necessary to configure this DS to be managed
 # by the console and to be registered with the config DS - these
 # are usually passed in via the CGI params, or use reasonable
 # default values
-my $admConf = getAdmConf("@instconfigdir@/admin-serv");
+my $admConf = getAdmConf("$baseconfigdir/admin-serv");
 $inf->{General}->{ConfigDirectoryLdapURL} = $query->param('ldap_url') ||
     $admConf->{ldapurl};
 $inf->{General}->{AdminDomain} = $query->param('admin_domain') ||
     $admConf->{AdminDomain};
 
-# read the config file to find out the paths
-my $dseldif = "@instconfigdir@/$instname/dse.ldif";
-my $conn = new FileConn($dseldif);
-if (!$conn) {
-    print "Content-type: text/plain\n\n";
-    print "NMC_ErrInfo: Could not open $dseldif: Error: $!\n";
-    print "NMC_Status: 1\n";
-    print STDERR "Error: Could not open $dseldif: Error: $!\n";
-    exit 1;
-}
-
-my $dn = "cn=config";
-my $entry = $conn->search($dn, "base", "(cn=*)", 0);
-if (!$entry)
-{
-    print "Content-type: text/plain\n\n";
-    print "NMC_ErrInfo: Search $dn in $dseldif failed: $entry\n";
-    print "NMC_Status: 1\n";
-    print STDERR "Error: Search $dn in $dseldif failed: $entry\n";
-    exit 1;
-}
-
 # Unregister the server from the configuration ds
 # get config ds url from input or admconf
 # get admin id from input or admconf
-# must get admin password from input (PASSWORD_PIPE?)
 # get admin domain
 # config ds info
 if (!unregisterDSWithConfigDS($inst, \@errs, $inf) && !$force)
 {
-    print "Content-type: text/plain\n\n";
     print "NMC_ErrInfo: ", $res->getText(@errs), "\n";
-    print "NMC_Status: 1\n";
+    $status = 1;
     print STDERR "Error:", $res->getText(@errs), "\n";
-    exit 1;
-}
-
-$dn = "cn=config,cn=ldbm database,cn=plugins,cn=config";
-my $dbentry = $conn->search($dn, "base", "(cn=*)", 0);
-if (!$dbentry)
-{
-    print "Content-type: text/plain\n\n";
-    print "NMC_ErrInfo: Search $dn in $dseldif failed: $dbentry\n";
-    print "NMC_Status: 1\n";
-    print "Error: Search $dn in $dseldif failed: $dbentry\n";
-    exit 1;
-}
-$conn->close();
-
-# stop the server
-my $instdir = "";
-foreach my $path ( @{$entry->{"nsslapd-instancedir"}} )
-{
-    if ( -d $path )
-    {
-        my $prog = $path . "/stop-slapd";
-        if (-x $prog) {
-            $? = 0;
-            # run the CGI
-            my $output = `$prog 2>&1`;
-            my $status = $?;
-            if ($status) {
-                # Ignore the stop failure
-                print "Content-type: text/plain\n\n";
-                print "NMC_ErrInfo: Could not stop directory server: $output\n";
-                print STDERR "Warning: Could not stop directory server: $output\n";
-            }
-            $instdir = $path;    # need to use it later...
-        } elsif (!$force) {
-            print "Content-type: text/plain\n\n";
-            print "NMC_ErrInfo: The program $prog does not exist\n";
-            print "NMC_Status: 1\n";
-            print STDERR "Error: The program $prog does not exist\n";
-            exit 1;
-        }
+    if (!$force) {
+        exit 1;
     }
 }
-    
-# remove physical dirs/files
-remove_tree($dbentry, "nsslapd-directory", $instname, 1);
-remove_tree($dbentry, "nsslapd-db-logdirectory", $instname, 1);
-remove_tree($entry, "nsslapd-lockdir", $instname);
-remove_tree($entry, "nsslapd-tmpdir", $instname);
-remove_tree($entry, "nsslapd-bakdir", $instname, 1);
-remove_tree($entry, "nsslapd-errorlog", $instname, 1);
 
-# instance dir
-if ( -d $instdir && $instdir =~ /$instname/ )
+if ( 1 == isConfigDS($instname, "$baseconfigdir/admin-serv") )
 {
-    # clean up pid files (if any)
-    remove_pidfile("STARTPIDFILE", $instdir, $instname);
-    remove_pidfile("PIDFILE", $instdir, $instname);
-
-    if ( 1 == isConfigDS($instname, "@instconfigdir@/admin-serv") )
-    {
-        # if it is the Config DS, adm.conf and local.conf needs to be removed.
-        unlink("@instconfigdir@/admin-serv/adm.conf");
-        unlink("@instconfigdir@/admin-serv/local.conf");
-    }
-
-    my $rc = rmtree($instdir);
-    if ( 0 == $rc )
-    {
-        print "Content-type: text/plain\n\n";
-        print "NMC_ErrInfo: $instdir was not removed.\n";
-        print STDERR "Warning: $instdir was not removed.\n";
-    }
+    # if it is the Config DS, adm.conf and local.conf needs to be removed.
+    unlink("$baseconfigdir/admin-serv/adm.conf");
+    unlink("$baseconfigdir/admin-serv/local.conf");
 }
-# Finally, config dir
-remove_tree($entry, "nsslapd-schemadir", $instname, 1, "\.db\$");
 
-# if we got here, report success
-print "Content-type: text/plain\n\n";
-print "NMC_Status: 0\n";
 exit 0;
+
+END {
+    # report status, no matter where or when exit was called
+    print "NMC_Status: $status\n";
+}




More information about the Fedora-directory-commits mailing list