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.ResourcePBImpl;
043import org.apache.hadoop.yarn.proto.YarnSecurityTokenProtos.ContainerTokenIdentifierProto;
044
045import com.google.protobuf.TextFormat;
046
047
048/**
049 * TokenIdentifier for a container. Encodes {@link ContainerId},
050 * {@link Resource} needed by the container and the target NMs host-address.
051 * 
052 */
053@Public
054@Evolving
055public class ContainerTokenIdentifier extends TokenIdentifier {
056
057  private static Log LOG = LogFactory.getLog(ContainerTokenIdentifier.class);
058
059  public static final Text KIND = new Text("ContainerToken");
060
061  private ContainerTokenIdentifierProto proto;
062
063  public ContainerTokenIdentifier(ContainerId containerID,
064      String hostName, String appSubmitter, Resource r, long expiryTimeStamp,
065      int masterKeyId, long rmIdentifier, Priority priority, long creationTime) {
066    this(containerID, hostName, appSubmitter, r, expiryTimeStamp, masterKeyId,
067        rmIdentifier, priority, creationTime, null);
068  }
069
070  public ContainerTokenIdentifier(ContainerId containerID, String hostName,
071      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId,
072      long rmIdentifier, Priority priority, long creationTime,
073      LogAggregationContext logAggregationContext) {
074    ContainerTokenIdentifierProto.Builder builder = 
075        ContainerTokenIdentifierProto.newBuilder();
076    if (containerID != null) {
077      builder.setContainerId(((ContainerIdPBImpl)containerID).getProto());
078    }
079    builder.setNmHostAddr(hostName);
080    builder.setAppSubmitter(appSubmitter);
081    if (r != null) {
082      builder.setResource(((ResourcePBImpl)r).getProto());
083    }
084    builder.setExpiryTimeStamp(expiryTimeStamp);
085    builder.setMasterKeyId(masterKeyId);
086    builder.setRmIdentifier(rmIdentifier);
087    if (priority != null) {
088      builder.setPriority(((PriorityPBImpl)priority).getProto());
089    }
090    builder.setCreationTime(creationTime);
091    
092    if (logAggregationContext != null) {
093      builder.setLogAggregationContext(
094          ((LogAggregationContextPBImpl)logAggregationContext).getProto());
095    }
096    proto = builder.build();
097  }
098
099  /**
100   * Default constructor needed by RPC layer/SecretManager.
101   */
102  public ContainerTokenIdentifier() {
103  }
104
105  public ContainerId getContainerID() {
106    if (!proto.hasContainerId()) {
107      return null;
108    }
109    return new ContainerIdPBImpl(proto.getContainerId());
110  }
111
112  public String getApplicationSubmitter() {
113    return proto.getAppSubmitter();
114  }
115
116  public String getNmHostAddress() {
117    return proto.getNmHostAddr();
118  }
119
120  public Resource getResource() {
121    if (!proto.hasResource()) {
122      return null;
123    }
124    return new ResourcePBImpl(proto.getResource());
125  }
126
127  public long getExpiryTimeStamp() {
128    return proto.getExpiryTimeStamp();
129  }
130
131  public int getMasterKeyId() {
132    return proto.getMasterKeyId();
133  }
134
135  public Priority getPriority() {
136    if (!proto.hasPriority()) {
137      return null;
138    }
139    return new PriorityPBImpl(proto.getPriority());
140  }
141
142  public long getCreationTime() {
143    return proto.getCreationTime();
144  }
145  /**
146   * Get the RMIdentifier of RM in which containers are allocated
147   * @return RMIdentifier
148   */
149  public long getRMIdentifier() {
150    return proto.getRmIdentifier();
151  }
152  
153  public ContainerTokenIdentifierProto getProto() {
154    return proto;
155  }
156
157  public LogAggregationContext getLogAggregationContext() {
158    if (!proto.hasLogAggregationContext()) {
159      return null;
160    }
161    return new LogAggregationContextPBImpl(proto.getLogAggregationContext());
162  }
163
164  @Override
165  public void write(DataOutput out) throws IOException {
166    LOG.debug("Writing ContainerTokenIdentifier to RPC layer: " + this);
167    out.write(proto.toByteArray());
168  }
169
170  @Override
171  public void readFields(DataInput in) throws IOException {
172    proto = ContainerTokenIdentifierProto.parseFrom((DataInputStream)in);
173  }
174
175  @Override
176  public Text getKind() {
177    return KIND;
178  }
179
180  @Override
181  public UserGroupInformation getUser() {
182    String containerId = null;
183    if (proto.hasContainerId()) {
184      containerId = new ContainerIdPBImpl(proto.getContainerId()).toString();
185    }
186    return UserGroupInformation.createRemoteUser(
187        containerId);
188  }
189
190  // TODO: Needed?
191  @InterfaceAudience.Private
192  public static class Renewer extends Token.TrivialRenewer {
193    @Override
194    protected Text getKind() {
195      return KIND;
196    }
197  }
198  
199  @Override
200  public int hashCode() {
201    return getProto().hashCode();
202  }
203
204  @Override
205  public boolean equals(Object other) {
206    if (other == null)
207      return false;
208    if (other.getClass().isAssignableFrom(this.getClass())) {
209      return this.getProto().equals(this.getClass().cast(other).getProto());
210    }
211    return false;
212  }
213
214  @Override
215  public String toString() {
216    return TextFormat.shortDebugString(getProto());
217  }
218}