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

DomGarguilo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo.git

commit 2c9f94f7d011103389f90ba40b0c61acdd0b5c1e
Merge: 403c99ddf9 2b2c3c8daa
Author: Dom G <[email protected]>
AuthorDate: Tue Oct 20 10:59:23 2026 -0400

    Merge branch '2.1' into main

 .../accumulo/miniclusterImpl/MiniAccumuloClusterImpl.java     | 11 ++++++++---
 .../main/java/org/apache/accumulo/test/upgrade/UpgradeIT.java |  3 ++-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --cc 
minicluster/src/main/java/org/apache/accumulo/miniclusterImpl/MiniAccumuloClusterImpl.java
index 9a4c4fd9bc,6e5af2ad17..8dba95d87f
--- 
a/minicluster/src/main/java/org/apache/accumulo/miniclusterImpl/MiniAccumuloClusterImpl.java
+++ 
b/minicluster/src/main/java/org/apache/accumulo/miniclusterImpl/MiniAccumuloClusterImpl.java
@@@ -60,9 -61,11 +60,10 @@@ import java.util.stream.Collectors
  import java.util.stream.Stream;
  
  import org.apache.accumulo.cluster.AccumuloCluster;
+ import org.apache.accumulo.core.Constants;
  import org.apache.accumulo.core.client.Accumulo;
  import org.apache.accumulo.core.client.AccumuloClient;
 -import org.apache.accumulo.core.client.AccumuloException;
 -import org.apache.accumulo.core.client.AccumuloSecurityException;
 +import org.apache.accumulo.core.client.TableNotFoundException;
  import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
  import org.apache.accumulo.core.clientImpl.ClientContext;
  import org.apache.accumulo.core.conf.AccumuloConfiguration;
@@@ -620,15 -613,25 +621,19 @@@ public class MiniAccumuloClusterImpl im
      log.info("Starting MAC against instance {} and zookeeper(s) {}.", 
config.getInstanceName(),
          config.getZooKeepers());
  
