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.LogAggregationContext;
037import org.apache.hadoop.yarn.api.records.Priority;
038import org.apache.hadoop.yarn.api.records.Resource;
039import org.apache.hadoop.yarn.api.records.impl.pb.ContainerIdPBImpl;
040import org.apache.hadoop.yarn.api.records.impl.pb.LogAggregationContextPBImpl;
041import org.apache.hadoop.yarn.api.records.impl.pb.PriorityPBImpl;
042import org.apache.hadoop.yarn.api.records.impl.pb.ProtoUtils;
043import org.apache.hadoop.yarn.api.records.impl.pb.ResourcePBImpl;
044import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager;
045import org.apache.hadoop.yarn.proto.YarnProtos.ContainerTypeProto;
046import org.apache.hadoop.yarn.proto.YarnSecurityTokenProtos.ContainerTokenIdentifierProto;
047import org.apache.hadoop.yarn.server.api.ContainerType;
048
049import com.google.protobuf.TextFormat;
050
051/**
052 * TokenIdentifier for a container. Encodes {@link ContainerId},
053 * {@link Resource} needed by the container and the target NMs host-address.
054 * 
055 */
056@Public
057@Evolving
058public class ContainerTokenIdentifier extends TokenIdentifier {
059
060  private static Log LOG = LogFactory.getLog(ContainerTokenIdentifier.class);
061
062  public static final Text KIND = new Text("ContainerToken");
063
064  private ContainerTokenIdentifierProto proto;
065
066  public ContainerTokenIdentifier(ContainerId containerID,
067      String hostName, String appSubmitter, Resource r, long expiryTimeStamp,
068      int masterKeyId, long rmIdentifier, Priority priority, long creationTime) {
069    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
070        rmIdentifier, priority, creationTime, null,
071        CommonNodeLabelsManager.NO_LABEL, ContainerType.TASK);
072  }
073
074  /**
075   * Creates a instance.
076   *
077   * @param appSubmitter appSubmitter
078   * @param containerID container ID
079   * @param creationTime creation time
080   * @param expiryTimeStamp expiry timestamp
081   * @param hostName hostname
082   * @param logAggregationContext log aggregation context
083   * @param masterKeyId master key ID
084   * @param priority priority
085   * @param r resource needed by the container
086   * @param rmIdentifier ResourceManager identifier
087   * @deprecated Use one of the other constructors instead.
088   */
089  @Deprecated
090  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
091      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
092      long rmIdentifier, Priority priority, long creationTime,
093      LogAggregationContext logAggregationContext) {
094    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
095        rmIdentifier, priority, creationTime, logAggregationContext,
096        CommonNodeLabelsManager.NO_LABEL);
097  }
098
099  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
100      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
101      long rmIdentifier, Priority priority, long creationTime,
102      LogAggregationContext logAggregationContext, String nodeLabelExpression) {
103    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
104        rmIdentifier, priority, creationTime, logAggregationContext,
105        nodeLabelExpression, ContainerType.TASK);
106  }
107
108  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
109      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
110      long rmIdentifier, Priority priority, long creationTime,
111      LogAggregationContext logAggregationContext, String nodeLabelExpression,
112      ContainerType containerType) {
113    this(containerID, 0, hostName, appSubmitter, r, expiryTimeStamp,
114        masterKeyId, rmIdentifier, priority, creationTime,
115        logAggregationContext, nodeLabelExpression, containerType);
116  }
117
118  public ContainerTokenIdentifier(ContainerId containerID, int containerVersion,
119      String hostName, String appSubmitter, Resource r, long expiryTimeStamp,
120      int masterKeyId, long rmIdentifier, Priority priority, long creationTime,
121      LogAggregationContext logAggregationContext, String nodeLabelExpression,
122      ContainerType containerType) {
123    ContainerTokenIdentifierProto.Builder builder =
124        ContainerTokenIdentifierProto.newBuilder();
125    if (containerID != null) {
126      builder.setContainerId(((ContainerIdPBImpl)containerID).getProto());
127    }
128    builder.setVersion(containerVersion);
129    builder.setNmHostAddr(hostName);
130    builder.setAppSubmitter(appSubmitter);
131    if (r != null) {
132      builder.setResource(((ResourcePBImpl)r).getProto());
133    }
134    builder.setExpiryTimeStamp(expiryTimeStamp);
135    builder.setMasterKeyId(masterKeyId);
136    builder.setRmIdentifier(rmIdentifier);
137    if (priority != null) {
138      builder.setPriority(((PriorityPBImpl)priority).getProto());
139    }
140    builder.setCreationTime(creationTime);
141    
142    if (logAggregationContext != null) {
143      builder.setLogAggregationContext(
144          ((LogAggregationContextPBImpl)logAggregationContext).getProto());
145    }
146    
147    if (nodeLabelExpression != null) {
148      builder.setNodeLabelExpression(nodeLabelExpression);
149    }
150    builder.setContainerType(convertToProtoFormat(containerType));
151
152    proto = builder.build();
153  }
154
155  /**
156   * Default constructor needed by RPC layer/SecretManager.
157   */
158  public ContainerTokenIdentifier() {
159  }
160
161  public ContainerId getContainerID() {
162    if (!proto.hasContainerId()) {
163      return null;
164    }
165    return new ContainerIdPBImpl(proto.getContainerId());
166  }
167
168  public String getApplicationSubmitter() {
169    return proto.getAppSubmitter();
170  }
171
172  public String getNmHostAddress() {
173    return proto.getNmHostAddr();
174  }
175
176  public Resource getResource() {
177    if (!proto.hasResource()) {
178      return null;
179    }
180    return new ResourcePBImpl(proto.getResource());
181  }
182
183  public long getExpiryTimeStamp() {
184    return proto.getExpiryTimeStamp();
185  }
186
187  public int getMasterKeyId() {
188    return proto.getMasterKeyId();
189  }
190
191  public Priority getPriority() {
192    if (!proto.hasPriority()) {
193      return null;
194    }
195    return new PriorityPBImpl(proto.getPriority());
196  }
197
198  public long getCreationTime() {
199    return proto.getCreationTime();
200  }
201  /**
202   * Get the RMIdentifier of RM in which containers are allocated
203   * @return RMIdentifier
204   */
205  public long getRMIdentifier() {
206    return proto.getRmIdentifier();
207  }
208
209  /**
210   * Get the ContainerType of container to allocate.
211   * @return ContainerType
212   */
213  public ContainerType getContainerType(){
214    if (!proto.hasContainerType()) {
215      return null;
216    }
217    return convertFromProtoFormat(proto.getContainerType());
218  }
219
220  public ContainerTokenIdentifierProto getProto() {
221    return proto;
222  }
223
224  public LogAggregationContext getLogAggregationContext() {
225    if (!proto.hasLogAggregationContext()) {
226      return null;
227    }
228    return new LogAggregationContextPBImpl(proto.getLogAggregationContext());
229  }
230
231  @Override
232  public void write(DataOutput out) throws IOException {
233    LOG.debug("Writing ContainerTokenIdentifier to RPC layer: " + this);
234    out.write(proto.toByteArray());
235  }
236
237  @Override
238  public void readFields(DataInput in) throws IOException {
239    proto = ContainerTokenIdentifierProto.parseFrom((DataInputStream)in);
240  }
241
242  @Override
243  public Text getKind() {
244    return KIND;
245  }
246
247  @Override
248  public UserGroupInformation getUser() {
249    String containerId = null;
250    if (proto.hasContainerId()) {
251      containerId = new ContainerIdPBImpl(proto.getContainerId()).toString();
252    }
253    return UserGroupInformation.createRemoteUser(
254        containerId);
255  }
256
257  /**
258   * Get the Container version
259   * @return container version
260   */
261  public int getVersion() {
262    if (proto.hasVersion()) {
263      return proto.getVersion();
264    } else {
265      return 0;
266    }
267  }
268  /**
269   * Get the node-label-expression in the original ResourceRequest
270   */
271  public String getNodeLabelExpression() {
272    if (proto.hasNodeLabelExpression()) {
273      return proto.getNodeLabelExpression();
274    }
275    return CommonNodeLabelsManager.NO_LABEL;
276  }
277
278  // TODO: Needed?
279  @InterfaceAudience.Private
280  public static class Renewer extends Token.TrivialRenewer {
281    @Override
282    protected Text getKind() {
283      return KIND;
284    }
285  }
286  
287  @Override
288  public int hashCode() {
289    return getProto().hashCode();
290  }
291
292  @Override
293  public boolean equals(Object other) {
294    if (other == null)
295      return false;
296    if (other.getClass().isAssignableFrom(this.getClass())) {
297      return this.getProto().equals(this.getClass().cast(other).getProto());
298    }
299    return false;
300  }
301
302  @Override
303  public String toString() {
304    return TextFormat.shortDebugString(getProto());
305  }
306
307  private ContainerTypeProto convertToProtoFormat(ContainerType containerType) {
308    return ProtoUtils.convertToProtoFormat(containerType);
309  }
310
311  private ContainerType convertFromProtoFormat(
312      ContainerTypeProto containerType) {
313    return ProtoUtils.convertFromProtoFormat(containerType);
314  }
315}