ソースを参照

AMBARI-9515. RU: need to be able to abort an upgrade, including HOLDING states (ncole)

Nate Cole 10 年 前
コミット
93e70b6ad7

+ 7 - 0
ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java

@@ -872,6 +872,13 @@ class ActionScheduler implements Runnable {
         cancelCommand.setReason(reason);
         actionQueue.enqueue(hostRoleCommand.getHostName(), cancelCommand);
       }
+
+      if (hostRoleCommand.getStatus().isHoldingState()) {
+        db.abortHostRole(hostRoleCommand.getHostName(),
+            hostRoleCommand.getRequestId(),
+            hostRoleCommand.getStageId(), hostRoleCommand.getRole().name());
+      }
+
       // If host role is an Action, we have to send an event
       if (hostRoleCommand.getRoleCommand().equals(RoleCommand.ACTIONEXECUTE)) {
         String clusterName = hostRoleCommand.getExecutionCommandWrapper().getExecutionCommand().getClusterName();

+ 0 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeService.java

@@ -108,7 +108,6 @@ public class UpgradeService extends BaseService {
 
     if (null != upgradeId) {
       mapIds.put(Resource.Type.Upgrade, upgradeId.toString());
-      mapIds.put(Resource.Type.Request, upgradeId.toString());
     }
 
     return createResource(Resource.Type.Upgrade, mapIds);

+ 51 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java

@@ -39,6 +39,7 @@ import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
@@ -105,6 +106,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   protected static final String UPGRADE_FROM_VERSION = "Upgrade/from_version";
   protected static final String UPGRADE_TO_VERSION = "Upgrade/to_version";
   protected static final String UPGRADE_DIRECTION = "Upgrade/direction";
+  protected static final String UPGRADE_REQUEST_STATUS = "Upgrade/request_status";
+  protected static final String UPGRADE_ABORT_REASON = "Upgrade/abort_reason";
 
   private static final Set<String> PK_PROPERTY_IDS = new HashSet<String>(
       Arrays.asList(UPGRADE_REQUEST_ID, UPGRADE_CLUSTER_NAME));
@@ -117,6 +120,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   private static final String COMMAND_PARAM_TASKS = "tasks";
   private static final String COMMAND_PARAM_STRUCT_OUT = "structured_out";
 
+  private static final String DEFAULT_REASON_TEMPLATE = "Aborting upgrade %s";
+
   private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<Resource.Type, String>();
 
   @Inject
@@ -289,7 +294,52 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
       Predicate predicate)
       throws SystemException, UnsupportedPropertyException,
       NoSuchResourceException, NoSuchParentResourceException {
-    throw new SystemException("Cannot update Upgrades");
+
+    Set<Map<String, Object>> requestMaps = request.getProperties();
+
+    if (requestMaps.size() > 1) {
+      throw new SystemException("Can only update one upgrade per request.");
+    }
+
+    // !!! above check ensures only one
+    final Map<String, Object> propertyMap = requestMaps.iterator().next();
+
+    String requestId = (String) propertyMap.get(UPGRADE_REQUEST_ID);
+    if (null == requestId) {
+      throw new IllegalArgumentException(String.format("%s is required", UPGRADE_REQUEST_ID));
+    }
+
+    String requestStatus = (String) propertyMap.get(UPGRADE_REQUEST_STATUS);
+    if (null == requestStatus) {
+      throw new IllegalArgumentException(String.format("%s is required", UPGRADE_REQUEST_STATUS));
+    }
+
+    HostRoleStatus status = HostRoleStatus.valueOf(requestStatus);
+    if (status != HostRoleStatus.ABORTED) {
+      throw new IllegalArgumentException(
+          String.format("Cannot set status %s, only %s is allowed",
+          status, HostRoleStatus.ABORTED));
+    }
+
+    String reason = (String) propertyMap.get(UPGRADE_ABORT_REASON);
+    if (null == reason) {
+      reason = String.format(DEFAULT_REASON_TEMPLATE, requestId);
+    }
+
+    ActionManager actionManager = getManagementController().getActionManager();
+    List<org.apache.ambari.server.actionmanager.Request> requests =
+        actionManager.getRequests(Collections.singletonList(Long.valueOf(requestId)));
+
+    org.apache.ambari.server.actionmanager.Request internalRequest = requests.get(0);
+
+    HostRoleStatus internalStatus = CalculatedStatus.statusFromStages(
+      internalRequest.getStages()).getStatus();
+
+    if (!internalStatus.isCompletedState()) {
+      actionManager.cancelRequest(internalRequest.getRequestId(), reason);
+    }
+
+    return getRequestStatus(null);
   }
 
   @Override

+ 33 - 0
ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java

@@ -2223,6 +2223,39 @@ public class TestActionScheduler {
 
   }
 
+  @Test
+  public void testAbortHolding() {
+    UnitOfWork unitOfWork = EasyMock.createMock(UnitOfWork.class);
+    ActionDBAccessor db = EasyMock.createMock(ActionDBAccessor.class);
+    ActionQueue aq = new ActionQueue();
+    Clusters fsm = EasyMock.createMock(Clusters.class);
+    Configuration conf = new Configuration(new Properties());
+
+    db.abortHostRole("h1", -1L, -1L, "AMBARI_SERVER_ACTION");
+    EasyMock.expectLastCall();
+
+    EasyMock.replay(db);
+
+    ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
+        new HostsMap((String) null),
+        unitOfWork, null, conf);
+
+    HostRoleCommand hrc1 = new HostRoleCommand("h1", Role.NAMENODE, null, RoleCommand.EXECUTE);
+    hrc1.setStatus(HostRoleStatus.COMPLETED);
+    HostRoleCommand hrc3 = new HostRoleCommand("h1", Role.AMBARI_SERVER_ACTION, null, RoleCommand.CUSTOM_COMMAND);
+    hrc3.setStatus(HostRoleStatus.HOLDING);
+    HostRoleCommand hrc4 = new HostRoleCommand("h1", Role.FLUME_HANDLER, null, RoleCommand.EXECUTE);
+    hrc4.setStatus(HostRoleStatus.PENDING);
+
+    List<HostRoleCommand> hostRoleCommands = Arrays.asList(hrc1, hrc3, hrc4);
+
+    scheduler.cancelHostRoleCommands(hostRoleCommands, "foo");
+
+    EasyMock.verify(db);
+
+  }
+
+
   public static class MockModule extends AbstractModule {
     @Override
     protected void configure() {

+ 24 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java

@@ -109,6 +109,7 @@ public class UpgradeResourceProviderTest {
 
     injector.getInstance(GuiceJpaInitializer.class);
 
+
     helper = injector.getInstance(OrmTestHelper.class);
 
     amc = injector.getInstance(AmbariManagementController.class);
@@ -458,9 +459,32 @@ public class UpgradeResourceProviderTest {
       assertEquals("downgrade", map.get("upgrade_direction"));
     }
 
+  }
+
+  @Test
+  public void testAbort() throws Exception {
+    org.apache.ambari.server.controller.spi.RequestStatus status = testCreateResources();
+
+    Set<Resource> createdResources = status.getAssociatedResources();
+    assertEquals(1, createdResources.size());
+    Resource res = createdResources.iterator().next();
+    Long id = (Long) res.getPropertyValue("Upgrade/request_id");
+    assertNotNull(id);
+    assertEquals(Long.valueOf(1), id);
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_ID, id.toString());
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_STATUS, "ABORTED");
+
+    UpgradeResourceProvider urp = createProvider(amc);
+
+    // !!! make sure we can.  actual abort is tested elsewhere
+    Request req = PropertyHelper.getUpdateRequest(requestProps, null);
+    urp.updateResources(req, null);
 
   }
 
+
   /**
    * @param amc
    * @return the provider