You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ds...@apache.org on 2013/12/20 20:01:01 UTC

git commit: AMBARI-4145 Ability to restart a component (dsen)

Updated Branches:
  refs/heads/trunk 26dee15ee -> d60ee2cb1


AMBARI-4145 Ability to restart a component (dsen)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d60ee2cb
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d60ee2cb
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d60ee2cb

Branch: refs/heads/trunk
Commit: d60ee2cb16f25d799ade3ceb629ad9edb3643049
Parents: 26dee15
Author: Dmitry Sen <ds...@hortonworks.com>
Authored: Fri Dec 20 20:42:38 2013 +0200
Committer: Dmitry Sen <ds...@hortonworks.com>
Committed: Fri Dec 20 21:00:50 2013 +0200

----------------------------------------------------------------------
 .../ambari_agent/CustomServiceOrchestrator.py   |   3 +
 .../libraries/script/script.py                  |  26 +++++
 .../org/apache/ambari/server/RoleCommand.java   |   1 +
 .../ambari/server/agent/ExecutionCommand.java   |   1 +
 .../ambari/server/agent/HeartBeatHandler.java   |   3 +-
 .../AmbariCustomCommandExecutionHelperImpl.java | 115 ++++++++++++++++++-
 .../ambari/server/metadata/ActionMetadata.java  |  16 +++
 .../ambari/server/state/ComponentInfo.java      |  11 ++
 .../HDP/2.0._/services/HBASE/metainfo.xml       |   2 +-
 .../HBASE/package/scripts/hbase_regionserver.py |   2 +-
 .../server/agent/TestHeartbeatHandler.java      |  51 ++++++++
 .../api/util/StackExtensionHelperTest.java      |   1 +
 12 files changed, 227 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
index 7acbefd..7ffc1c9 100644
--- a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
+++ b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
@@ -43,6 +43,7 @@ class CustomServiceOrchestrator():
   SCRIPT_TYPE_PYTHON = "PYTHON"
   COMMAND_NAME_STATUS = "STATUS"
   CUSTOM_ACTION_COMMAND = 'ACTIONEXECUTE'
+  CUSTOM_COMMAND_COMMAND = 'CUSTOM_COMMAND'
 
   PRE_HOOK_PREFIX="before"
   POST_HOOK_PREFIX="after"
@@ -95,6 +96,8 @@ class CustomServiceOrchestrator():
         script_tuple = (os.path.join(base_dir, script) , base_dir)
         hook_dir = None
       else:
+        if command_name == self.CUSTOM_COMMAND_COMMAND:
+          command_name = command['hostLevelParams']['custom_command']
         stack_name = command['hostLevelParams']['stack_name']
         stack_version = command['hostLevelParams']['stack_version']
         hook_dir = self.file_cache.get_hook_base_dir(stack_name, stack_version)

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-agent/src/main/python/resource_management/libraries/script/script.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/resource_management/libraries/script/script.py b/ambari-agent/src/main/python/resource_management/libraries/script/script.py
index 93d9aa2..b8c9d83 100644
--- a/ambari-agent/src/main/python/resource_management/libraries/script/script.py
+++ b/ambari-agent/src/main/python/resource_management/libraries/script/script.py
@@ -163,3 +163,29 @@ class Script(object):
     print("Error: " + message)
     sys.stderr.write("Error: " + message)
     sys.exit(1)