-     control.start(ServerType.TABLET_SERVER);
-     control.start(ServerType.SCAN_SERVER);
 -    try (var reservation = SingletonManager.getClientReservation()) {
 -      var zrw = new ZooReaderWriter(getSiteConfiguration());
 -      String instanceNamePath =
 -          Constants.ZROOT + Constants.ZINSTANCES + "/" + 
config.getInstanceName();
 -      byte[] bytes = zrw.getData(instanceNamePath);
 -      InstanceId iid = InstanceId.of(new String(bytes, UTF_8));
--
 +    try {
+       // fail fast before starting servers - they'll fail to start if this 
node exists already
 -      final String upgradePrepNode = ZooUtil.getRoot(iid) + 
Constants.ZPREPARE_FOR_UPGRADE;
 -      if (zrw.exists(upgradePrepNode)) {
 -        throw new IllegalStateException(
 -            "Cannot start, instance is prepared for upgrade: " + 
upgradePrepNode + " exists");
++      if 
(getServerContext().getZooSession().asReader().exists(Constants.ZPREPARE_FOR_UPGRADE))
 {
++        throw new IllegalStateException("Cannot start, instance is prepared 
for upgrade: "
++            + Constants.ZPREPARE_FOR_UPGRADE + " exists");
+       }
 -      SetGoalState.setGoalState(zrw, ZooUtil.getRoot(iid), 
ManagerGoalState.NORMAL);
 +      SetGoalState.setGoalState(getServerContext(), ManagerGoalState.NORMAL);
      } catch (KeeperException e) {
        throw new IllegalStateException("Could not set manager goal state", e);
      }
  
+     control.start(ServerType.TABLET_SERVER);
++    control.start(ServerType.SCAN_SERVER);
      control.start(ServerType.MANAGER);
      control.start(ServerType.GARBAGE_COLLECTOR);
  
diff --cc test/src/main/java/org/apache/accumulo/test/upgrade/UpgradeIT.java
index ce18e3f606,0000000000..10892c69bb
mode 100644,000000..100644
--- a/test/src/main/java/org/apache/accumulo/test/upgrade/UpgradeIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/upgrade/UpgradeIT.java
@@@ -1,175 -1,0 +1,176 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   https://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.accumulo.test.upgrade;
 +
 +import static org.junit.jupiter.api.Assertions.assertThrows;
 +import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
 +import static org.junit.jupiter.api.Assertions.assertTrue;
 +
 +import java.io.IOException;
 +import java.time.Duration;
 +
 +import org.apache.accumulo.core.Constants;
 +import org.apache.accumulo.core.cli.ServerOpts;
 +import org.apache.accumulo.core.client.admin.servers.ServerId;
 +import org.apache.accumulo.core.conf.Property;
 +import org.apache.accumulo.core.conf.SiteConfiguration;
 +import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
 +import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
 +import org.apache.accumulo.core.lock.ServiceLock;
 +import org.apache.accumulo.core.lock.ServiceLockPaths.AddressSelector;
 +import org.apache.accumulo.core.lock.ServiceLockPaths.ResourceGroupPredicate;
 +import org.apache.accumulo.core.zookeeper.ZooSession;
 +import org.apache.accumulo.manager.Manager;
 +import org.apache.accumulo.minicluster.ServerType;
 +import org.apache.accumulo.miniclusterImpl.MiniAccumuloConfigImpl;
 +import org.apache.accumulo.server.AbstractServer;
 +import org.apache.accumulo.server.ServerContext;
 +import org.apache.accumulo.test.harness.AccumuloClusterHarness;
 +import org.apache.accumulo.test.util.Wait;
 +import org.apache.hadoop.conf.Configuration;
 +import org.junit.jupiter.api.Test;
 +
 +public class UpgradeIT extends AccumuloClusterHarness {
 +
 +  private class ServerThatWontStart extends AbstractServer {
 +
 +    protected ServerThatWontStart(String[] args) {
 +      super(ServerId.Type.TABLET_SERVER, new ServerOpts(), (conf, rgid) -> 
new ServerContext(conf),
 +          args);
 +    }
 +
 +    @Override
 +    public void run() {}
 +
 +    @Override
 +    public ServiceLock getLock() {
 +      return null;
 +    }
 +
 +    @Override
 +    public void startServiceLockVerificationThread() {}
 +
 +    @Override
 +    public void close() {}
 +
 +  }
 +
 +  // This class exists because Manager constructor is not visible
 +  private class TestManager extends Manager {
 +
 +    protected TestManager(String[] args) throws IOException {
 +      super(new ServerOpts(), (conf, rgid) -> new ServerContext(conf), args);
 +    }
 +
 +    @Override
 +    public void startServiceLockVerificationThread() {}
 +
 +    @Override
 +    public void close() {}
 +
 +  }
 +
 +  @Override
 +  protected Duration defaultTimeout() {
 +    return Duration.ofMinutes(5);
 +  }
 +
 +  @Override
 +  public void configureMiniCluster(MiniAccumuloConfigImpl cfg, Configuration 
hadoopCoreSite) {
 +    cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
 +  }
 +
 +  @Test
 +  public void testServersWontStart() throws Exception {
 +    // Constants.ZPREPARE_FOR_UPGRADE is created by 'accumulo upgrade 
--prepare'
 +    // which is run when the user wants to shutdown an instance in preparation
 +    // to upgrade it. When this node exists, no servers should start. There is
 +    // no ability to create this node in ZooKeeper before MAC starts for this
 +    // test, so we will create the node after MAC starts, then try to restart
 +    // MAC.
 +
 +    final ZooSession zs = getServerContext().getZooSession();
 +    final ZooReaderWriter zrw = zs.asReaderWriter();
 +    final String upgradePath = Constants.ZPREPARE_FOR_UPGRADE;
 +    zrw.putPersistentData(upgradePath, new byte[0], NodeExistsPolicy.SKIP);
 +
 +    getCluster().stop();
 +
 +    getCluster().getClusterControl().startAllServers(ServerType.ZOOKEEPER);
 +
 +    // Confirm all servers down
 +    Wait.waitFor(() -> getServerContext().getServerPaths()
 +        .getCompactor(ResourceGroupPredicate.ANY, AddressSelector.all(), 
true).size() == 0);
 +    Wait.waitFor(() -> 
getServerContext().getServerPaths().getGarbageCollector(true) == null);
 +    Wait.waitFor(() -> getServerContext().getServerPaths().getManager(true) 
== null);
 +    Wait.waitFor(() -> getServerContext().getServerPaths()
 +        .getScanServer(ResourceGroupPredicate.ANY, AddressSelector.all(), 
true).size() == 0);
 +    Wait.waitFor(() -> getServerContext().getServerPaths()
 +        .getTabletServer(ResourceGroupPredicate.ANY, AddressSelector.all(), 
true).size() == 0);
 +
-     assertThrows(AssertionError.class,
++    var startIse = assertThrows(IllegalStateException.class,
 +        () -> assertTimeoutPreemptively(Duration.ofMinutes(2), () -> 
getCluster().start()));
++    assertTrue(startIse.getMessage().startsWith("Cannot start, instance is 
prepared for upgrade"));
 +
 +    // Confirm no servers started
 +    Wait.waitFor(() -> getServerContext().getServerPaths()
 +        .getCompactor(ResourceGroupPredicate.ANY, AddressSelector.all(), 
true).size() == 0);
 +    Wait.waitFor(() -> 
getServerContext().getServerPaths().getGarbageCollector(true) == null);
 +    Wait.waitFor(() -> getServerContext().getServerPaths().getManager(true) 
== null);
 +    Wait.waitFor(() -> getServerContext().getServerPaths()
 +        .getScanServer(ResourceGroupPredicate.ANY, AddressSelector.all(), 
true).size() == 0);
 +    Wait.waitFor(() -> getServerContext().getServerPaths()
 +        .getTabletServer(ResourceGroupPredicate.ANY, AddressSelector.all(), 
true).size() == 0);
 +
 +    // Validate the exception from the servers
 +    System.setProperty(SiteConfiguration.ACCUMULO_PROPERTIES_PROPERTY,
 +        "file://" + getCluster().getAccumuloPropertiesPath());
 +    try {
 +      IllegalStateException ise =
 +          assertThrows(IllegalStateException.class, () -> new 
ServerThatWontStart(new String[0]));
 +      assertTrue(ise.getMessage()
 +          .startsWith("Instance has been prepared for upgrade to a minor or 
major version"));
 +    } finally {
 +      System.clearProperty(SiteConfiguration.ACCUMULO_PROPERTIES_PROPERTY);
 +    }
 +
 +  }
 +
 +  @Test
 +  public void testUpgradeManagerFailure() throws Exception {
 +    // Test that the Manager fails when an upgrade is needed,
 +    // but UpgradeProgressTracker.initialize was never called.
 +
 +    getCluster().stop();
 +    getCluster().getClusterControl().startAllServers(ServerType.ZOOKEEPER);
 +
 +    ServerContext ctx = getCluster().getServerContext();
 +    UpgradeUtilIT.downgradePersistentVersion(ctx);
 +
 +    System.setProperty(SiteConfiguration.ACCUMULO_PROPERTIES_PROPERTY,
 +        "file://" + getCluster().getAccumuloPropertiesPath());
 +
 +    try (TestManager mgr = new TestManager(new String[0])) {
 +      IllegalStateException ise = assertThrows(IllegalStateException.class, 
() -> mgr.runServer());
 +      assertTrue(ise.getMessage().equals("Upgrade not started, " + 
Constants.ZUPGRADE_PROGRESS
 +          + " node does not exist. Did you run 'accumulo upgrade --start'?"));
 +    }
 +  }
 +
 +}

Reply via email to