files) {
+ this.files = files;
+ }
+
+ public String getProperty(String name, String defaultValue) {
+ String value = getProperty(name);
+ if (StringUtils.isEmpty(value)) {
+ return defaultValue;
+ }
+ return value;
+ }
+
+ public void setProperty(String name, String value) {
+ properties.put(name, value);
+ }
+
+ public String getProperty(String name) {
+ return properties.get(name.trim());
+ }
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ AuxServiceConfiguration configuration = (AuxServiceConfiguration) o;
+ return Objects.equals(this.properties, configuration.properties)
+ && Objects.equals(this.files, configuration.files);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(properties, files);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Configuration {\n");
+
+ sb.append(" properties: ").append(toIndentedString(properties))
+ .append("\n");
+ sb.append(" files: ").append(toIndentedString(files)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceFile.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceFile.java
new file mode 100644
index 0000000000..6b79b9c698
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceFile.java
@@ -0,0 +1,137 @@
+/*
+ * 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
+ *
+ * http://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.hadoop.yarn.server.nodemanager.containermanager.records;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import java.util.Objects;
+
+/**
+ * A config file that needs to be created and made available as a volume in an
+ * service component container.
+ **/
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AuxServiceFile {
+
+ /**
+ * Config Type.
+ **/
+ public enum TypeEnum {
+ STATIC("STATIC"), ARCHIVE("ARCHIVE");
+
+ private String value;
+
+ TypeEnum(String type) {
+ this.value = type;
+ }
+
+ @Override
+ @JsonValue
+ public String toString() {
+ return value;
+ }
+ }
+
+ private TypeEnum type = null;
+ private String srcFile = null;
+
+ /**
+ * Config file in the standard format like xml, properties, json, yaml,
+ * template.
+ **/
+ public AuxServiceFile type(TypeEnum t) {
+ this.type = t;
+ return this;
+ }
+
+ @JsonProperty("type")
+ public TypeEnum getType() {
+ return type;
+ }
+
+ public void setType(TypeEnum type) {
+ this.type = type;
+ }
+
+ /**
+ * This provides the source location of the configuration file, the content
+ * of which is dumped to dest_file post property substitutions, in the format
+ * as specified in type. Typically the src_file would point to a source
+ * controlled network accessible file maintained by tools like puppet, chef,
+ * or hdfs etc. Currently, only hdfs is supported.
+ **/
+ public AuxServiceFile srcFile(String file) {
+ this.srcFile = file;
+ return this;
+ }
+
+ @JsonProperty("src_file")
+ public String getSrcFile() {
+ return srcFile;
+ }
+
+ public void setSrcFile(String srcFile) {
+ this.srcFile = srcFile;
+ }
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ AuxServiceFile auxServiceFile = (AuxServiceFile) o;
+ return Objects.equals(this.type, auxServiceFile.type)
+ && Objects.equals(this.srcFile, auxServiceFile.srcFile);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, srcFile);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class AuxServiceFile {\n");
+
+ sb.append(" type: ").append(toIndentedString(type)).append("\n");
+ sb.append(" srcFile: ").append(toIndentedString(srcFile)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceRecord.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceRecord.java
new file mode 100644
index 0000000000..40882beba7
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceRecord.java
@@ -0,0 +1,175 @@
+/*
+ * 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
+ *
+ * http://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.hadoop.yarn.server.nodemanager.containermanager.records;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * An Service resource has the following attributes.
+ **/
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({ "name", "version", "description", "launch_time",
+ "configuration" })
+public class AuxServiceRecord {
+
+ private String name = null;
+ private String version = null;
+ private String description = null;
+ private Date launchTime = null;
+ private AuxServiceConfiguration configuration = new AuxServiceConfiguration();
+
+ /**
+ * A unique service name.
+ **/
+ public AuxServiceRecord name(String n) {
+ this.name = n;
+ return this;
+ }
+
+ @JsonProperty("name")
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @JsonProperty("version")
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ /**
+ * Version of the service.
+ */
+ public AuxServiceRecord version(String v) {
+ this.version = v;
+ return this;
+ }
+
+ @JsonProperty("description")
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Description of the service.
+ */
+ public AuxServiceRecord description(String d) {
+ this.description = d;
+ return this;
+ }
+
+ /**
+ * The time when the service was created, e.g. 2016-03-16T01:01:49.000Z.
+ **/
+ public AuxServiceRecord launchTime(Date time) {
+ this.launchTime = time == null ? null : (Date) time.clone();
+ return this;
+ }
+
+ @JsonProperty("launch_time")
+ public Date getLaunchTime() {
+ return launchTime == null ? null : (Date) launchTime.clone();
+ }
+
+ public void setLaunchTime(Date time) {
+ this.launchTime = time == null ? null : (Date) time.clone();
+ }
+ /**
+ * Config properties of an service. Configurations provided at the
+ * service/global level are available to all the components. Specific
+ * properties can be overridden at the component level.
+ **/
+ public AuxServiceRecord configuration(AuxServiceConfiguration conf) {
+ this.configuration = conf;
+ return this;
+ }
+
+ @JsonProperty("configuration")
+ public AuxServiceConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ public void setConfiguration(AuxServiceConfiguration conf) {
+ this.configuration = conf;
+ }
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ AuxServiceRecord service = (AuxServiceRecord) o;
+ return Objects.equals(this.name, service.name) && Objects.equals(this
+ .version, service.version);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, version);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Service {\n");
+
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" version: ").append(toIndentedString(version)).append("\n");
+ sb.append(" description: ").append(toIndentedString(description))
+ .append("\n");
+ sb.append(" configuration: ").append(toIndentedString(configuration))
+ .append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceRecords.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceRecords.java
new file mode 100644
index 0000000000..c2454e71a1
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/AuxServiceRecords.java
@@ -0,0 +1,46 @@
+/**
+ * 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
+ *
+ * http://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.hadoop.yarn.server.nodemanager.containermanager.records;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A list of Services.
+ **/
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AuxServiceRecords {
+ private List services = new ArrayList<>();
+
+ public AuxServiceRecords serviceList(AuxServiceRecord... serviceList) {
+ for (AuxServiceRecord service : serviceList) {
+ this.services.add(service);
+ }
+ return this;
+ }
+
+ public List getServices() {
+ return services;
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/package-info.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/package-info.java
new file mode 100644
index 0000000000..bfdc33f166
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/records/package-info.java
@@ -0,0 +1,29 @@
+/**
+ * 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
+ *
+ * http://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 used for auxiliary services manifest records. To the extent
+ * possible, the format matches the YARN service framework service
+ * specification.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+package org.apache.hadoop.yarn.server.nodemanager.containermanager.records;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
index ca08897eee..4b82f37a42 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
@@ -24,13 +24,16 @@
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.records.AuxServiceRecord;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.resourceplugin.ResourcePlugin;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.resourceplugin.ResourcePluginManager;
+import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.AuxiliaryServicesInfo;
import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.NMResourceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -556,6 +559,25 @@ public Object getNMResourceInfo(
return new NMResourceInfo();
}
+ @GET
+ @Path("/auxiliaryservices")
+ @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
+ MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
+ public AuxiliaryServicesInfo getAuxiliaryServices(@javax.ws.rs.core.Context
+ HttpServletRequest hsr) {
+ init();
+ AuxiliaryServicesInfo auxiliaryServices = new AuxiliaryServicesInfo();
+ if (!hasAdminAccess(hsr)) {
+ return auxiliaryServices;
+ }
+ Collection loadedServices = nmContext.getAuxServices()
+ .getServiceRecords();
+ if (loadedServices != null) {
+ auxiliaryServices.addAll(loadedServices);
+ }
+ return auxiliaryServices;
+ }
+
@PUT
@Path("/yarn/sysfs/{user}/{appId}")
@Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
@@ -625,6 +647,21 @@ protected Boolean hasAccess(String user, ApplicationId appId,
return true;
}
+ protected Boolean hasAdminAccess(HttpServletRequest hsr) {
+ // Check for the authorization.
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
+
+ if (callerUGI == null) {
+ return false;
+ }
+
+ if (!this.nmContext.getApplicationACLsManager().isAdmin(callerUGI)) {
+ return false;
+ }
+
+ return true;
+ }
+
private UserGroupInformation getCallerUserGroupInformation(
HttpServletRequest hsr, boolean usePrincipal) {
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/AuxiliaryServiceInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/AuxiliaryServiceInfo.java
new file mode 100644
index 0000000000..873314d28e
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/AuxiliaryServiceInfo.java
@@ -0,0 +1,60 @@
+/**
+ * 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
+ *
+ * http://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.hadoop.yarn.server.nodemanager.webapp.dao;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Information about a loaded auxiliary service.
+ */
+@XmlRootElement(name = "service")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AuxiliaryServiceInfo {
+ private String name;
+ private String version;
+ private String startTime;
+
+ public AuxiliaryServiceInfo() {
+ // JAXB needs this
+ }
+
+ public AuxiliaryServiceInfo(String name, String version, Date startTime) {
+ DateFormat dateFormat =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ this.name = name;
+ this.version = version;
+ this.startTime = dateFormat.format(startTime);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getStartTime() {
+ return startTime;
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/AuxiliaryServicesInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/AuxiliaryServicesInfo.java
new file mode 100644
index 0000000000..e11b9c296f
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/AuxiliaryServicesInfo.java
@@ -0,0 +1,55 @@
+/**
+ * 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
+ *
+ * http://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.hadoop.yarn.server.nodemanager.webapp.dao;
+
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.records.AuxServiceRecord;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * A list of loaded auxiliary services.
+ */
+@XmlRootElement(name = "services")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AuxiliaryServicesInfo {
+ private ArrayList services = new
+ ArrayList<>();
+
+ public AuxiliaryServicesInfo() {
+ // JAXB needs this
+ }
+
+ public void add(AuxServiceRecord s) {
+ services.add(new AuxiliaryServiceInfo(s.getName(), s.getVersion(), s
+ .getLaunchTime()));
+ }
+
+ public void addAll(Collection serviceList) {
+ for (AuxServiceRecord service : serviceList) {
+ add(service);
+ }
+ }
+
+ public ArrayList getServices() {
+ return services;
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/amrmproxy/BaseAMRMProxyTest.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/amrmproxy/BaseAMRMProxyTest.java
index 2794857c6e..2ecbf316eb 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/amrmproxy/BaseAMRMProxyTest.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/amrmproxy/BaseAMRMProxyTest.java
@@ -53,6 +53,7 @@
import org.apache.hadoop.yarn.server.nodemanager.NodeManager.NMContext;
import org.apache.hadoop.yarn.server.nodemanager.NodeResourceMonitor;
import org.apache.hadoop.yarn.server.nodemanager.NodeStatusUpdater;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.AuxServices;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManager;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
@@ -827,5 +828,14 @@ public DeletionService getDeletionService() {
public NMLogAggregationStatusTracker getNMLogAggregationStatusTracker() {
return null;
}
+
+ @Override
+ public void setAuxServices(AuxServices auxServices) {
+ }
+
+ @Override
+ public AuxServices getAuxServices() {
+ return null;
+ }
}
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
index ca0b32a752..ece8d9bfb0 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
@@ -31,6 +31,15 @@
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.records.AuxServiceRecord;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.records.AuxServiceRecords;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -87,6 +96,11 @@
import org.junit.Assert;
import org.junit.Test;
+/**
+ * Test for auxiliary services. Parameter 0 tests the Configuration-based aux
+ * services and parameter 1 tests manifest-based aux services.
+ */
+@RunWith(value = Parameterized.class)
public class TestAuxServices {
private static final Logger LOG =
LoggerFactory.getLogger(TestAuxServices.class);
@@ -99,6 +113,36 @@ public class TestAuxServices {
private final static Context MOCK_CONTEXT = mock(Context.class);
private final static DeletionService MOCK_DEL_SERVICE = mock(
DeletionService.class);
+ private final Boolean useManifest;
+ private File rootDir = GenericTestUtils.getTestDir(getClass()
+ .getSimpleName());
+ private File manifest = new File(rootDir, "manifest.txt");
+ private ObjectMapper mapper = new ObjectMapper();
+
+ @Parameterized.Parameters
+ public static Collection getParams() {
+ return Arrays.asList(false, true);
+ }
+
+ @Before
+ public void setup() {
+ if (!rootDir.exists()) {
+ rootDir.mkdirs();
+ }
+ }
+
+ @After
+ public void cleanup() {
+ if (useManifest) {
+ manifest.delete();
+ }
+ rootDir.delete();
+ }
+
+ public TestAuxServices(Boolean useManifest) {
+ this.useManifest = useManifest;
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
static class LightService extends AuxiliaryService implements Service
{
@@ -204,15 +248,27 @@ public ByteBuffer getMetaData() {
}
}
+ private void writeManifestFile(AuxServiceRecords services, Configuration
+ conf) throws IOException {
+ conf.set(YarnConfiguration.NM_AUX_SERVICES_MANIFEST, manifest
+ .getAbsolutePath());
+ mapper.writeValue(manifest, services);
+ }
+
@SuppressWarnings("resource")
@Test
public void testRemoteAuxServiceClassPath() throws Exception {
Configuration conf = new YarnConfiguration();
FileSystem fs = FileSystem.get(conf);
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
- new String[] {"ServiceC"});
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
- "ServiceC"), ServiceC.class, Service.class);
+ AuxServiceRecord serviceC =
+ AuxServices.newAuxService("ServiceC", ServiceC.class.getName());
+ AuxServiceRecords services = new AuxServiceRecords().serviceList(serviceC);
+ if (!useManifest) {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
+ new String[]{"ServiceC"});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
+ "ServiceC"), ServiceC.class, Service.class);
+ }
Context mockContext2 = mock(Context.class);
LocalDirsHandlerService mockDirsHandler = mock(
@@ -223,11 +279,8 @@ public void testRemoteAuxServiceClassPath() throws Exception {
rootAuxServiceDirPath);
when(mockContext2.getLocalDirsHandler()).thenReturn(mockDirsHandler);
- File rootDir = GenericTestUtils.getTestDir(getClass()
- .getSimpleName());
- if (!rootDir.exists()) {
- rootDir.mkdirs();
- }
+ DeletionService mockDelService2 = mock(DeletionService.class);
+
AuxServices aux = null;
File testJar = null;
try {
@@ -243,11 +296,16 @@ public void testRemoteAuxServiceClassPath() throws Exception {
perms.add(PosixFilePermission.GROUP_WRITE);
Files.setPosixFilePermissions(Paths.get(testJar.getAbsolutePath()),
perms);
- conf.set(String.format(
- YarnConfiguration.NM_AUX_SERVICE_REMOTE_CLASSPATH, "ServiceC"),
- testJar.getAbsolutePath());
+ if (useManifest) {
+ AuxServices.setClasspath(serviceC, testJar.getAbsolutePath());
+ writeManifestFile(services, conf);
+ } else {
+ conf.set(String.format(
+ YarnConfiguration.NM_AUX_SERVICE_REMOTE_CLASSPATH, "ServiceC"),
+ testJar.getAbsolutePath());
+ }
aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
- mockContext2, MOCK_DEL_SERVICE);
+ mockContext2, mockDelService2);
aux.init(conf);
Assert.fail("The permission of the jar is wrong."
+ "Should throw out exception.");
@@ -260,11 +318,16 @@ public void testRemoteAuxServiceClassPath() throws Exception {
testJar = JarFinder.makeClassLoaderTestJar(this.getClass(), rootDir,
"test-runjar.jar", 2048, ServiceC.class.getName());
- conf.set(String.format(
- YarnConfiguration.NM_AUX_SERVICE_REMOTE_CLASSPATH, "ServiceC"),
- testJar.getAbsolutePath());
+ if (useManifest) {
+ AuxServices.setClasspath(serviceC, testJar.getAbsolutePath());
+ writeManifestFile(services, conf);
+ } else {
+ conf.set(String.format(
+ YarnConfiguration.NM_AUX_SERVICE_REMOTE_CLASSPATH, "ServiceC"),
+ testJar.getAbsolutePath());
+ }
aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
- mockContext2, MOCK_DEL_SERVICE);
+ mockContext2, mockDelService2);
aux.init(conf);
aux.start();
Map meta = aux.getMetaData();
@@ -281,7 +344,7 @@ public void testRemoteAuxServiceClassPath() throws Exception {
// initialize the same auxservice again, and make sure that we did not
// re-download the jar from remote directory.
aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
- mockContext2, MOCK_DEL_SERVICE);
+ mockContext2, mockDelService2);
aux.init(conf);
aux.start();
meta = aux.getMetaData();
@@ -290,7 +353,7 @@ public void testRemoteAuxServiceClassPath() throws Exception {
auxName = i.getKey();
}
Assert.assertEquals("ServiceC", auxName);
- verify(MOCK_DEL_SERVICE, times(0)).delete(any(FileDeletionTask.class));
+ verify(mockDelService2, times(0)).delete(any(FileDeletionTask.class));
status = fs.listStatus(rootAuxServiceDirPath);
Assert.assertTrue(status.length == 1);
aux.serviceStop();
@@ -301,22 +364,17 @@ public void testRemoteAuxServiceClassPath() throws Exception {
FileTime fileTime = FileTime.fromMillis(time);
Files.setLastModifiedTime(Paths.get(testJar.getAbsolutePath()),
fileTime);
- conf.set(
- String.format(YarnConfiguration.NM_AUX_SERVICE_REMOTE_CLASSPATH,
- "ServiceC"),
- testJar.getAbsolutePath());
aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
- mockContext2, MOCK_DEL_SERVICE);
+ mockContext2, mockDelService2);
aux.init(conf);
aux.start();
- verify(MOCK_DEL_SERVICE, times(1)).delete(any(FileDeletionTask.class));
+ verify(mockDelService2, times(1)).delete(any(FileDeletionTask.class));
status = fs.listStatus(rootAuxServiceDirPath);
Assert.assertTrue(status.length == 2);
aux.serviceStop();
} finally {
if (testJar != null) {
testJar.delete();
- rootDir.delete();
}
if (fs.exists(new Path(root))) {
fs.delete(new Path(root), true);
@@ -333,10 +391,17 @@ public void testRemoteAuxServiceClassPath() throws Exception {
public void testCustomizedAuxServiceClassPath() throws Exception {
// verify that we can load AuxService Class from default Class path
Configuration conf = new YarnConfiguration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
- new String[] {"ServiceC"});
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
- "ServiceC"), ServiceC.class, Service.class);
+ AuxServiceRecord serviceC =
+ AuxServices.newAuxService("ServiceC", ServiceC.class.getName());
+ AuxServiceRecords services = new AuxServiceRecords().serviceList(serviceC);
+ if (useManifest) {
+ writeManifestFile(services, conf);
+ } else {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
+ new String[]{"ServiceC"});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
+ "ServiceC"), ServiceC.class, Service.class);
+ }
@SuppressWarnings("resource")
AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
@@ -358,31 +423,41 @@ public void testCustomizedAuxServiceClassPath() throws Exception {
// create a new jar file, and configure it as customized class path
// for this AuxService, and make sure that we could load the class
// from this configured customized class path
- File rootDir = GenericTestUtils.getTestDir(getClass()
- .getSimpleName());
- if (!rootDir.exists()) {
- rootDir.mkdirs();
- }
File testJar = null;
try {
testJar = JarFinder.makeClassLoaderTestJar(this.getClass(), rootDir,
- "test-runjar.jar", 2048, ServiceC.class.getName());
+ "test-runjar.jar", 2048, ServiceC.class.getName(), LightService
+ .class.getName());
conf = new YarnConfiguration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
- new String[] {"ServiceC"});
- conf.set(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "ServiceC"),
- ServiceC.class.getName());
- conf.set(String.format(
- YarnConfiguration.NM_AUX_SERVICES_CLASSPATH, "ServiceC"),
- testJar.getAbsolutePath());
// remove "-org.apache.hadoop." from system classes
String systemClasses = "-org.apache.hadoop." + "," +
- ApplicationClassLoader.SYSTEM_CLASSES_DEFAULT;
- conf.set(String.format(
- YarnConfiguration.NM_AUX_SERVICES_SYSTEM_CLASSES,
- "ServiceC"), systemClasses);
+ ApplicationClassLoader.SYSTEM_CLASSES_DEFAULT;
+ if (useManifest) {
+ AuxServices.setClasspath(serviceC, testJar.getAbsolutePath());
+ AuxServices.setSystemClasses(serviceC, systemClasses);
+ writeManifestFile(services, conf);
+ } else {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
+ new String[]{"ServiceC"});
+ conf.set(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
+ "ServiceC"), ServiceC.class.getName());
+ conf.set(String.format(
+ YarnConfiguration.NM_AUX_SERVICES_CLASSPATH, "ServiceC"),
+ testJar.getAbsolutePath());
+ conf.set(String.format(
+ YarnConfiguration.NM_AUX_SERVICES_SYSTEM_CLASSES,
+ "ServiceC"), systemClasses);
+ }
+ Context mockContext2 = mock(Context.class);
+ LocalDirsHandlerService mockDirsHandler = mock(
+ LocalDirsHandlerService.class);
+ String root = "target/LocalDir";
+ Path rootAuxServiceDirPath = new Path(root, "nmAuxService");
+ when(mockDirsHandler.getLocalPathForWrite(anyString())).thenReturn(
+ rootAuxServiceDirPath);
+ when(mockContext2.getLocalDirsHandler()).thenReturn(mockDirsHandler);
aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
- MOCK_CONTEXT, MOCK_DEL_SERVICE);
+ mockContext2, MOCK_DEL_SERVICE);
aux.init(conf);
aux.start();
meta = aux.getMetaData();
@@ -405,21 +480,32 @@ public void testCustomizedAuxServiceClassPath() throws Exception {
} finally {
if (testJar != null) {
testJar.delete();
- rootDir.delete();
}
}
}
@Test
- public void testAuxEventDispatch() {
+ public void testAuxEventDispatch() throws IOException {
Configuration conf = new Configuration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[] { "Asrv", "Bsrv" });
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv"),
- ServiceA.class, Service.class);
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv"),
- ServiceB.class, Service.class);
- conf.setInt("A.expected.init", 1);
- conf.setInt("B.expected.stop", 1);
+ if (useManifest) {
+ AuxServiceRecord serviceA =
+ AuxServices.newAuxService("Asrv", ServiceA.class.getName());
+ serviceA.getConfiguration().setProperty("A.expected.init", "1");
+ AuxServiceRecord serviceB =
+ AuxServices.newAuxService("Bsrv", ServiceB.class.getName());
+ serviceB.getConfiguration().setProperty("B.expected.stop", "1");
+ writeManifestFile(new AuxServiceRecords().serviceList(serviceA,
+ serviceB), conf);
+ } else {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[]{"Asrv",
+ "Bsrv"});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv"),
+ ServiceA.class, Service.class);
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv"),
+ ServiceB.class, Service.class);
+ conf.setInt("A.expected.init", 1);
+ conf.setInt("B.expected.stop", 1);
+ }
final AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
aux.init(conf);
@@ -477,14 +563,36 @@ public void testAuxEventDispatch() {
}
}
- @Test
- public void testAuxServices() {
+ private Configuration getABConf() throws
+ IOException {
+ return getABConf("Asrv", "Bsrv", ServiceA.class, ServiceB.class);
+ }
+
+ private Configuration getABConf(String aName, String bName,
+ Class extends Service> aClass, Class extends Service> bClass) throws
+ IOException {
Configuration conf = new Configuration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[] { "Asrv", "Bsrv" });
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv"),
- ServiceA.class, Service.class);
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv"),
- ServiceB.class, Service.class);
+ if (useManifest) {
+ AuxServiceRecord serviceA =
+ AuxServices.newAuxService(aName, aClass.getName());
+ AuxServiceRecord serviceB =
+ AuxServices.newAuxService(bName, bClass.getName());
+ writeManifestFile(new AuxServiceRecords().serviceList(serviceA, serviceB),
+ conf);
+ } else {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[]{aName,
+ bName});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, aName),
+ aClass, Service.class);
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, bName),
+ bClass, Service.class);
+ }
+ return conf;
+ }
+
+ @Test
+ public void testAuxServices() throws IOException {
+ Configuration conf = getABConf();
final AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
aux.init(conf);
@@ -510,15 +618,9 @@ public void testAuxServices() {
}
}
-
@Test
- public void testAuxServicesMeta() {
- Configuration conf = new Configuration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[] { "Asrv", "Bsrv" });
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv"),
- ServiceA.class, Service.class);
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv"),
- ServiceB.class, Service.class);
+ public void testAuxServicesMeta() throws IOException {
+ Configuration conf = getABConf();
final AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
aux.init(conf);
@@ -547,16 +649,10 @@ public void testAuxServicesMeta() {
}
}
-
-
@Test
- public void testAuxUnexpectedStop() {
- Configuration conf = new Configuration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[] { "Asrv", "Bsrv" });
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv"),
- ServiceA.class, Service.class);
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv"),
- ServiceB.class, Service.class);
+ public void testAuxUnexpectedStop() throws IOException {
+ // AuxServices no longer expected to stop when services stop
+ Configuration conf = getABConf();
final AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
aux.init(conf);
@@ -564,21 +660,17 @@ public void testAuxUnexpectedStop() {
Service s = aux.getServices().iterator().next();
s.stop();
- assertEquals("Auxiliary service stopped, but AuxService unaffected.",
- STOPPED, aux.getServiceState());
- assertTrue(aux.getServices().isEmpty());
+ assertEquals("Auxiliary service stop caused AuxServices stop",
+ STARTED, aux.getServiceState());
+ assertEquals(2, aux.getServices().size());
}
@Test
- public void testValidAuxServiceName() {
+ public void testValidAuxServiceName() throws IOException {
+ Configuration conf = getABConf("Asrv1", "Bsrv_2", ServiceA.class,
+ ServiceB.class);
final AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
- Configuration conf = new Configuration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[] {"Asrv1", "Bsrv_2"});
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv1"),
- ServiceA.class, Service.class);
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv_2"),
- ServiceB.class, Service.class);
try {
aux.init(conf);
} catch (Exception ex) {
@@ -588,30 +680,33 @@ public void testValidAuxServiceName() {
//Test bad auxService Name
final AuxServices aux1 = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[] {"1Asrv1"});
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "1Asrv1"),
- ServiceA.class, Service.class);
+ if (useManifest) {
+ AuxServiceRecord serviceA =
+ AuxServices.newAuxService("1Asrv1", ServiceA.class.getName());
+ writeManifestFile(new AuxServiceRecords().serviceList(serviceA), conf);
+ } else {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES, new String[]
+ {"1Asrv1"});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
+ "1Asrv1"), ServiceA.class, Service.class);
+ }
try {
aux1.init(conf);
Assert.fail("Should receive the exception.");
} catch (Exception ex) {
- assertTrue(ex.getMessage().contains("The ServiceName: 1Asrv1 set in " +
- "yarn.nodemanager.aux-services is invalid.The valid service name " +
- "should only contain a-zA-Z0-9_ and can not start with numbers"));
+ assertTrue("Wrong message: " + ex.getMessage(),
+ ex.getMessage().contains("The auxiliary service name: 1Asrv1 is " +
+ "invalid. The valid service name should only contain a-zA-Z0-9_" +
+ " and cannot start with numbers."));
}
}
@Test
public void testAuxServiceRecoverySetup() throws IOException {
- Configuration conf = new YarnConfiguration();
+ Configuration conf = getABConf("Asrv", "Bsrv", RecoverableServiceA.class,
+ RecoverableServiceB.class);
conf.setBoolean(YarnConfiguration.NM_RECOVERY_ENABLED, true);
conf.set(YarnConfiguration.NM_RECOVERY_DIR, TEST_DIR.toString());
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
- new String[] { "Asrv", "Bsrv" });
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Asrv"),
- RecoverableServiceA.class, Service.class);
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "Bsrv"),
- RecoverableServiceB.class, Service.class);
try {
final AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER,
MOCK_CONTEXT, MOCK_DEL_SERVICE);
@@ -708,20 +803,33 @@ public ByteBuffer getMetaData() {
}
@Test
- public void testAuxServicesConfChange() {
+ public void testAuxServicesConfChange() throws IOException {
Configuration conf = new Configuration();
- conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
- new String[]{"ConfChangeAuxService"});
- conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
- "ConfChangeAuxService"), ConfChangeAuxService.class, Service.class);
+ if (useManifest) {
+ AuxServiceRecord service =
+ AuxServices.newAuxService("ConfChangeAuxService",
+ ConfChangeAuxService.class.getName());
+ service.getConfiguration().setProperty("dummyConfig", "testValue");
+ writeManifestFile(new AuxServiceRecords().serviceList(service), conf);
+ } else {
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
+ new String[]{"ConfChangeAuxService"});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
+ "ConfChangeAuxService"), ConfChangeAuxService.class, Service.class);
+ conf.set("dummyConfig", "testValue");
+ }
AuxServices aux = new AuxServices(MOCK_AUX_PATH_HANDLER, MOCK_CONTEXT,
MOCK_DEL_SERVICE);
- conf.set("dummyConfig", "testValue");
aux.init(conf);
aux.start();
for (AuxiliaryService s : aux.getServices()) {
assertEquals(STARTED, s.getServiceState());
- assertEquals(conf.get("dummyConfig"), "testValue");
+ if (useManifest) {
+ assertNull(conf.get("dummyConfig"));
+ } else {
+ assertEquals("testValue", conf.get("dummyConfig"));
+ }
+ assertEquals("changedTestValue", s.getConfig().get("dummyConfig"));
}
aux.stop();