+
+  def start(self, env):
+    """
+    To be overridden by subclasses
+    """
+    self.fail_with_error('start method isn\'t implemented')
+
+  def stop(self, env):
+    """
+    To be overridden by subclasses
+    """
+    self.fail_with_error('stop method isn\'t implemented')
+
+  def restart(self, env):
+    """
+    Default implementation of restart command is to call stop and start methods
+    Feel free to override restart() method with your implementation.
+    """
+    self.stop(env)
+    self.start(env)
+
+  def configure(self, env):
+    """
+    To be overridden by subclasses
+    """
+    self.fail_with_error('configure method isn\'t implemented')

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/java/org/apache/ambari/server/RoleCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/RoleCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/RoleCommand.java
index be5f591..b98c50c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/RoleCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/RoleCommand.java
@@ -33,5 +33,6 @@ public enum RoleCommand {
   ABORT,
   UPGRADE,
   SERVICE_CHECK,
+  CUSTOM_COMMAND,
   ACTIONEXECUTE
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
index 5df20cc..dc8d605 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
@@ -258,6 +258,7 @@ public class ExecutionCommand extends AgentCommand {
     String SERVICE_CHECK = "SERVICE_CHECK"; // TODO: is it standart command? maybe add it to RoleCommand enum?
 
     String COMMAND_TIMEOUT_DEFAULT = "600"; // TODO: Will be replaced by proper initialization in another jira
+    String CUSTOM_COMMAND = "custom_command";
 
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index 7501fb4..947b97f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
@@ -193,7 +193,8 @@ public class HeartBeatHandler {
     List<CommandReport> reports = heartbeat.getReports();
     for (CommandReport report : reports) {
       LOG.debug("Received command report: " + report);
-      if (RoleCommand.ACTIONEXECUTE.toString().equals(report.getRoleCommand())) {
+      if (RoleCommand.ACTIONEXECUTE.toString().equals(report.getRoleCommand()) ||
+        RoleCommand.CUSTOM_COMMAND.toString().equals(report.getRoleCommand())) {
         continue;
       }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperImpl.java
index d0901e4..f1c7743 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperImpl.java
@@ -81,7 +81,8 @@ public class AmbariCustomCommandExecutionHelperImpl implements AmbariCustomComma
         + ", serviceName=" + actionRequest.getServiceName()
         + ", request=" + actionRequest.toString());
 
-    if (!isValidCommand(actionRequest.getCommandName(), actionRequest.getServiceName())) {
+    if (!isValidCommand(actionRequest.getCommandName(),
+      actionRequest.getServiceName()) && !isValidCustomCommand(actionRequest)) {
       throw new AmbariException(
           "Unsupported action " + actionRequest.getCommandName() + " for " + actionRequest.getServiceName());
     }
@@ -100,6 +101,28 @@ public class AmbariCustomCommandExecutionHelperImpl implements AmbariCustomComma
     return true;
   }
 
+  private Boolean isValidCustomCommand(ExecuteActionRequest actionRequest) throws AmbariException {
+    String clustername = actionRequest.getClusterName();
+    Cluster cluster = clusters.getCluster(clustername);
+    StackId stackId = cluster.getDesiredStackVersion();
+    String serviceName = actionRequest.getServiceName();
+    String componentName = actionRequest.getComponentName();
+    String commandName = actionRequest.getCommandName();
+
+    if (componentName == null) {
+      return false;
+    }
+    ComponentInfo componentInfo = ambariMetaInfo.getComponent(
+      stackId.getStackName(), stackId.getStackVersion(),
+      serviceName, componentName);
+
+    if (!componentInfo.isCustomCommand(commandName) &&
+      !actionMetadata.isDefaultHostComponentCommand(commandName)) {
+      return false;
+    }
+    return true;
+  }
+
   @Override
   public void addAction(ExecuteActionRequest actionRequest, Stage stage,
                         HostsMap hostsMap, Map<String, String> hostLevelParams)
@@ -108,11 +131,99 @@ public class AmbariCustomCommandExecutionHelperImpl implements AmbariCustomComma
       addServiceCheckAction(actionRequest, stage, hostsMap, hostLevelParams);
     } else if (actionRequest.getCommandName().equals("DECOMMISSION_DATANODE")) {
       addDecommissionDatanodeAction(actionRequest, stage, hostLevelParams);
+    } else if (isValidCustomCommand(actionRequest)) {
+      addCustomcommandAction(actionRequest, stage, hostsMap, hostLevelParams);
     } else {
       throw new AmbariException("Unsupported action " + actionRequest.getCommandName());
     }
   }
 
+  private void addCustomcommandAction(ExecuteActionRequest actionRequest,
+    Stage stage, HostsMap hostsMap, Map<String, String> hostLevelParams)
+    throws AmbariException {
+
+    if (actionRequest.getHosts().isEmpty()) {
+      throw new AmbariException("Invalid request : No hosts specified.");
+    }
+
+    String serviceName = actionRequest.getServiceName();
+    String componentName = actionRequest.getComponentName();
+    String commandName = actionRequest.getCommandName();
+
+    String clusterName = stage.getClusterName();
+    Cluster cluster = clusters.getCluster(clusterName);
+    StackId stackId = cluster.getDesiredStackVersion();
+    AmbariMetaInfo ambariMetaInfo = amc.getAmbariMetaInfo();
+    ServiceInfo serviceInfo =
+      ambariMetaInfo.getServiceInfo(stackId.getStackName(),
+        stackId.getStackVersion(), serviceName);
+
+    long nowTimestamp = System.currentTimeMillis();
+
+    for (String hostName: actionRequest.getHosts()) {
+
+      stage.addHostRoleExecutionCommand(hostName, Role.valueOf(componentName),
+        RoleCommand.CUSTOM_COMMAND,
+        new ServiceComponentHostOpInProgressEvent(componentName,
+        hostName, nowTimestamp), cluster.getClusterName(), serviceName);
+
+      Map<String, Map<String, String>> configurations =
+        new TreeMap<String, Map<String, String>>();
+      Map<String, Map<String, String>> configTags =
+        amc.findConfigurationTagsWithOverrides(cluster, hostName);
+
+      ExecutionCommand execCmd =  stage.getExecutionCommandWrapper(hostName,
+        componentName).getExecutionCommand();
+
+      execCmd.setConfigurations(configurations);
+      execCmd.setConfigurationTags(configTags);
+
+      execCmd.setClusterHostInfo(
+        StageUtils.getClusterHostInfo(clusters.getHostsForCluster(clusterName), cluster, hostsMap, configs));
+
+      if (hostLevelParams == null) {
+        hostLevelParams = new TreeMap<String, String>();
+      }
+      hostLevelParams.put(JDK_LOCATION, amc.getJdkResourceUrl());
+      hostLevelParams.put(STACK_NAME, stackId.getStackName());
+      hostLevelParams.put(STACK_VERSION,stackId.getStackVersion());
+      hostLevelParams.put(CUSTOM_COMMAND, commandName);
+      execCmd.setHostLevelParams(hostLevelParams);
+
+      Map<String,String> commandParams = new TreeMap<String, String>();
+      commandParams.put(SCHEMA_VERSION, serviceInfo.getSchemaVersion());
+
+      String commandTimeout = COMMAND_TIMEOUT_DEFAULT;
+
+      if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
+        // Service check command is not custom command
+        ComponentInfo componentInfo = ambariMetaInfo.getComponent(
+          stackId.getStackName(), stackId.getStackVersion(),
+          serviceName, componentName);
+        CommandScriptDefinition script = componentInfo.getCommandScript();
+
+        if (script != null) {
+          commandParams.put(SCRIPT, script.getScript());
+          commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
+          commandTimeout = String.valueOf(script.getTimeout());
+        } else {
+          String message = String.format("Component %s has not command script " +
+            "defined. It is not possible to run service check" +
+            " for this service", componentName);
+          throw new AmbariException(message);
+        }
+        // We don't need package/repo infomation to perform service check
+      }
+      commandParams.put(COMMAND_TIMEOUT, commandTimeout);
+
+      commandParams.put(SERVICE_METADATA_FOLDER,
+        serviceInfo.getServiceMetadataFolder());
+
+      execCmd.setCommandParams(commandParams);
+
+    }
+  }
+
   private void addServiceCheckAction(ExecuteActionRequest actionRequest, Stage stage,
                                      HostsMap hostsMap,
                                      Map<String, String> hostLevelParams)
@@ -238,7 +349,7 @@ public class AmbariCustomCommandExecutionHelperImpl implements AmbariCustomComma
         commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
         commandTimeout = String.valueOf(script.getTimeout());
       } else {
-        String message = String.format("Service %s has not command script " +
+        String message = String.format("Service %s has no command script " +
                 "defined. It is not possible to run service check" +
                 " for this service", serviceName);
         throw new AmbariException(message);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java b/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
index dc6d229..d6bd198 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
@@ -32,11 +32,20 @@ public class ActionMetadata {
   private final Map<String, String> serviceClients = new HashMap<String, String>();
   private final Map<String, String> serviceCheckActions =
       new HashMap<String, String>();
+  private final List<String> defaultHostComponentCommands = new ArrayList<String>();
 
   public ActionMetadata() {
     fillServiceActions();
     fillServiceClients();
     fillServiceCheckActions();
+    fillHostComponentCommands();
+  }
+
+  private void fillHostComponentCommands() {
+    //Standart commands for any host component
+    // TODO: Add START/STOP/INSTALL commands
+    defaultHostComponentCommands.add("RESTART");
+    defaultHostComponentCommands.add("CONFIGURE");
   }
 
   private void fillServiceClients() {
@@ -106,4 +115,11 @@ public class ActionMetadata {
   public String getServiceCheckAction(String serviceName) {
     return serviceCheckActions.get(serviceName.toLowerCase());
   }
+
+  public boolean isDefaultHostComponentCommand(String command) {
+    if (command != null && defaultHostComponentCommands.contains(command)) {
+      return true;
+    }
+    return false;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
index 8e2a562..7be8fc3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
@@ -89,4 +89,15 @@ public class ComponentInfo {
     }
     return customCommands;
   }
+
+  public boolean isCustomCommand(String commandName) {
+    if (customCommands != null && commandName != null) {
+      for (CustomCommandDefinition cc: customCommands) {
+        if (commandName.equals(cc.getName())){
+          return true;
+        }
+      }
+    }
+    return false;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
index 363338b..f6db6be 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
@@ -44,7 +44,7 @@
           </commandScript>
           <customCommands>
             <customCommand>
-              <name>DECOMMISSION_REGIONSERVER</name>
+              <name>DECOMMISSION</name>
               <commandScript>
                 <script>scripts/hbase_regionserver.py</script>
                 <scriptType>PYTHON</scriptType>

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
index 014d0ab..2d91e75 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
@@ -59,7 +59,7 @@ class HbaseRegionServer(Script):
     pid_file = format("{pid_dir}/hbase-hbase-regionserver.pid")
     check_process_status(pid_file)
     
-  def decommission(self):
+  def decommission(self, env):
     print "Decommission not yet implemented!"
     
 def main():

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java b/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
index e8a3a1f..6417a72 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
@@ -1308,6 +1308,57 @@ public class TestHeartbeatHandler {
             State.INSTALL_FAILED, serviceComponentHost2.getState());
   }
 
+  @Test
+  public void testIgnoreCustomActionReport() throws AmbariException, InvalidStateTransitionException {
+    ActionManager am = getMockActionManager();
+
+    CommandReport cr1 = new CommandReport();
+    cr1.setActionId(StageUtils.getActionId(requestId, stageId));
+    cr1.setTaskId(1);
+    cr1.setClusterName(DummyCluster);
+    cr1.setServiceName(HDFS);
+    cr1.setRole(NAMENODE);
+    cr1.setStatus(HostRoleStatus.FAILED.toString());
+    cr1.setRoleCommand("CUSTOM_COMMAND");
+    cr1.setStdErr("none");
+    cr1.setStdOut("dummy output");
+    cr1.setExitCode(0);
+    CommandReport cr2 = new CommandReport();
+    cr2.setActionId(StageUtils.getActionId(requestId, stageId));
+    cr2.setTaskId(2);
+    cr2.setClusterName(DummyCluster);
+    cr2.setServiceName(HDFS);
+    cr2.setRole(NAMENODE);
+    cr2.setStatus(HostRoleStatus.FAILED.toString());
+    cr2.setRoleCommand("ACTIONEXECUTE");
+    cr2.setStdErr("none");
+    cr2.setStdOut("dummy output");
+    cr2.setExitCode(0);
+
+    ArrayList<CommandReport> reports = new ArrayList<CommandReport>();
+    reports.add(cr1);
+    reports.add(cr2);
+
+    HeartBeat hb = new HeartBeat();
+    hb.setTimestamp(System.currentTimeMillis());
+    hb.setResponseId(0);
+    hb.setHostname(DummyHostname1);
+    hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
+    hb.setReports(reports);
+
+    ActionQueue aq = new ActionQueue();
+    HeartBeatHandler handler = getHeartBeatHandler(am, aq);
+
+    // CUSTOM_COMMAND and ACTIONEXECUTE reports are ignored
+    // they should not change the host component state
+    try {
+      handler.handleHeartBeat(hb);
+    } catch (Exception e) {
+      fail();
+    }
+
+  }
+
   private ActionManager getMockActionManager() {
     return new ActionManager(0, 0, null, null,
               new ActionDBInMemoryImpl(), new HostsMap((String) null), null, unitOfWork, null);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d60ee2cb/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
index 152a6b5..a31ed6e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
@@ -89,6 +89,7 @@ public class StackExtensionHelperTest {
                 firstComponent.getCustomCommands();
         assertEquals(1, customCommands.size());
         assertEquals("RESTART", customCommands.get(0).getName());
+        assertTrue(firstComponent.isCustomCommand("RESTART"));
         assertEquals("scripts/hbase_master_restart.py",
                 customCommands.get(0).getCommandScript().getScript());
         assertEquals(CommandScriptDefinition.Type.PYTHON,