Bläddra i källkod

AMBARI-13612. Add RM and ATS Proxy Urls to Ambari Tez (DIPAYAN BHOWMICK via srimanth)

Srimanth Gunturi 9 år sedan
förälder
incheckning
dd8bdd2748

+ 12 - 0
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ViewController.java

@@ -33,4 +33,16 @@ public interface ViewController {
    * @return Get the properties that any user is allowed to see, even non-admin users.
    */
   public ViewStatus getViewStatus();
+
+  /**
+   *
+   * @return The Active Application timeline server URL. Though, there is currently no
+   * HA in ATS, the ATS Url that is returned is considered as the Active one.
+   */
+  String getActiveATSUrl();
+
+  /**
+   * @return The active resource manager URL.
+   */
+  String getActiveRMUrl();
 }

+ 13 - 7
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/ViewControllerImpl.java

@@ -42,7 +42,6 @@ public class ViewControllerImpl implements ViewController {
 
   private AmbariApi ambariApi;
 
-
   @Inject
   public ViewControllerImpl(ViewContext viewContext) {
     this.ambariApi = new AmbariApi(viewContext);
@@ -60,21 +59,28 @@ public class ViewControllerImpl implements ViewController {
 
     ViewStatus status = new ViewStatus();
     Map<String, String> parameters = new HashMap<String, String>();
+    parameters.put(ViewController.PARAM_YARN_ATS_URL, getActiveATSUrl());
+    parameters.put(ViewController.PARAM_YARN_RESOURCEMANAGER_URL, getActiveRMUrl());
+    status.setParameters(parameters);
+    return status;
+  }
+
+  @Override
+  public String getActiveATSUrl() {
     try {
-      parameters.put(ViewController.PARAM_YARN_ATS_URL, ambariApi.getServices().getTimelineServerUrl());
+      return ambariApi.getServices().getTimelineServerUrl();
     } catch (AmbariApiException ex) {
       throw new ATSUrlFetchException(ex);
     }
+  }
 
+  @Override
+  public String getActiveRMUrl() {
     try {
-      parameters.put(ViewController.PARAM_YARN_RESOURCEMANAGER_URL, ambariApi.getServices().getRMUrl());
+      return ambariApi.getServices().getRMUrl();
     } catch (AmbariApiException ex) {
       throw new ActiveRMFetchException(ex);
     }
-
-    status.setParameters(parameters);
-    return status;
   }
-
 }
 

+ 48 - 0
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/exceptions/ProxyException.java

@@ -0,0 +1,48 @@
+/**
+ * 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.ambari.view.tez.exceptions;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Exception thrown by the proxy resources
+ */
+
+public class ProxyException extends WebApplicationException {
+
+  public ProxyException(String message, int status) {
+    this(message, status, null);
+  }
+
+  public ProxyException(String message, int status, String trace) {
+    super(toEntity(message, status, trace));
+  }
+
+  private static Response toEntity(String message, int status, String trace) {
+    Map<String, Object> json = new HashMap<>();
+    json.put("message", message);
+    json.put("status", status);
+    json.put("trace", trace);
+    return Response.status(status).entity(json).type(MediaType.APPLICATION_JSON).build();
+  }
+}

+ 47 - 0
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/rest/AtsProxyResource.java

@@ -0,0 +1,47 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.tez.rest;
+
+import com.google.inject.Inject;
+import org.apache.ambari.view.tez.ViewController;
+import org.apache.ambari.view.tez.utils.ProxyHelper;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+/**
+ * Proxy class to query Application timeline server
+ */
+public class AtsProxyResource extends BaseProxyResource {
+
+  private ViewController viewController;
+  private ProxyHelper proxyHelper;
+
+  @Inject
+  public AtsProxyResource(ViewController viewController, ProxyHelper proxyHelper) {
+    super(proxyHelper);
+    this.viewController = viewController;
+    this.proxyHelper = proxyHelper;
+  }
+
+  @Override
+  public String getProxyUrl(String endpoint, MultivaluedMap<String, String> queryParams) {
+    String atsUrl = viewController.getActiveATSUrl();
+    return String.format("%s/%s%s", atsUrl, endpoint, proxyHelper.getQueryParamsString(queryParams));
+  }
+}

+ 57 - 0
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/rest/BaseProxyResource.java

@@ -0,0 +1,57 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.tez.rest;
+
+import com.google.inject.Inject;
+import org.apache.ambari.view.tez.utils.ProxyHelper;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.*;
+import java.util.HashMap;
+
+/**
+ * Base class for the proxy resources
+ */
+public abstract class BaseProxyResource {
+
+  private ProxyHelper proxyHelper;
+
+  @Inject
+  public BaseProxyResource(ProxyHelper proxyHelper) {
+    this.proxyHelper = proxyHelper;
+  }
+
+  @Path("/{endpoint:.+}")
+  @GET
+  @Produces({MediaType.APPLICATION_JSON})
+  public Response getData(@Context UriInfo uriInfo, @PathParam("endpoint") String endpoint) {
+    String url = getProxyUrl(endpoint, uriInfo.getQueryParameters());
+    String response = proxyHelper.getResponse(url, new HashMap<String, String>());
+
+    JSONObject jsonObject = (JSONObject) JSONValue.parse(response);
+    return Response.ok(jsonObject).type(MediaType.APPLICATION_JSON).build();
+  }
+
+  public abstract String getProxyUrl(String endpoint, MultivaluedMap<String, String> queryParams);
+}

+ 47 - 0
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/rest/RMProxyResource.java

@@ -0,0 +1,47 @@
+/**
+ * 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.ambari.view.tez.rest;
+
+import com.google.inject.Inject;
+import org.apache.ambari.view.tez.ViewController;
+import org.apache.ambari.view.tez.utils.ProxyHelper;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+/**
+ * Proxy class to query the Active RM server
+ */
+public class RMProxyResource extends BaseProxyResource {
+
+  private ViewController viewController;
+  private ProxyHelper proxyHelper;
+
+  @Inject
+  public RMProxyResource(ViewController viewController, ProxyHelper proxyHelper) {
+    super(proxyHelper);
+    this.viewController = viewController;
+    this.proxyHelper = proxyHelper;
+  }
+
+  @Override
+  public String getProxyUrl(String endpoint, MultivaluedMap<String, String> queryParams) {
+    String activeRMUrl = viewController.getActiveRMUrl();
+    return String.format("%s/proxy/%s%s", activeRMUrl, endpoint, proxyHelper.getQueryParamsString(queryParams));
+  }
+}

+ 97 - 0
contrib/views/tez/src/main/java/org/apache/ambari/view/tez/utils/ProxyHelper.java

@@ -0,0 +1,97 @@
+/**
+ * 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.ambari.view.tez.utils;
+
+
+import com.google.inject.Inject;
+import org.apache.ambari.view.URLConnectionProvider;
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.tez.exceptions.ProxyException;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.Map;
+import java.util.Set;
+
+public class ProxyHelper {
+
+  private ViewContext viewContext;
+
+  private static final Logger LOG = LoggerFactory.getLogger(ProxyHelper.class);
+
+  @Inject
+  public ProxyHelper(ViewContext viewContext) {
+    this.viewContext = viewContext;
+  }
+
+
+  public String getResponse(String url, Map<String, String> headers) {
+    LOG.debug("Fetching the result from the URL: {} using proxy", url);
+    InputStream inputStream = null;
+    try {
+      URLConnectionProvider provider = viewContext.getURLConnectionProvider();
+      HttpURLConnection connection = provider.getConnectionAsCurrent(url, "GET", (String) null, headers);
+
+      if(connection.getResponseCode() != Response.Status.OK.getStatusCode()) {
+        LOG.error("Failure in fetching results for the URL: {}. Status: {}", url, connection.getResponseCode());
+        inputStream = connection.getErrorStream();
+        String trace = IOUtils.toString(inputStream);
+        throw new ProxyException("Failed to fetch results by the proxy from url: " + url, connection.getResponseCode(), trace);
+      }
+
+      inputStream = connection.getInputStream();
+      return IOUtils.toString(inputStream);
+
+    } catch (IOException e) {
+      LOG.error("Cannot access the url: {}", url, e);
+      throw new ProxyException("Failed to fetch results by the proxy from url: " + url + ".Internal Error.",
+        Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage());
+    } finally {
+      if (inputStream != null) {
+        try {
+          inputStream.close();
+        } catch (IOException e) { /* Noting to do */ }
+      }
+    }
+  }
+
+  public String getQueryParamsString(MultivaluedMap<String, String> queryParameters) {
+    Set<String> keySet = queryParameters.keySet();
+    StringBuilder builder = new StringBuilder();
+    if(keySet.size() > 0)
+      builder.append("?");
+
+    int count = 0;
+    for(String key: keySet) {
+      builder.append(key);
+      builder.append("=");
+      builder.append(queryParameters.getFirst(key));
+      if(count < keySet.size() - 1) {
+        builder.append("&");
+      }
+    }
+    return builder.toString();
+  }
+}

+ 8 - 0
contrib/views/tez/src/main/resources/view.xml

@@ -41,6 +41,14 @@ limitations under the License. Kerberos, LDAP, Custom. Binary/Htt
     <name>status</name>
     <service-class>org.apache.ambari.view.tez.rest.ViewStatusResource</service-class>
   </resource>
+  <resource>
+    <name>rmproxy</name>
+    <service-class>org.apache.ambari.view.tez.rest.RMProxyResource</service-class>
+  </resource>
+  <resource>
+    <name>atsproxy</name>
+    <service-class>org.apache.ambari.view.tez.rest.AtsProxyResource</service-class>
+  </resource>
   <resource>
     <name>configurations</name>
     <service-class>org.apache.ambari.view.tez.ConfigurationService</service-class>