001/**
002* Licensed to the Apache Software Foundation (ASF) under one
003* or more contributor license agreements.  See the NOTICE file
004* distributed with this work for additional information
005* regarding copyright ownership.  The ASF licenses this file
006* to you under the Apache License, Version 2.0 (the
007* "License"); you may not use this file except in compliance
008* with the License.  You may obtain a copy of the License at
009*
010*     http://www.apache.org/licenses/LICENSE-2.0
011*
012* Unless required by applicable law or agreed to in writing, software
013* distributed under the License is distributed on an "AS IS" BASIS,
014* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015* See the License for the specific language governing permissions and
016* limitations under the License.
017*/
018
019package org.apache.hadoop.yarn.security;
020
021import java.io.DataInput;
022import java.io.DataInputStream;
023import java.io.DataOutput;
024import java.io.IOException;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.apache.hadoop.classification.InterfaceAudience;
029import org.apache.hadoop.classification.InterfaceAudience.Public;
030import org.apache.hadoop.classification.InterfaceStability.Evolving;
031import org.apache.hadoop.io.Text;
032import org.apache.hadoop.security.UserGroupInformation;
033import org.apache.hadoop.security.token.Token;
034import org.apache.hadoop.security.token.TokenIdentifier;
035import org.apache.hadoop.yarn.api.records.ContainerId;
036import org.apache.hadoop.yarn.api.records.ExecutionType;
037import org.apache.hadoop.yarn.api.records.LogAggregationContext;
038import org.apache.hadoop.yarn.api.records.Priority;
039import org.apache.hadoop.yarn.api.records.Resource;
040import org.apache.hadoop.yarn.api.records.impl.pb.ContainerIdPBImpl;
041import org.apache.hadoop.yarn.api.records.impl.pb.LogAggregationContextPBImpl;
042import org.apache.hadoop.yarn.api.records.impl.pb.PriorityPBImpl;
043import org.apache.hadoop.yarn.api.records.impl.pb.ProtoUtils;
044import org.apache.hadoop.yarn.api.records.impl.pb.ResourcePBImpl;
045import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager;
046import org.apache.hadoop.yarn.proto.YarnProtos.ContainerTypeProto;
047import org.apache.hadoop.yarn.proto.YarnProtos.ExecutionTypeProto;
048import org.apache.hadoop.yarn.proto.YarnSecurityTokenProtos.ContainerTokenIdentifierProto;
049import org.apache.hadoop.yarn.server.api.ContainerType;
050
051import com.google.protobuf.TextFormat;
052
053/**
054 * TokenIdentifier for a container. Encodes {@link ContainerId},
055 * {@link Resource} needed by the container and the target NMs host-address.
056 * 
057 */
058@Public
059@Evolving
060public class ContainerTokenIdentifier extends TokenIdentifier {
061
062  private static Log LOG = LogFactory.getLog(ContainerTokenIdentifier.class);
063
064  public static final Text KIND = new Text("ContainerToken");
065
066  private ContainerTokenIdentifierProto proto;
067
068  public ContainerTokenIdentifier(ContainerId containerID,
069      String hostName, String appSubmitter, Resource r, long expiryTimeStamp,
070      int masterKeyId, long rmIdentifier, Priority priority, long creationTime) {
071    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
072        rmIdentifier, priority, creationTime, null,
073        CommonNodeLabelsManager.NO_LABEL, ContainerType.TASK);
074  }
075
076  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
077      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
078      long rmIdentifier, Priority priority, long creationTime,
079      LogAggregationContext logAggregationContext, String nodeLabelExpression) {
080    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
081        rmIdentifier, priority, creationTime, logAggregationContext,
082        nodeLabelExpression, ContainerType.TASK);
083  }
084
085  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
086      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
087      long rmIdentifier, Priority priority, long creationTime,
088      LogAggregationContext logAggregationContext, String nodeLabelExpression,
089      ContainerType containerType) {
090    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
091        rmIdentifier, priority, creationTime, logAggregationContext,
092        nodeLabelExpression, containerType, ExecutionType.GUARANTEED);
093  }
094
095  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
096      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
097      long rmIdentifier, Priority priority, long creationTime,
098      LogAggregationContext logAggregationContext, String nodeLabelExpression,
099      ContainerType containerType, ExecutionType executionType) {
100    ContainerTokenIdentifierProto.Builder builder =
101        ContainerTokenIdentifierProto.newBuilder();
102    if (containerID != null) {
103      builder.setContainerId(((ContainerIdPBImpl)containerID).getProto());
104    }
105    builder.setNmHostAddr(hostName);
106    builder.setAppSubmitter(appSubmitter);
107    if (r != null) {
108      builder.setResource(((ResourcePBImpl)r).getProto());
109    }
110    builder.setExpiryTimeStamp(expiryTimeStamp);
111    builder.setMasterKeyId(masterKeyId);
112    builder.setRmIdentifier(rmIdentifier);
113    if (priority != null) {
114      builder.setPriority(((PriorityPBImpl)priority).getProto());
115    }
116    builder.setCreationTime(creationTime);
117    
118    if (logAggregationContext != null) {
119      builder.setLogAggregationContext(
120          ((LogAggregationContextPBImpl)logAggregationContext).getProto());
121    }
122    
123    if (nodeLabelExpression != null) {
124      builder.setNodeLabelExpression(nodeLabelExpression);
125    }
126    builder.setContainerType(convertToProtoFormat(containerType));
127    builder.setExecutionType(convertToProtoFormat(executionType));
128
129    proto = builder.build();
130  }
131
132  /**
133   * Default constructor needed by RPC layer/SecretManager.
134   */
135  public ContainerTokenIdentifier() {
136  }
137
138  public ContainerId getContainerID() {
139    if (!proto.hasContainerId()) {
140      return null;
141    }
142    return new ContainerIdPBImpl(proto.getContainerId());
143  }
144
145  public String getApplicationSubmitter() {
146    return proto.getAppSubmitter();
147  }
148
149  public String getNmHostAddress() {
150    return proto.getNmHostAddr();
151  }
152
153  public Resource getResource() {
154    if (!proto.hasResource()) {
155      return null;
156    }
157    return new ResourcePBImpl(proto.getResource());
158  }
159
160  public long getExpiryTimeStamp() {
161    return proto.getExpiryTimeStamp();
162  }
163
164  public int getMasterKeyId() {
165    return proto.getMasterKeyId();
166  }
167
168  public Priority getPriority() {
169    if (!proto.hasPriority()) {
170      return null;
171    }
172    return new PriorityPBImpl(proto.getPriority());
173  }
174
175  public long getCreationTime() {
176    return proto.getCreationTime();
177  }
178  /**
179   * Get the RMIdentifier of RM in which containers are allocated.
180   * @return RMIdentifier
181   */
182  public long getRMIdentifier() {
183    return proto.getRmIdentifier();
184  }
185
186  /**
187   * Get the ContainerType of container to allocate
188   * @return ContainerType
189   */
190  public ContainerType getContainerType(){
191    if (!proto.hasContainerType()) {
192      return null;
193    }
194    return convertFromProtoFormat(proto.getContainerType());
195  }
196
197  /**
198   * Get the ExecutionType of container to allocate
199   * @return ExecutionType
200   */
201  public ExecutionType getExecutionType(){
202    if (!proto.hasExecutionType()) {
203      return null;
204    }
205    return convertFromProtoFormat(proto.getExecutionType());
206  }
207
208  public ContainerTokenIdentifierProto getProto() {
209    return proto;
210  }
211
212  public LogAggregationContext getLogAggregationContext() {
213    if (!proto.hasLogAggregationContext()) {
214      return null;
215    }
216    return new LogAggregationContextPBImpl(proto.getLogAggregationContext());
217  }
218
219  @Override
220  public void write(DataOutput out) throws IOException {
221    LOG.debug("Writing ContainerTokenIdentifier to RPC layer: " + this);
222    out.write(proto.toByteArray());
223  }
224
225  @Override
226  public void readFields(DataInput in) throws IOException {
227    proto = ContainerTokenIdentifierProto.parseFrom((DataInputStream)in);
228  }
229
230  @Override
231  public Text getKind() {
232    return KIND;
233  }
234
235  @Override
236  public UserGroupInformation getUser() {
237    String containerId = null;
238    if (proto.hasContainerId()) {
239      containerId = new ContainerIdPBImpl(proto.getContainerId()).toString();
240    }
241    return UserGroupInformation.createRemoteUser(
242        containerId);
243  }
244  
245  /**
246   * Get the node-label-expression in the original ResourceRequest
247   */
248  public String getNodeLabelExpression() {
249    if (proto.hasNodeLabelExpression()) {
250      return proto.getNodeLabelExpression();
251    }
252    return CommonNodeLabelsManager.NO_LABEL;
253  }
254
255  // TODO: Needed?
256  @InterfaceAudience.Private
257  public static class Renewer extends Token.TrivialRenewer {
258    @Override
259    protected Text getKind() {
260      return KIND;
261    }
262  }
263  
264  @Override
265  public int hashCode() {
266    return getProto().hashCode();
267  }
268
269  @Override
270  public boolean equals(Object other) {
271    if (other == null)
272      return false;
273    if (other.getClass().isAssignableFrom(this.getClass())) {
274      return this.getProto().equals(this.getClass().cast(other).getProto());
275    }
276    return false;
277  }
278
279  @Override
280  public String toString() {
281    return TextFormat.shortDebugString(getProto());
282  }
283
284  private ContainerTypeProto convertToProtoFormat(ContainerType containerType) {
285    return ProtoUtils.convertToProtoFormat(containerType);
286  }
287
288  private ContainerType convertFromProtoFormat(
289      ContainerTypeProto containerType) {
290    return ProtoUtils.convertFromProtoFormat(containerType);
291  }
292
293  private ExecutionTypeProto convertToProtoFormat(ExecutionType executionType) {
294    return ProtoUtils.convertToProtoFormat(executionType);
295  }
296
297  private ExecutionType convertFromProtoFormat(
298      ExecutionTypeProto executionType) {
299    return ProtoUtils.convertFromProtoFormat(executionType);
300  }
301}