This is an automated email from the ASF dual-hosted git repository.

xyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new 957aa09  remove legacy znode when delete namespace or tenant 
forcefully (#11196)
957aa09 is described below

commit 957aa094c8a102c26619af4f3025e554dbbd7b69
Author: Aloys <[email protected]>
AuthorDate: Thu Jul 8 13:17:25 2021 +0800

    remove legacy znode when delete namespace or tenant forcefully (#11196)
    
    Fixes #11195
    
    ### Motivation
    
    Fix metadata not cleaned after delete namespace or tenant forcefully.
    
    ### Modifications
    **For force delete of namespace**
    Add delete for znode  `/managed-ledger/tenant/namespaces/persistent` , 
`/managed-ledger/tenant/namespaces/non-persistent` and  
`/managed-ledger/tenant/namespaces`  if exist.
    
    **For force delete of tenant**
    Add delete for znode  `/managed-ledger/tenant` if exist.
    
    ### Verifying this change
    
    This change added tests and can be verified as follows:
    
    Add new test for force delete of namespace in 
`AdminApiTest.testDeleteNamespaceForcefully`
    Extended test for force delete of tenant.
---
 .../apache/pulsar/broker/admin/AdminResource.java  |  2 +-
 .../pulsar/broker/admin/impl/NamespacesBase.java   | 18 +++++++
 .../pulsar/broker/admin/impl/TenantsBase.java      | 12 +++++
 .../apache/pulsar/broker/admin/AdminApiTest.java   | 56 ++++++++++++++++++++++
 4 files changed, 87 insertions(+), 1 deletion(-)

diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java
index c73c72d..4c3e374 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java
@@ -80,7 +80,7 @@ public abstract class AdminResource extends PulsarWebResource 
{
     private static final Logger log = 
LoggerFactory.getLogger(AdminResource.class);
     public static final String POLICIES_READONLY_FLAG_PATH = 
"/admin/flags/policies-readonly";
     public static final String PARTITIONED_TOPIC_PATH_ZNODE = 
"partitioned-topics";
-    private static final String MANAGED_LEDGER_PATH_ZNODE = "/managed-ledgers";
+    public static final String MANAGED_LEDGER_PATH_ZNODE = "/managed-ledgers";
 
     protected BookKeeper bookKeeper() {
         return pulsar().getBookKeeperClient();
diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
index ec9de23..f484b56 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
@@ -105,6 +105,7 @@ import org.apache.pulsar.common.util.FutureUtil;
 import 
org.apache.pulsar.metadata.api.MetadataStoreException.AlreadyExistsException;
 import 
org.apache.pulsar.metadata.api.MetadataStoreException.BadVersionException;
 import org.apache.pulsar.metadata.api.MetadataStoreException.NotFoundException;
+import org.apache.pulsar.zookeeper.LocalZooKeeperConnectionService;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
@@ -458,6 +459,23 @@ public abstract class NamespacesBase extends AdminResource 
{
                     deleteRecursive(namespaceResources(), 
globalPartitionedPath);
                 }
 
+                final String managedLedgerPath = 
joinPath(MANAGED_LEDGER_PATH_ZNODE, namespaceName.toString());
+                final String persistentDomain = managedLedgerPath + "/" + 
TopicDomain.persistent.value();
+                final String nonPersistentDomain = managedLedgerPath +  "/" + 
TopicDomain.non_persistent.value();
+
+                try {
+                    LocalZooKeeperConnectionService.deleteIfExists(
+                            pulsar().getLocalZkCache().getZooKeeper(), 
persistentDomain, -1);
+                    LocalZooKeeperConnectionService.deleteIfExists(
+                            pulsar().getLocalZkCache().getZooKeeper(), 
nonPersistentDomain, -1);
+                    LocalZooKeeperConnectionService.deleteIfExists(
+                            pulsar().getLocalZkCache().getZooKeeper(), 
managedLedgerPath, -1);
+                } catch (KeeperException | InterruptedException e) {
+                    // warn level log here since this failure has no side 
effect besides left a un-used metadata
+                    // and also will not affect the re-creation of namespace
+                    log.warn("[{}] Failed to remove managed-ledger for {}", 
clientAppId(), namespaceName, e);
+                }
+
                 // we have successfully removed all the ownership for the 
namespace, the policies znode can be deleted
                 // now
                 final String globalZkPolicyPath = path(POLICIES, 
namespaceName.toString());
diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java
 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java
index d81da0a..51b7fa7 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.pulsar.broker.admin.impl;
 
+import static 
org.apache.pulsar.broker.admin.AdminResource.MANAGED_LEDGER_PATH_ZNODE;
 import static 
org.apache.pulsar.broker.cache.ConfigurationCacheService.POLICIES;
 import com.google.common.collect.Lists;
 import io.swagger.annotations.ApiOperation;
@@ -50,6 +51,8 @@ import org.apache.pulsar.common.naming.NamedEntity;
 import org.apache.pulsar.common.policies.data.TenantInfo;
 import org.apache.pulsar.common.policies.data.TenantInfoImpl;
 import org.apache.pulsar.common.util.FutureUtil;
+import org.apache.pulsar.zookeeper.LocalZooKeeperConnectionService;
+import org.apache.zookeeper.KeeperException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -327,6 +330,15 @@ public class TenantsBase extends PulsarWebResource {
                 }
                 return null;
             }
+            final String managedLedgerPath = 
joinPath(MANAGED_LEDGER_PATH_ZNODE, tenant);
+            try {
+                LocalZooKeeperConnectionService.deleteIfExists(
+                        pulsar().getLocalZkCache().getZooKeeper(), 
managedLedgerPath, -1);
+            } catch (KeeperException | InterruptedException e) {
+                // warn level log here since this failure has no side effect 
besides left a un-used metadata
+                // and also will not affect the re-creation of tenant
+                log.warn("[{}] Failed to remove managed-ledger for {}", 
clientAppId(), tenant, e);
+            }
             // delete tenant normally
             internalDeleteTenant(asyncResponse, tenant);
 
diff --git 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java
index f16d2a6..69dfa05 100644
--- 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java
+++ 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.pulsar.broker.admin;
 
+import static 
org.apache.pulsar.broker.admin.AdminResource.MANAGED_LEDGER_PATH_ZNODE;
+import static org.apache.pulsar.common.policies.path.PolicyPath.joinPath;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -1219,6 +1221,9 @@ public class AdminApiTest extends 
MockedPulsarServiceBaseTest {
                     assertFalse(admin.tenants().getTenants().contains(tenant));
                 });
 
+        final String managedLedgerPathForTenant = 
joinPath(MANAGED_LEDGER_PATH_ZNODE, tenant);
+        
assertNull(pulsar.getLocalZkCache().getZooKeeper().exists(managedLedgerPathForTenant,
 false));
+
         admin.tenants().createTenant(tenant,
                 new TenantInfoImpl(Sets.newHashSet("role1", "role2"), 
Sets.newHashSet("test")));
         assertTrue(admin.tenants().getTenants().contains(tenant));
@@ -1227,6 +1232,57 @@ public class AdminApiTest extends 
MockedPulsarServiceBaseTest {
         // reset back to false
         pulsar.getConfiguration().setForceDeleteTenantAllowed(false);
         pulsar.getConfiguration().setForceDeleteNamespaceAllowed(false);
+
+    }
+
+    @Test
+    public void testDeleteNamespaceForcefully() throws Exception {
+        // allow forced deletion of namespaces
+        pulsar.getConfiguration().setForceDeleteNamespaceAllowed(true);
+
+        String tenant = "my-tenant";
+        assertFalse(admin.tenants().getTenants().contains(tenant));
+
+        // create tenant
+        admin.tenants().createTenant(tenant,
+                new TenantInfoImpl(Sets.newHashSet("role1", "role2"), 
Sets.newHashSet("test")));
+
+        assertTrue(admin.tenants().getTenants().contains(tenant));
+
+        // create namespace
+        String namespace = tenant + "/my-ns";
+        admin.namespaces().createNamespace("my-tenant/my-ns", 
Sets.newHashSet("test"));
+
+        assertEquals(admin.namespaces().getNamespaces(tenant), 
Lists.newArrayList("my-tenant/my-ns"));
+
+        // create topic
+        String topic = namespace + "/my-topic";
+        admin.topics().createPartitionedTopic(topic, 10);
+
+        assertFalse(admin.topics().getList(namespace).isEmpty());
+
+        try {
+            admin.namespaces().deleteNamespace(namespace, false);
+            fail("should have failed due to namespace not empty");
+        } catch (PulsarAdminException e) {
+            // Expected: cannot delete non-empty tenant
+        }
+
+        // delete namespace forcefully
+        admin.namespaces().deleteNamespace(namespace, true);
+        
assertFalse(admin.namespaces().getNamespaces(tenant).contains(namespace));
+        assertTrue(admin.namespaces().getNamespaces(tenant).isEmpty());
+
+        final String managedLedgerPath = joinPath(MANAGED_LEDGER_PATH_ZNODE, 
namespace);
+        final String persistentDomain = managedLedgerPath + "/" + 
TopicDomain.persistent.value();
+        final String nonPersistentDomain = managedLedgerPath + "/" + 
TopicDomain.non_persistent.value();
+
+        
assertNull(pulsar.getLocalZkCache().getZooKeeper().exists(persistentDomain, 
false));
+        
assertNull(pulsar.getLocalZkCache().getZooKeeper().exists(nonPersistentDomain, 
false));
+        
assertNull(pulsar.getLocalZkCache().getZooKeeper().exists(managedLedgerPath, 
false));
+
+        // reset back to false
+        pulsar.getConfiguration().setForceDeleteNamespaceAllowed(false);
     }
 
     @Test

Reply via email to