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    
019    package org.apache.hadoop.yarn.security;
020    
021    import java.io.DataInput;
022    import java.io.DataInputStream;
023    import java.io.DataOutput;
024    import java.io.IOException;
025    
026    import org.apache.commons.logging.Log;
027    import org.apache.commons.logging.LogFactory;
028    import org.apache.hadoop.classification.InterfaceAudience;
029    import org.apache.hadoop.classification.InterfaceAudience.Public;
030    import org.apache.hadoop.classification.InterfaceStability.Evolving;
031    import org.apache.hadoop.io.Text;
032    import org.apache.hadoop.security.UserGroupInformation;
033    import org.apache.hadoop.security.token.Token;
034    import org.apache.hadoop.security.token.TokenIdentifier;
035    import org.apache.hadoop.yarn.api.records.ContainerId;
036    import org.apache.hadoop.yarn.api.records.LogAggregationContext;
037    import org.apache.hadoop.yarn.api.records.Priority;
038    import org.apache.hadoop.yarn.api.records.Resource;
039    import org.apache.hadoop.yarn.api.records.impl.pb.ContainerIdPBImpl;
040    import org.apache.hadoop.yarn.api.records.impl.pb.LogAggregationContextPBImpl;
041    import org.apache.hadoop.yarn.api.records.impl.pb.PriorityPBImpl;
042    import org.apache.hadoop.yarn.api.records.impl.pb.ResourcePBImpl;
043    import org.apache.hadoop.yarn.proto.YarnSecurityTokenProtos.ContainerTokenIdentifierProto;
044    
045    import 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
055    public 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    }