Package com.vmware.bdd.plugin.clouderamgr.poller.host

Source Code of com.vmware.bdd.plugin.clouderamgr.poller.host.HostInstallPoller

/***************************************************************************
* Copyright (c) 2014 VMware, Inc. All Rights Reserved.
* Licensed 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 com.vmware.bdd.plugin.clouderamgr.poller.host;

import com.cloudera.api.model.ApiCommand;
import com.cloudera.api.v6.RootResourceV6;
import com.google.gson.Gson;
import com.vmware.bdd.plugin.clouderamgr.poller.host.parser.HostInstallDetailsParser;
import com.vmware.bdd.plugin.clouderamgr.poller.host.parser.IDetailsParser;
import com.vmware.bdd.plugin.clouderamgr.poller.host.parser.ParseResult;
import com.vmware.bdd.software.mgmt.plugin.monitor.ClusterReport;
import com.vmware.bdd.software.mgmt.plugin.monitor.ClusterReportQueue;
import com.vmware.bdd.software.mgmt.plugin.monitor.NodeReport;
import com.vmware.bdd.software.mgmt.plugin.monitor.StatusPoller;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.URI;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Author: Xiaoding Bian
* Date: 6/26/14
* Time: 6:25 PM
*/
public class HostInstallPoller extends StatusPoller{
   private static final Logger logger = Logger.getLogger(HostInstallPoller.class);
   private final String POST_ADDR = "/cmf/j_spring_security_check";
   private final String POST_USER_KEY = "j_username";
   private final String POST_PASSWORD_KEY = "j_password";

   private String domain;
   private String username;
   private String password;
   private BasicCookieStore cookieStore;
   private CloseableHttpClient httpClient;
   private PoolingHttpClientConnectionManager httpClientConnectionManager = null;
   private IDetailsParser parser = new HostInstallDetailsParser();

   private int leftStepsNum = 10;

   private RootResourceV6 rootResource;
   private Long parentCmdId;
   private ClusterReportQueue reportQueue;
   private ClusterReport currentReport;
   private int endProgress;
   private ExecutorService executor;
   private Set<String> msgSet = new HashSet<String>();
   private List<String> installingNodes;

   volatile private boolean reported;
   volatile private boolean running =  true;

   public HostInstallPoller(final RootResourceV6 rootResource, final Long parentCmdId,
         final ClusterReport currentReport,
         final ClusterReportQueue reportQueue, int endProgress, List<String> nodeNames,
         String domain, String username, String password) throws Exception {
      this.rootResource = rootResource;
      this.parentCmdId = parentCmdId;
      this.reportQueue = reportQueue;
      this.currentReport = currentReport;
      this.endProgress = endProgress;
      this.installingNodes = nodeNames;
      this.domain = domain;
      this.username = username;
      this.password = password;
   }

   @Override
   public void setup() {
      try {
         login();
         httpClientConnectionManager = new PoolingHttpClientConnectionManager();
         httpClientConnectionManager.setMaxTotal(20);
         this.httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore)
               .setConnectionManager(httpClientConnectionManager).build();
         int maxSessionNum = 10;
         int i = 0;
         reported = true;
         executor = Executors.newCachedThreadPool();
         for (final ApiCommand command : rootResource.getCommandsResource().readCommand(parentCmdId).getChildren()) {
            /* Each crawler will launch a http session with CM server and keep on requesting.
             * So far, we only report cluster level status, so it's no need to monitor each subcommand,
             * especially for large scale cluster.
             */
            if (i == maxSessionNum) {
               break;
            }
            executor.submit(new Crawler(command.getId()));
            i += 1;
         }
      } catch (Exception e) {
         // As this implementation does not follow official APIs, may not work
         // in future version, just ignore any exception
      }
   }

   @Override
   public boolean poll() {
      ClusterReport toReport = null;
      synchronized (currentReport) {
         if (!reported) {
            if (leftStepsNum == 0) {
               currentReport.setProgress(endProgress);
            } else {
               int currentProgress = currentReport.getProgress();
               int toProgress = currentProgress + (endProgress - currentProgress) / leftStepsNum;
               currentReport.setProgress(toProgress > endProgress ? endProgress : toProgress );
               leftStepsNum -= 1;
            }
            toReport = currentReport.clone();
            reported = true;
         }
      }
      if (toReport != null) {
         // free the "currentReport" lock before adding to reportQueue to avoid blocking
         logger.info("report status progress=" + toReport.getProgress() + ", action=" + toReport.getAction());
         reportQueue.addClusterReport(toReport);
      }
      if (rootResource.getCommandsResource().readCommand(parentCmdId).getEndTime() != null) {
         running = false;
         executor.shutdown();
         return true;
      }
      return false;
   }

   @Override
   public void tearDown() {
      try {
         this.httpClient.close();
      } catch (IOException e) {
      }

      if (httpClientConnectionManager != null) {
         httpClientConnectionManager.shutdown();
      }
   }

   private void login() throws Exception {
      cookieStore = new BasicCookieStore();
      CloseableHttpClient loginClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
      URI uri = new URI(domain + POST_ADDR);
      HttpUriRequest login = RequestBuilder.post()
            .setUri(uri)
            .addParameter(POST_USER_KEY, username)
            .addParameter(POST_PASSWORD_KEY, password)
            .build();
      logger.info("Login " + uri.toString());

      CloseableHttpResponse response = loginClient.execute(login);
      try {
         HttpEntity entity = response.getEntity();

         logger.info("Login form get: " + response.getStatusLine());
         EntityUtils.consume(entity);

         List<Cookie> cookies = cookieStore.getCookies();
         if (cookies.isEmpty()) {
            logger.info("Get no cookies");
         } else {
            logger.info("All cookies: " + (new Gson()).toJson(cookies));
         }
      } finally {
         response.close();
         loginClient.close();
      }
   }

   private class Crawler implements Runnable {
      private Long commandId;
      private String currentMsg = null;

      public Crawler(Long commandId) {
         this.commandId = commandId;
      }

      @Override
      public void run() {
         String detailsUrl = domain + "/cmf/command/" + commandId + "/detailsContent";
         HttpGet httpget = new HttpGet(detailsUrl);
         try {
            while (running) {
               CloseableHttpResponse response = null;
               try {
                  if (rootResource.getCommandsResource().readCommand(commandId).getEndTime() != null
                        && !rootResource.getCommandsResource().readCommand(commandId).getSuccess()) {
                     break;
                  }

                  response = httpClient.execute(httpget);
                  ParseResult result = parser.parse(EntityUtils.toString(response.getEntity()));
                  if (result.getPercent() == 100) {
                     break;
                  }
                  if (result.getMessage() != null && !result.getMessage().equals(currentMsg)) {
                     currentMsg = result.getMessage();
                     synchronized (currentReport) {
                        if (!msgSet.contains(currentMsg)) {
                           msgSet.add(currentMsg);
                           setNodeActions();
                           reported = false;
                        }
                     }
                  }
                  Thread.sleep(5 * 1000);
               } catch (Exception e) {
                  // ignore
                  break;
               } finally {
                  try {
                     if(response != null) {
                        response.close();
                     }
                  } catch (IOException e) {
                  }
               }
            }
         } finally {
            httpget.releaseConnection();
         }
      }

      private void setNodeActions() {
         for (String nodeName : installingNodes) {
            NodeReport node = currentReport.getNodeReports().get(nodeName);
            node.setAction(currentMsg);
         }
      }
   }
}
TOP

Related Classes of com.vmware.bdd.plugin.clouderamgr.poller.host.HostInstallPoller

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.