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