diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/client/ApiServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/client/ApiServiceClient.java index 63378dc5a44..d439e8b155d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/client/ApiServiceClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/client/ApiServiceClient.java @@ -471,19 +471,30 @@ public int actionDestroy(String appName) throws IOException, YarnException { public int actionFlex(String appName, Map componentCounts) throws IOException, YarnException { int result = EXIT_SUCCESS; + ServiceApiUtil.validateNameFormat(appName, getConfig()); try { + // We have to check the original number of container of the app + // so that we can do relative changes. + ClientResponse response = getApiClient(getServicePath(appName)) + .get(ClientResponse.class); + if (response.getStatus() == 404 || response.getStatus() != 200) { + throw new YarnException(MessageFormat.format("Fail to check the current application status: {0}", appName)); + } + Service currentService = jsonSerDeser.fromJson(response.getEntity(String.class)); Service service = new Service(); service.setName(appName); service.setState(ServiceState.FLEX); for (Map.Entry entry : componentCounts.entrySet()) { Component component = new Component(); component.setName(entry.getKey()); - Long numberOfContainers = Long.parseLong(entry.getValue()); + Long currentNumberOfContainer = currentService.getComponent(entry.getKey()).getNumberOfContainers(); + Long numberOfContainers = ServiceApiUtil.parseNumberOfContainers( + currentNumberOfContainer, entry.getValue(), entry.getKey()); component.setNumberOfContainers(numberOfContainers); service.addComponent(component); } String buffer = jsonSerDeser.toJson(service); - ClientResponse response = getApiClient(getServicePath(appName)) + response = getApiClient(getServicePath(appName)) .put(ClientResponse.class, buffer); result = processResponse(response); } catch (Exception e) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java index 5cdb8c91dc7..4f340a4f49e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java @@ -588,37 +588,13 @@ public int actionFlex(String serviceName, Map throw new IllegalArgumentException(entry.getKey() + " does not exist !"); } long numberOfContainers = - parseNumberOfContainers(component, entry.getValue()); + ServiceApiUtil.parseNumberOfContainers(component.getNumberOfContainers(), entry.getValue(), component.getName()); componentCounts.put(compName, numberOfContainers); } flexComponents(serviceName, componentCounts, persistedService); return EXIT_SUCCESS; } - // Parse the number of containers requested by user, e.g. - // +5 means add 5 additional containers - // -5 means reduce 5 containers, if it goes to negative, sets it to 0 - // 5 means sets it to 5 containers. - private long parseNumberOfContainers(Component component, String newNumber) { - - long orig = component.getNumberOfContainers(); - if (newNumber.startsWith("+")) { - return orig + Long.parseLong(newNumber.substring(1)); - } else if (newNumber.startsWith("-")) { - long ret = orig - Long.parseLong(newNumber.substring(1)); - if (ret < 0) { - LOG.warn(MessageFormat.format( - "[COMPONENT {0}]: component count goes to negative ({1}{2} = {3})," - + " ignore and reset it to 0.", - component.getName(), orig, newNumber, ret)); - ret = 0; - } - return ret; - } else { - return Long.parseLong(newNumber); - } - } - // Called by Rest Service public Map flexByRestService(String serviceName, Map componentCounts) throws YarnException, IOException { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java index c681093a306..434d75ab8a0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java @@ -784,4 +784,28 @@ public static void checkServiceDependencySatisified(Service service) { } } } + + // Parse the number of containers requested by user, e.g. + // +5 means add 5 additional containers + // -5 means reduce 5 containers, if it goes to negative, sets it to 0 + // 5 means sets it to 5 containers. + public static long parseNumberOfContainers(long orig, String newNumber, String compName) { + + if (newNumber.startsWith("+")) { + return orig + Long.parseLong(newNumber.substring(1)); + } else if (newNumber.startsWith("-")) { + long ret = orig - Long.parseLong(newNumber.substring(1)); + if (ret < 0) { + LOG.warn(MessageFormat.format( + "[COMPONENT {0}]: component count goes to negative ({1}{2} = {3})," + + " ignore and reset it to 0.", + compName, orig, newNumber, ret)); + ret = 0; + } + return ret; + } else { + return Long.parseLong(newNumber); + } + } + } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java index 2bf59b8afc8..c4383726618 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/utils/TestServiceApiUtil.java @@ -765,6 +765,14 @@ public void run() { Assert.assertTrue(thread.isAlive()); } + @Test + public void testParseNumberOfContainers() { + assertEquals(ServiceApiUtil.parseNumberOfContainers(3, "1", "appName"), 1); + assertEquals(ServiceApiUtil.parseNumberOfContainers(3, "+1", "appName"), 4); + assertEquals(ServiceApiUtil.parseNumberOfContainers(3, "-1", "appName"), 2); + assertEquals(ServiceApiUtil.parseNumberOfContainers(3, "-4", "appName"), 0); + } + public static Service createExampleApplication() { Service exampleApp = new Service();