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, 0, hostName, appSubmitter, r, expiryTimeStamp,
091        masterKeyId, rmIdentifier, priority, creationTime,
092        logAggregationContext, nodeLabelExpression, containerType,
093        ExecutionType.GUARANTEED);
094  }
095
096  public ContainerTokenIdentifier(ContainerId containerID, int containerVersion,
097      String hostName, String appSubmitter, Resource r, long expiryTimeStamp,
098      int masterKeyId, long rmIdentifier, Priority priority, long creationTime,
099      LogAggregationContext logAggregationContext, String nodeLabelExpression,
100      ContainerType containerType, ExecutionType executionType) {
101    ContainerTokenIdentifierProto.Builder builder =
102        ContainerTokenIdentifierProto.newBuilder();
103    if (containerID != null) {
104      builder.setContainerId(((ContainerIdPBImpl)containerID).getProto());
105    }
106    builder.setVersion(containerVersion);
107    builder.setNmHostAddr(hostName);
108    builder.setAppSubmitter(appSubmitter);
109    if (r != null) {
110      builder.setResource(((ResourcePBImpl)r).getProto());
111    }
112    builder.setExpiryTimeStamp(expiryTimeStamp);
113    builder.setMasterKeyId(masterKeyId);
114    builder.setRmIdentifier(rmIdentifier);
115    if (priority != null) {
116      builder.setPriority(((PriorityPBImpl)priority).getProto());
117    }
118    builder.setCreationTime(creationTime);
119    
120    if (logAggregationContext != null) {
121      builder.setLogAggregationContext(
122          ((LogAggregationContextPBImpl)logAggregationContext).getProto());
123    }
124    
125    if (nodeLabelExpression != null) {
126      builder.setNodeLabelExpression(nodeLabelExpression);
127    }
128    builder.setContainerType(convertToProtoFormat(containerType));
129    builder.setExecutionType(convertToProtoFormat(executionType));
130
131    proto = builder.build();
132  }
133
134  /**
135   * Default constructor needed by RPC layer/SecretManager.
136   */
137  public ContainerTokenIdentifier() {
138  }
139
140  public ContainerId getContainerID() {
141    if (!proto.hasContainerId()) {
142      return null;
143    }
144    return new ContainerIdPBImpl(proto.getContainerId());
145  }
146
147  public String getApplicationSubmitter() {
148    return proto.getAppSubmitter();
149  }
150
151  public String getNmHostAddress() {
152    return proto.getNmHostAddr();
153  }
154
155  public Resource getResource() {
156    if (!proto.hasResource()) {
157      return null;
158    }
159    return new ResourcePBImpl(proto.getResource());
160  }
161
162  public long getExpiryTimeStamp() {
163    return proto.getExpiryTimeStamp();
164  }
165
166  public int getMasterKeyId() {
167    return proto.getMasterKeyId();
168  }
169
170  public Priority getPriority() {
171    if (!proto.hasPriority()) {
172      return null;
173    }
174    return new PriorityPBImpl(proto.getPriority());
175  }
176
177  public long getCreationTime() {
178    return proto.getCreationTime();
179  }
180  /**
181   * Get the RMIdentifier of RM in which containers are allocated.
182   * @return RMIdentifier
183   */
184  public long getRMIdentifier() {
185    return proto.getRmIdentifier();
186  }
187
188  /**
189   * Get the ContainerType of container to allocate.
190   * @return ContainerType
191   */
192  public ContainerType getContainerType(){
193    if (!proto.hasContainerType()) {
194      return null;
195    }
196    return convertFromProtoFormat(proto.getContainerType());
197  }
198
199  /**
200   * Get the ExecutionType of container to allocate
201   * @return ExecutionType
202   */
203  public ExecutionType getExecutionType(){
204    if (!proto.hasExecutionType()) {
205      return null;
206    }
207    return convertFromProtoFormat(proto.getExecutionType());
208  }
209
210  public ContainerTokenIdentifierProto getProto() {
211    return proto;
212  }
213
214  public LogAggregationContext getLogAggregationContext() {
215    if (!proto.hasLogAggregationContext()) {
216      return null;
217    }
218    return new LogAggregationContextPBImpl(proto.getLogAggregationContext());
219  }
220
221  @Override
222  public void write(DataOutput out) throws IOException {
223    LOG.debug("Writing ContainerTokenIdentifier to RPC layer: " + this);
224    out.write(proto.toByteArray());
225  }
226
227  @Override
228  public void readFields(DataInput in) throws IOException {
229    proto = ContainerTokenIdentifierProto.parseFrom((DataInputStream)in);
230  }
231
232  @Override
233  public Text getKind() {
234    return KIND;
235  }
236
237  @Override
238  public UserGroupInformation getUser() {
239    String containerId = null;
240    if (proto.hasContainerId()) {
241      containerId = new ContainerIdPBImpl(proto.getContainerId()).toString();
242    }
243    return UserGroupInformation.createRemoteUser(
244        containerId);
245  }
246
247  /**
248   * Get the Container version
249   * @return container version
250   */
251  public int getVersion() {
252    if (proto.hasVersion()) {
253      return proto.getVersion();
254    } else {
255      return 0;
256    }
257  }
258  /**
259   * Get the node-label-expression in the original ResourceRequest
260   */
261  public String getNodeLabelExpression() {
262    if (proto.hasNodeLabelExpression()) {
263      return proto.getNodeLabelExpression();
264    }
265    return CommonNodeLabelsManager.NO_LABEL;
266  }
267
268  // TODO: Needed?
269  @InterfaceAudience.Private
270  public static class Renewer extends Token.TrivialRenewer {
271    @Override
272    protected Text getKind() {
273      return KIND;
274    }
275  }
276  
277  @Override
278  public int hashCode() {
279    return getProto().hashCode();
280  }
281
282  @Override
283  public boolean equals(Object other) {
284    if (other == null)
285      return false;
286    if (other.getClass().isAssignableFrom(this.getClass())) {
287      return this.getProto().equals(this.getClass().cast(other).getProto());
288    }
289    return false;
290  }
291
292  @Override
293  public String toString() {
294    return TextFormat.shortDebugString(getProto());
295  }
296
297  private ContainerTypeProto convertToProtoFormat(ContainerType containerType) {
298    return ProtoUtils.convertToProtoFormat(containerType);
299  }
300
301  private ContainerType convertFromProtoFormat(
302      ContainerTypeProto containerType) {
303    return ProtoUtils.convertFromProtoFormat(containerType);
304  }
305
306  private ExecutionTypeProto convertToProtoFormat(ExecutionType executionType) {
307    return ProtoUtils.convertToProtoFormat(executionType);
308  }
309
310  private ExecutionType convertFromProtoFormat(
311      ExecutionTypeProto executionType) {
312    return ProtoUtils.convertFromProtoFormat(executionType);
313  }
314}