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