blob: 8947df57f76d59f759fbe9cf6010087db58b4dca [file] [log] [blame]
/*
* 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.drill.yarn.appMaster.http;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.drill.yarn.appMaster.AMYarnFacade.YarnAppHostReport;
import org.apache.drill.yarn.appMaster.ClusterController;
import org.apache.drill.yarn.appMaster.ClusterControllerImpl;
import org.apache.drill.yarn.appMaster.ClusterControllerImpl.State;
import org.apache.drill.yarn.appMaster.ControllerVisitor;
import org.apache.drill.yarn.appMaster.Scheduler;
import org.apache.drill.yarn.appMaster.SchedulerStateActions;
import org.apache.drill.yarn.core.ContainerRequestSpec;
import org.apache.drill.yarn.core.DrillOnYarnConfig;
import org.apache.drill.yarn.zk.ZKRegistry;
import com.typesafe.config.Config;
@XmlRootElement
public class ControllerModel implements ControllerVisitor {
public static class ClusterGroupModel {
protected String name;
protected String type;
protected int targetCount;
protected int taskCount;
protected int liveCount;
protected int memory;
protected int vcores;
protected double disks;
public String getName( ) { return name; }
public String getType( ) { return type; }
public int getTargetCount( ) { return targetCount; }
public int getTaskCount( ) { return taskCount; }
public int getLiveCount( ) { return liveCount; }
public int getMemory( ) { return memory; }
public int getVcores( ) { return vcores; }
public String getDisks( ) {
return String.format( "%.02f", disks );
}
}
protected String zkConnectStr;
protected String zkRoot;
protected String zkClusterId;
protected ClusterControllerImpl.State state;
protected String stateHint;
protected boolean supportsDisks;
protected int yarnMemory;
protected int yarnVcores;
protected int yarnNodeCount;
protected int taskCount;
protected int liveCount;
protected int unmanagedCount;
protected int targetCount;
protected int totalDrillMemory;
protected int totalDrillVcores;
protected double totalDrillDisks;
protected int blacklistCount;
protected int freeNodeCount;
protected YarnAppHostReport appRpt;
protected int refreshSecs;
protected List<ClusterGroupModel> groups = new ArrayList<>( );
public boolean supportsDiskResource( ) { return supportsDisks; }
public int getRefreshSecs( ) { return refreshSecs; }
public String getZkConnectionStr( ) { return zkConnectStr; }
public String getZkRoot( ) { return zkRoot; }
public String getZkClusterId( ) { return zkClusterId; }
public String getAppId( ) { return appRpt.appId; }
public String getRmHost( ) { return appRpt.rmHost; }
public String getRmLink( ) { return appRpt.rmUrl; }
public String getNmHost( ) { return appRpt.nmHost; }
public String getNmLink( ) { return appRpt.nmUrl; }
public String getRmAppLink( ) { return appRpt.rmAppUrl; }
public String getNmAppLink( ) { return appRpt.nmAppUrl; }
public String getState( ) { return state.toString( ); }
public String getStateHint( ) { return stateHint; }
public int getYarnMemory( ) { return yarnMemory; }
public int getYarnVcores( ) { return yarnVcores; }
public int getDrillTotalMemory( ) { return totalDrillMemory; }
public int getDrillTotalVcores( ) { return totalDrillVcores; }
public String getDrillTotalDisks( ) {
return String.format( "%.2f", totalDrillDisks );
}
public int getYarnNodeCount( ) { return yarnNodeCount; }
public int getTaskCount( ) { return taskCount; }
public int getLiveCount( ) { return liveCount; }
public int getUnmanagedCount( ) { return unmanagedCount; }
public int getTargetCount( ) { return targetCount; }
public List<ClusterGroupModel> getGroups( ) { return groups; }
public int getBlacklistCount( ) { return blacklistCount; }
public int getFreeNodeCount( ) { return freeNodeCount; }
private static Map<ClusterControllerImpl.State,String> stateHints = makeStateHints( );
@Override
public void visit(ClusterController controller) {
Config config = DrillOnYarnConfig.config();
refreshSecs = config.getInt( DrillOnYarnConfig.HTTP_REFRESH_SECS );
zkConnectStr = config.getString( DrillOnYarnConfig.ZK_CONNECT );
zkRoot = config.getString( DrillOnYarnConfig.ZK_ROOT );
zkClusterId = config.getString( DrillOnYarnConfig.CLUSTER_ID );
ClusterControllerImpl impl = (ClusterControllerImpl) controller;
appRpt = impl.getYarn().getAppHostReport();
state = impl.getState( );
stateHint = stateHints.get( state );
// Removed based on feedback. Users should check the
// YARN RM UI instead.
// if ( state == State.LIVE ) {
// RegisterApplicationMasterResponse resp = impl.getYarn( ).getRegistrationResponse();
// yarnVcores = resp.getMaximumResourceCapability().getVirtualCores();
// yarnMemory = resp.getMaximumResourceCapability().getMemory();
// yarnNodeCount = impl.getYarn( ).getNodeCount();
// }
capturePools( impl );
supportsDisks = impl.supportsDiskResource();
blacklistCount = impl.getNodeInventory( ).getBlacklist( ).size( );
freeNodeCount = impl.getFreeNodeCount();
}
private void capturePools(ClusterControllerImpl impl) {
for ( SchedulerStateActions pool : impl.getPools( ) ) {
ControllerModel.ClusterGroupModel poolModel = new ControllerModel.ClusterGroupModel( );
Scheduler sched = pool.getScheduler();
ContainerRequestSpec containerSpec = sched.getResource( );
poolModel.name = sched.getName();
poolModel.type = sched.getType( );
poolModel.targetCount = sched.getTarget();
poolModel.memory = containerSpec.memoryMb;
poolModel.vcores = containerSpec.vCores;
poolModel.disks = containerSpec.disks;
poolModel.taskCount = pool.getTaskCount();
poolModel.liveCount = pool.getLiveCount( );
targetCount += poolModel.targetCount;
taskCount += poolModel.taskCount;
liveCount += poolModel.liveCount;
totalDrillMemory += poolModel.liveCount * poolModel.memory;
totalDrillVcores += poolModel.liveCount * poolModel.vcores;
totalDrillDisks += poolModel.liveCount * poolModel.disks;
groups.add( poolModel );
}
if ( state != State.LIVE ) {
targetCount = 0;
}
}
/**
* Count the unmanaged drillbits. Do this as a separate call, not via the
* {@link #visit(ClusterController) visit} method, to avoid locking both
* the cluster controller and ZK registry.
*
* @param controller
*/
public void countStrayDrillbits(ClusterController controller) {
ZKRegistry zkRegistry = (ZKRegistry) controller.getProperty( ZKRegistry.CONTROLLER_PROPERTY );
if ( zkRegistry != null ) {
unmanagedCount = zkRegistry.listUnmanagedDrillits().size();
}
}
/**
* Create a table of user-visible descriptions for each controller state.
*
* @return
*/
private static Map<State, String> makeStateHints() {
Map<ClusterControllerImpl.State,String> hints = new HashMap<>( );
// UI likely will never display the FAILED state.
hints.put( ClusterControllerImpl.State.START, "AM is starting up." );
hints.put( ClusterControllerImpl.State.LIVE, "AM is operating normally." );
hints.put( ClusterControllerImpl.State.ENDING, "AM is shutting down." );
// UI will never display the ENDED state.
hints.put( ClusterControllerImpl.State.ENDED, "AM is about to exit." );
// UI will never display the FAILED state.
hints.put( ClusterControllerImpl.State.FAILED, "AM failed to start and is about to exit." );
return hints;
}
}