blob: 30a2bb0f3f4061ba4dc99af0d61de5252b1832db [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.slider.server.appmaster.state;
import com.google.common.base.Preconditions;
import org.apache.hadoop.registry.client.binding.RegistryTypeUtils;
import org.apache.hadoop.registry.client.types.Endpoint;
import org.apache.hadoop.registry.client.types.ProtocolTypes;
import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.NodeId;
import org.apache.slider.api.ClusterNode;
import org.apache.slider.api.proto.Messages;
import org.apache.slider.api.types.ContainerInformation;
import org.apache.slider.common.tools.SliderUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Tracking information about a container
*/
public final class RoleInstance implements Cloneable {
public Container container;
/**
* Container ID
*/
public final String id;
public long createTime;
public long startTime;
/**
* flag set when it is released, to know if it has
* already been targeted for termination
*/
public boolean released;
/**
* Name of the role
*/
public String role;
/**
* Version of the app
*/
public String appVersion;
/**
* Role Id; matches priority in resources.json
*/
public int roleId;
/**
* state from StateValues
*/
public int state;
/**
* Exit code: only valid if the state >= STOPPED
*/
public int exitCode;
/**
* what was the command executed?
*/
public String command;
/**
* Any diagnostics
*/
public String diagnostics;
/**
* What is the tail output from the executed process (or [] if not started
* or the log cannot be picked up
*/
public String[] output;
/**
* Any environment details
*/
public String[] environment;
public String host;
public String hostURL;
public ContainerAllocationOutcome placement;
/**
* A list of registered endpoints.
*/
private List<Endpoint> endpoints =
new ArrayList<>(2);
public RoleInstance(ContainerAssignment assignment) {
this(assignment.container);
placement = assignment.placement;
}
/**
* Create an instance to track an allocated container
* @param container a container which must be non null, and have a non-null Id field.
*/
public RoleInstance(Container container) {
Preconditions.checkNotNull(container, "Null container");
Preconditions.checkState(container.getId() != null,
"Null container ID");
this.container = container;
id = container.getId().toString();
if (container.getNodeId() != null) {
host = container.getNodeId().getHost();
}
if (container.getNodeHttpAddress() != null) {
hostURL = "http://" + container.getNodeHttpAddress();
}
}
public ContainerId getId() {
return container.getId();
}
public NodeId getHost() {
return container.getNodeId();
}
@Override
public String toString() {
final StringBuilder sb =
new StringBuilder("RoleInstance{");
sb.append("role='").append(role).append('\'');
sb.append(", id='").append(id).append('\'');
sb.append(", container=").append(SliderUtils.containerToString(container));
sb.append(", createTime=").append(createTime);
sb.append(", startTime=").append(startTime);
sb.append(", released=").append(released);
sb.append(", roleId=").append(roleId);
sb.append(", host=").append(host);
sb.append(", hostURL=").append(hostURL);
sb.append(", state=").append(state);
sb.append(", placement=").append(placement);
sb.append(", exitCode=").append(exitCode);
sb.append(", command='").append(command).append('\'');
sb.append(", diagnostics='").append(diagnostics).append('\'');
sb.append(", output=").append(Arrays.toString(output));
sb.append(", environment=").append(Arrays.toString(environment));
sb.append('}');
return sb.toString();
}
public ContainerId getContainerId() {
return container != null ? container.getId() : null;
}
/**
* Generate the protobuf format of a request
* @return protobuf format. This excludes the Container info
*/
public Messages.RoleInstanceState toProtobuf() {
Messages.RoleInstanceState.Builder builder =
Messages.RoleInstanceState.newBuilder();
if (container != null) {
builder.setName(container.getId().toString());
} else {
builder.setName("unallocated instance");
}
if (command != null) {
builder.setCommand(command);
}
if (environment != null) {
builder.addAllEnvironment(Arrays.asList(environment));
}
if (diagnostics != null) {
builder.setDiagnostics(diagnostics);
}
builder.setExitCode(exitCode);
if (output != null) {
builder.addAllOutput(Arrays.asList(output));
}
if (role != null) {
builder.setRole(role);
}
builder.setRoleId(roleId);
builder.setState(state);
builder.setReleased(released);
builder.setCreateTime(createTime);
builder.setStartTime(startTime);
builder.setHost(host);
builder.setHostURL(hostURL);
if (appVersion != null) {
builder.setAppVersion(appVersion);
}
return builder.build();
}
/**
* Build a serializable ClusterNode structure from this instance.
* This operation is unsynchronized.
* @return a serialized value.
*/
public ClusterNode toClusterNode() {
ClusterNode node;
if (container != null) {
node = new ClusterNode(container.getId());
} else {
node = new ClusterNode();
node.name = "unallocated instance";
}
node.command = command;
node.createTime = createTime;
node.diagnostics = diagnostics;
if (environment != null) {
node.environment = Arrays.copyOf(environment, environment.length);
}
node.exitCode = exitCode;
node.host = host;
node.hostUrl = hostURL;
if (output != null) {
node.output = Arrays.copyOf(output, output.length);
}
node.released = released;
node.role = role;
node.roleId = roleId;
node.startTime = startTime ;
node.state = state;
return node;
}
/**
* Clone operation clones all the simple values but shares the
* Container object into the cloned copy -same with the output,
* diagnostics and env arrays.
* @return a clone of the object
* @throws CloneNotSupportedException
*/
@Override
public Object clone() throws CloneNotSupportedException {
RoleInstance cloned = (RoleInstance) super.clone();
// clone the endpoint list, but not the values
cloned.endpoints = new ArrayList<Endpoint>(this.endpoints);
return cloned;
}
/**
* Get the list of endpoints.
* @return the endpoint list.
*/
public List<Endpoint> getEndpoints() {
return endpoints;
}
/**
* Add an endpoint registration
* @param endpoint endpoint (non-null)
*/
public void addEndpoint(Endpoint endpoint) {
Preconditions.checkArgument(endpoint != null);
endpoints.add(endpoint);
}
/**
* Register a port endpoint as an inet-addr formatted endpoint, using the
* hostname as the first part of the address
* @param port port port
* @param api API API name
*/
public void registerPortEndpoint(int port, String api) {
Endpoint epr =
RegistryTypeUtils.inetAddrEndpoint(api,
ProtocolTypes.PROTOCOL_TCP, host, port);
addEndpoint(epr);
}
/**
* Serialize. Some data structures (e.g output)
* may be shared
* @return a serialized form for marshalling as JSON
*/
public ContainerInformation serialize() {
ContainerInformation info = new ContainerInformation();
info.containerId = id;
info.component = role;
info.appVersion = appVersion;
info.startTime = startTime;
info.createTime = createTime;
info.diagnostics = diagnostics;
info.state = state;
info.host = host;
info.hostURL = hostURL;
info.released = released ? Boolean.TRUE : null;
if (placement != null) {
info.placement = placement.toString();
}
if (output != null) {
info.output = output;
}
return info;
}
}