/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hdfs.server.namenode;

import static org.apache.hadoop.hdfs.server.common.HdfsServerConstants.CRYPTO_XATTR_FILE_ENCRYPTION_INFO;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivilegedExceptionAction;
import java.util.AbstractMap;
import java.util.concurrent.ExecutorService;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.crypto.CipherSuite;
import org.apache.hadoop.crypto.CryptoProtocolVersion;
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.EncryptedKeyVersion;
import org.apache.hadoop.fs.FileEncryptionInfo;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.UnresolvedLinkException;
import org.apache.hadoop.fs.XAttr;
import org.apache.hadoop.fs.XAttrSetFlag;
import org.apache.hadoop.fs.BatchedRemoteIterator.BatchedListEntries;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.hdfs.XAttrHelper;
import org.apache.hadoop.hdfs.protocol.EncryptionZone;
import org.apache.hadoop.hdfs.protocol.ZoneReencryptionStatus;
import org.apache.hadoop.hdfs.protocol.SnapshotAccessControlException;
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos;
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ReencryptionInfoProto;
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.ZoneEncryptionInfoProto;
import org.apache.hadoop.hdfs.protocolPB.PBHelperClient;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory.DirOp;
import org.apache.hadoop.hdfs.server.namenode.ReencryptionUpdater.FileEdekInfo;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.util.Lists;
import org.apache.hadoop.util.Time;

import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
import org.apache.hadoop.thirdparty.protobuf.InvalidProtocolBufferException;

import static org.apache.hadoop.hdfs.server.common.HdfsServerConstants.CRYPTO_XATTR_ENCRYPTION_ZONE;
import static org.apache.hadoop.util.Time.monotonicNow;

/**
 * Helper class to perform encryption zone operation.
 */
final class FSDirEncryptionZoneOp {

  /**
   * Private constructor for preventing FSDirEncryptionZoneOp object creation.
   * Static-only class.
   */
  private FSDirEncryptionZoneOp() {}

  /**
   * Invoke KeyProvider APIs to generate an encrypted data encryption key for
   * an encryption zone. Should not be called with any locks held.
   *
   * @param fsd the namespace tree.
   * @param ezKeyName key name of an encryption zone
   * @return New EDEK, or null if ezKeyName is null
   * @throws IOException
   */
  private static EncryptedKeyVersion generateEncryptedDataEncryptionKey(
      final FSDirectory fsd, final String ezKeyName) throws IOException {
    // must not be holding lock during this operation
    assert !fsd.getFSNamesystem().hasReadLock();
    assert !fsd.getFSNamesystem().hasWriteLock();
    if (ezKeyName == null) {
      return null;
    }
    long generateEDEKStartTime = monotonicNow();
    // Generate EDEK with login user (hdfs) so that KMS does not need
    // an extra proxy configuration allowing hdfs to proxy its clients and
    // KMS does not need configuration to allow non-hdfs user GENERATE_EEK
    // operation.
    EncryptedKeyVersion edek = SecurityUtil.doAsLoginUser(
        new PrivilegedExceptionAction<EncryptedKeyVersion>() {
          @Override
          public EncryptedKeyVersion run() throws IOException {
            try {
              return fsd.getProvider().generateEncryptedKey(ezKeyName);
            } catch (GeneralSecurityException e) {
              throw new IOException(e);
            }
          }
        });
    long generateEDEKTime = monotonicNow() - generateEDEKStartTime;
    NameNode.getNameNodeMetrics().addGenerateEDEKTime(generateEDEKTime);
    Preconditions.checkNotNull(edek);
    return edek;
  }

  static KeyProvider.Metadata ensureKeyIsInitialized(final FSDirectory fsd,
      final String keyName, final String src) throws IOException {
    KeyProviderCryptoExtension provider = fsd.getProvider();
    if (provider == null) {
      throw new IOException("Can't create an encryption zone for " + src
          + " since no key provider is available.");
    }
    if (keyName == null || keyName.isEmpty()) {
      throw new IOException("Must specify a key name when creating an "
          + "encryption zone");
    }
    EncryptionFaultInjector.getInstance().ensureKeyIsInitialized();
    KeyProvider.Metadata metadata = provider.getMetadata(keyName);
    if (metadata == null) {
      /*
       * It would be nice if we threw something more specific than
       * IOException when the key is not found, but the KeyProvider API
       * doesn't provide for that. If that API is ever changed to throw
       * something more specific (e.g. UnknownKeyException) then we can
       * update this to match it, or better yet, just rethrow the
       * KeyProvider's exception.
       */
      throw new IOException("Key " + keyName + " doesn't exist.");
    }
    // If the provider supports pool for EDEKs, this will fill in the pool
    provider.warmUpEncryptedKeys(keyName);
    return metadata;
  }

  /**
   * Create an encryption zone on directory path using the specified key.
   *
   * @param fsd the namespace tree.
   * @param srcArg the path of a directory which will be the root of the
   *               encryption zone. The directory must be empty
   * @param pc permission checker to check fs permission
   * @param cipher the name of the cipher suite, which will be used
   *               when it is generated.
   * @param keyName name of a key which must be present in the configured
   *                KeyProvider
   * @param logRetryCache whether to record RPC ids in editlog for retry cache
   *                      rebuilding
   * @return FileStatus
   * @throws IOException
   */
  static FileStatus createEncryptionZone(final FSDirectory fsd,
      final String srcArg, final FSPermissionChecker pc, final String cipher,
      final String keyName, final boolean logRetryCache) throws IOException {
    final CipherSuite suite = CipherSuite.convert(cipher);
    List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
    // For now this is hard coded, as we only support one method.
    final CryptoProtocolVersion version =
        CryptoProtocolVersion.ENCRYPTION_ZONES;

    final INodesInPath iip;
    fsd.writeLock();
    try {
      iip = fsd.resolvePath(pc, srcArg, DirOp.WRITE);
      final XAttr ezXAttr = fsd.ezManager.createEncryptionZone(iip, suite,
          version, keyName);
      xAttrs.add(ezXAttr);
    } finally {
      fsd.writeUnlock();
    }
    fsd.getEditLog().logSetXAttrs(iip.getPath(), xAttrs, logRetryCache);
    return fsd.getAuditFileInfo(iip);
  }

  /**
   * Get the encryption zone for the specified path.
   *
   * @param fsd the namespace tree.
   * @param srcArg the path of a file or directory to get the EZ for
   * @param pc permission checker to check fs permission
   * @return the EZ with file status.
   */
  static Map.Entry<EncryptionZone, FileStatus> getEZForPath(
      final FSDirectory fsd, final String srcArg, final FSPermissionChecker pc)
      throws IOException {
    final INodesInPath iip;
    final EncryptionZone ret;
    fsd.readLock();
    try {
      iip = fsd.resolvePath(pc, srcArg, DirOp.READ);
      if (fsd.isPermissionEnabled()) {
        fsd.checkPathAccess(pc, iip, FsAction.READ);
      }
      ret = fsd.ezManager.getEZINodeForPath(iip);
    } finally {
      fsd.readUnlock();
    }
    FileStatus auditStat = fsd.getAuditFileInfo(iip);
    return new AbstractMap.SimpleImmutableEntry<>(ret, auditStat);
  }

  static EncryptionZone getEZForPath(final FSDirectory fsd,
      final INodesInPath iip) throws IOException {
    fsd.readLock();
    try {
      return fsd.ezManager.getEZINodeForPath(iip);
    } finally {
      fsd.readUnlock();
    }
  }

  static BatchedListEntries<EncryptionZone> listEncryptionZones(
      final FSDirectory fsd, final long prevId) throws IOException {
    fsd.readLock();
    try {
      return fsd.ezManager.listEncryptionZones(prevId);
    } finally {
      fsd.readUnlock();
    }
  }

  static List<XAttr> reencryptEncryptionZone(final FSDirectory fsd,
      final INodesInPath iip, final String keyVersionName) throws IOException {
    assert keyVersionName != null;
    return fsd.ezManager.reencryptEncryptionZone(iip, keyVersionName);
  }

  static List<XAttr> cancelReencryptEncryptionZone(final FSDirectory fsd,
      final INodesInPath iip) throws IOException {
    return fsd.ezManager.cancelReencryptEncryptionZone(iip);
  }

  static BatchedListEntries<ZoneReencryptionStatus> listReencryptionStatus(
      final FSDirectory fsd, final long prevId)
      throws IOException {
    fsd.readLock();
    try {
      return fsd.ezManager.listReencryptionStatus(prevId);
    } finally {
      fsd.readUnlock();
    }
  }

  /**
   * Update re-encryption progress (submitted). Caller should
   * logSync after calling this, outside of the FSN lock.
   * <p>
   * The reencryption status is updated during SetXAttrs.
   */
  static XAttr updateReencryptionSubmitted(final FSDirectory fsd,
      final INodesInPath iip, final String ezKeyVersionName)
      throws IOException {
    assert fsd.hasWriteLock();
    Preconditions.checkNotNull(ezKeyVersionName, "ezKeyVersionName is null.");
    final ZoneEncryptionInfoProto zoneProto = getZoneEncryptionInfoProto(iip);
    Preconditions.checkNotNull(zoneProto, "ZoneEncryptionInfoProto is null.");

    final ReencryptionInfoProto newProto = PBHelperClient
        .convert(ezKeyVersionName, Time.now(), false, 0, 0, null, null);
    final ZoneEncryptionInfoProto newZoneProto = PBHelperClient
        .convert(PBHelperClient.convert(zoneProto.getSuite()),
            PBHelperClient.convert(zoneProto.getCryptoProtocolVersion()),
            zoneProto.getKeyName(), newProto);

    final XAttr xattr = XAttrHelper
        .buildXAttr(CRYPTO_XATTR_ENCRYPTION_ZONE, newZoneProto.toByteArray());
    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
    xattrs.add(xattr);
    FSDirXAttrOp.unprotectedSetXAttrs(fsd, iip, xattrs,
        EnumSet.of(XAttrSetFlag.REPLACE));
    return xattr;
  }

  /**
   * Update re-encryption progress (start, checkpoint). Caller should
   * logSync after calling this, outside of the FSN lock.
   * <p>
   * The reencryption status is updated during SetXAttrs.
   * Original reencryption status is passed in to get existing information
   * such as ezkeyVersionName and submissionTime.
   */
  static XAttr updateReencryptionProgress(final FSDirectory fsd,
      final INode zoneNode, final ZoneReencryptionStatus origStatus,
      final String lastFile, final long numReencrypted, final long numFailures)
      throws IOException {
    assert fsd.hasWriteLock();
    Preconditions.checkNotNull(zoneNode, "Zone node is null");
    INodesInPath iip = INodesInPath.fromINode(zoneNode);
    final ZoneEncryptionInfoProto zoneProto = getZoneEncryptionInfoProto(iip);
    Preconditions.checkNotNull(zoneProto, "ZoneEncryptionInfoProto is null.");
    Preconditions.checkNotNull(origStatus, "Null status for " + iip.getPath());

    final ReencryptionInfoProto newProto = PBHelperClient
        .convert(origStatus.getEzKeyVersionName(),
            origStatus.getSubmissionTime(), false,
            origStatus.getFilesReencrypted() + numReencrypted,
            origStatus.getNumReencryptionFailures() + numFailures, null,
            lastFile);

    final ZoneEncryptionInfoProto newZoneProto = PBHelperClient
        .convert(PBHelperClient.convert(zoneProto.getSuite()),
            PBHelperClient.convert(zoneProto.getCryptoProtocolVersion()),
            zoneProto.getKeyName(), newProto);

    final XAttr xattr = XAttrHelper
        .buildXAttr(CRYPTO_XATTR_ENCRYPTION_ZONE, newZoneProto.toByteArray());
    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
    xattrs.add(xattr);
    FSDirXAttrOp.unprotectedSetXAttrs(fsd, iip, xattrs,
        EnumSet.of(XAttrSetFlag.REPLACE));
    return xattr;
  }

  /**
   * Log re-encrypt complete (cancel, or 100% re-encrypt) to edits.
   * Caller should logSync after calling this, outside of the FSN lock.
   * <p>
   * Original reencryption status is passed in to get existing information,
   * this should include whether it is finished due to cancellation.
   * The reencryption status is updated during SetXAttrs for completion time.
   */
  static List<XAttr> updateReencryptionFinish(final FSDirectory fsd,
      final INodesInPath zoneIIP, final ZoneReencryptionStatus origStatus)
      throws IOException {
    assert origStatus != null;
    assert fsd.hasWriteLock();
    fsd.ezManager.getReencryptionStatus()
        .markZoneCompleted(zoneIIP.getLastINode().getId());
    final XAttr xattr =
        generateNewXAttrForReencryptionFinish(zoneIIP, origStatus);
    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
    xattrs.add(xattr);
    FSDirXAttrOp.unprotectedSetXAttrs(fsd, zoneIIP, xattrs,
        EnumSet.of(XAttrSetFlag.REPLACE));
    return xattrs;
  }

  static XAttr generateNewXAttrForReencryptionFinish(final INodesInPath iip,
      final ZoneReencryptionStatus status) throws IOException {
    final ZoneEncryptionInfoProto zoneProto = getZoneEncryptionInfoProto(iip);
    final ReencryptionInfoProto newRiProto = PBHelperClient
        .convert(status.getEzKeyVersionName(), status.getSubmissionTime(),
            status.isCanceled(), status.getFilesReencrypted(),
            status.getNumReencryptionFailures(), Time.now(), null);

    final ZoneEncryptionInfoProto newZoneProto = PBHelperClient
        .convert(PBHelperClient.convert(zoneProto.getSuite()),
            PBHelperClient.convert(zoneProto.getCryptoProtocolVersion()),
            zoneProto.getKeyName(), newRiProto);

    final XAttr xattr = XAttrHelper
        .buildXAttr(CRYPTO_XATTR_ENCRYPTION_ZONE, newZoneProto.toByteArray());
    return xattr;
  }

  private static ZoneEncryptionInfoProto getZoneEncryptionInfoProto(
      final INodesInPath iip) throws IOException {
    final XAttr fileXAttr = FSDirXAttrOp.unprotectedGetXAttrByPrefixedName(
        iip.getLastINode(), iip.getPathSnapshotId(),
        CRYPTO_XATTR_ENCRYPTION_ZONE);
    if (fileXAttr == null) {
      throw new IOException(
          "Could not find reencryption XAttr for file " + iip.getPath());
    }
    try {
      return ZoneEncryptionInfoProto.parseFrom(fileXAttr.getValue());
    } catch (InvalidProtocolBufferException e) {
      throw new IOException(
          "Could not parse file encryption info for " + "inode " + iip
              .getPath(), e);
    }
  }

  /**
   * Save the batch's edeks to file xattrs.
   */
  static void saveFileXAttrsForBatch(FSDirectory fsd,
      List<FileEdekInfo> batch) {
    assert fsd.getFSNamesystem().hasWriteLock();
    if (batch != null && !batch.isEmpty()) {
      for (FileEdekInfo entry : batch) {
        final INode inode = fsd.getInode(entry.getInodeId());
        // no dir lock, so inode could be removed. no-op if so.
        if (inode == null) {
          NameNode.LOG.info("Cannot find inode {}, skip saving xattr for"
              + " re-encryption", entry.getInodeId());
          continue;
        }
        fsd.getEditLog().logSetXAttrs(inode.getFullPathName(),
            inode.getXAttrFeature().getXAttrs(), false);
      }
    }
  }

  /**
   * Set the FileEncryptionInfo for an INode.
   *
   * @param fsd the namespace tree.
   * @param info file encryption information
   * @param flag action when setting xattr. Either CREATE or REPLACE.
   * @throws IOException
   */
  static void setFileEncryptionInfo(final FSDirectory fsd,
      final INodesInPath iip, final FileEncryptionInfo info,
      final XAttrSetFlag flag) throws IOException {
    // Make the PB for the xattr
    final HdfsProtos.PerFileEncryptionInfoProto proto =
        PBHelperClient.convertPerFileEncInfo(info);
    final byte[] protoBytes = proto.toByteArray();
    final XAttr fileEncryptionAttr =
        XAttrHelper.buildXAttr(CRYPTO_XATTR_FILE_ENCRYPTION_INFO, protoBytes);
    final List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
    xAttrs.add(fileEncryptionAttr);
    fsd.writeLock();
    try {
      FSDirXAttrOp.unprotectedSetXAttrs(fsd, iip, xAttrs, EnumSet.of(flag));
    } finally {
      fsd.writeUnlock();
    }
  }

  /**
   * This function combines the per-file encryption info (obtained
   * from the inode's XAttrs), and the encryption info from its zone, and
   * returns a consolidated FileEncryptionInfo instance. Null is returned
   * for non-encrypted or raw files.
   *
   * @param fsd the namespace tree.
   * @param iip inodes in the path containing the file, passed in to
   *            avoid obtaining the list of inodes again
   * @return consolidated file encryption info; null for non-encrypted files
   */
  static FileEncryptionInfo getFileEncryptionInfo(final FSDirectory fsd,
      final INodesInPath iip) throws IOException {
    if (iip.isRaw() ||
        !fsd.ezManager.hasCreatedEncryptionZone() ||
        !iip.getLastINode().isFile()) {
      return null;
    }
    fsd.readLock();
    try {
      EncryptionZone encryptionZone = getEZForPath(fsd, iip);
      if (encryptionZone == null) {
        // not an encrypted file
        return null;
      } else if(encryptionZone.getPath() == null
          || encryptionZone.getPath().isEmpty()) {
        if (NameNode.LOG.isDebugEnabled()) {
          NameNode.LOG.debug("Encryption zone " +
              encryptionZone.getPath() + " does not have a valid path.");
        }
      }

      XAttr fileXAttr = FSDirXAttrOp.unprotectedGetXAttrByPrefixedName(
          iip.getLastINode(), iip.getPathSnapshotId(),
          CRYPTO_XATTR_FILE_ENCRYPTION_INFO);
      if (fileXAttr == null) {
        NameNode.LOG.warn("Could not find encryption XAttr for file " +
            iip.getPath() + " in encryption zone " + encryptionZone.getPath());
        return null;
      }

      final CryptoProtocolVersion version = encryptionZone.getVersion();
      final CipherSuite suite = encryptionZone.getSuite();
      final String keyName = encryptionZone.getKeyName();
      try {
        HdfsProtos.PerFileEncryptionInfoProto fileProto =
            HdfsProtos.PerFileEncryptionInfoProto.parseFrom(
                fileXAttr.getValue());
        return PBHelperClient.convert(fileProto, suite, version, keyName);
      } catch (InvalidProtocolBufferException e) {
        throw new IOException("Could not parse file encryption info for " +
            "inode " + iip.getPath(), e);
      }
    } finally {
      fsd.readUnlock();
    }
  }

  /**
   * If the file and encryption key are valid, return the encryption info,
   * else throw a retry exception.  The startFile method generates the EDEK
   * outside of the lock so the zone must be reverified.
   *
   * @param dir the namespace tree.
   * @param iip inodes in the file path
   * @param ezInfo the encryption key
   * @return FileEncryptionInfo for the file
   * @throws RetryStartFileException if key is inconsistent with current zone
   */
  static FileEncryptionInfo getFileEncryptionInfo(FSDirectory dir,
      INodesInPath iip, EncryptionKeyInfo ezInfo)
          throws RetryStartFileException, IOException {
    FileEncryptionInfo feInfo = null;
    final EncryptionZone zone = getEZForPath(dir, iip);
    if (zone != null) {
      // The path is now within an EZ, but we're missing encryption parameters
      if (ezInfo == null) {
        throw new RetryStartFileException();
      }
      // Path is within an EZ and we have provided encryption parameters.
      // Make sure that the generated EDEK matches the settings of the EZ.
      final String ezKeyName = zone.getKeyName();
      if (!ezKeyName.equals(ezInfo.edek.getEncryptionKeyName())) {
        throw new RetryStartFileException();
      }
      feInfo = new FileEncryptionInfo(ezInfo.suite, ezInfo.protocolVersion,
          ezInfo.edek.getEncryptedKeyVersion().getMaterial(),
          ezInfo.edek.getEncryptedKeyIv(),
          ezKeyName, ezInfo.edek.getEncryptionKeyVersionName());
    }
    return feInfo;
  }

  static boolean isInAnEZ(final FSDirectory fsd, final INodesInPath iip)
      throws UnresolvedLinkException, SnapshotAccessControlException,
      IOException {
    if (!fsd.ezManager.hasCreatedEncryptionZone()) {
      return false;
    }
    fsd.readLock();
    try {
      return fsd.ezManager.isInAnEZ(iip);
    } finally {
      fsd.readUnlock();
    }
  }

  /**
   * Proactively warm up the edek cache. We'll get all the edek key names,
   * then launch up a separate thread to warm them up.
   */
  static void warmUpEdekCache(final ExecutorService executor,
      final FSDirectory fsd, final int delay, final int interval) {
    fsd.readLock();
    try {
      String[] edeks  = fsd.ezManager.getKeyNames();
      executor.execute(
          new EDEKCacheLoader(edeks, fsd.getProvider(), delay, interval));
    } finally {
      fsd.readUnlock();
    }
  }

  /**
   * EDEKCacheLoader is being run in a separate thread to loop through all the
   * EDEKs and warm them up in the KMS cache.
   */
  static class EDEKCacheLoader implements Runnable {
    private final String[] keyNames;
    private final KeyProviderCryptoExtension kp;
    private int initialDelay;
    private int retryInterval;

    EDEKCacheLoader(final String[] names, final KeyProviderCryptoExtension kp,
        final int delay, final int interval) {
      this.keyNames = names;
      this.kp = kp;
      this.initialDelay = delay;
      this.retryInterval = interval;
    }

    @Override
    public void run() {
      NameNode.LOG.info("Warming up {} EDEKs... (initialDelay={}, "
          + "retryInterval={})", keyNames.length, initialDelay, retryInterval);
      try {
        Thread.sleep(initialDelay);
      } catch (InterruptedException ie) {
        NameNode.LOG.info("EDEKCacheLoader interrupted before warming up.");
        return;
      }

      final int logCoolDown = 10000; // periodically print error log (if any)
      int sinceLastLog = logCoolDown; // always print the first failure
      boolean success = false;
      IOException lastSeenIOE = null;
      long warmUpEDEKStartTime = monotonicNow();
      while (true) {
        try {
          kp.warmUpEncryptedKeys(keyNames);
          NameNode.LOG
              .info("Successfully warmed up {} EDEKs.", keyNames.length);
          success = true;
          break;
        } catch (IOException ioe) {
          lastSeenIOE = ioe;
          if (sinceLastLog >= logCoolDown) {
            NameNode.LOG.info("Failed to warm up EDEKs.", ioe);
            sinceLastLog = 0;
          } else {
            NameNode.LOG.debug("Failed to warm up EDEKs.", ioe);
          }
        } catch (Exception e) {
          NameNode.LOG.error("Cannot warm up EDEKs.", e);
          throw e;
        }
        try {
          Thread.sleep(retryInterval);
        } catch (InterruptedException ie) {
          NameNode.LOG.info("EDEKCacheLoader interrupted during retry.");
          break;
        }
        sinceLastLog += retryInterval;
      }
      long warmUpEDEKTime = monotonicNow() - warmUpEDEKStartTime;
      NameNode.getNameNodeMetrics().addWarmUpEDEKTime(warmUpEDEKTime);
      if (!success) {
        NameNode.LOG.warn("Unable to warm up EDEKs.");
        if (lastSeenIOE != null) {
          NameNode.LOG.warn("Last seen exception:", lastSeenIOE);
        }
      }
    }
  }

  /**
   * If the file is in an encryption zone, we optimistically create an
   * EDEK for the file by calling out to the configured KeyProvider.
   * Since this typically involves doing an RPC, the fsn lock is yielded.
   *
   * Since the path can flip-flop between being in an encryption zone and not
   * in the meantime, the call MUST re-resolve the IIP and re-check
   * preconditions if this method does not return null;
   *
   * @param fsn the namesystem.
   * @param iip the inodes for the path
   * @param supportedVersions client's supported versions
   * @return EncryptionKeyInfo if the path is in an EZ, else null
   */
  static EncryptionKeyInfo getEncryptionKeyInfo(FSNamesystem fsn,
      INodesInPath iip, CryptoProtocolVersion[] supportedVersions)
      throws IOException {
    FSDirectory fsd = fsn.getFSDirectory();
    // Nothing to do if the path is not within an EZ
    final EncryptionZone zone = getEZForPath(fsd, iip);
    if (zone == null) {
      EncryptionFaultInjector.getInstance().startFileNoKey();
      return null;
    }
    CryptoProtocolVersion protocolVersion = fsn.chooseProtocolVersion(
        zone, supportedVersions);
    CipherSuite suite = zone.getSuite();
    String ezKeyName = zone.getKeyName();

    Preconditions.checkNotNull(protocolVersion);
    Preconditions.checkNotNull(suite);
    Preconditions.checkArgument(!suite.equals(CipherSuite.UNKNOWN),
                                "Chose an UNKNOWN CipherSuite!");
    Preconditions.checkNotNull(ezKeyName);

    // Generate EDEK while not holding the fsn lock.
    fsn.writeUnlock();
    try {
      EncryptionFaultInjector.getInstance().startFileBeforeGenerateKey();
      return new EncryptionKeyInfo(protocolVersion, suite, ezKeyName,
          generateEncryptedDataEncryptionKey(fsd, ezKeyName));
    } finally {
      fsn.writeLock();
      EncryptionFaultInjector.getInstance().startFileAfterGenerateKey();
    }
  }

  static class EncryptionKeyInfo {
    final CryptoProtocolVersion protocolVersion;
    final CipherSuite suite;
    final String ezKeyName;
    final KeyProviderCryptoExtension.EncryptedKeyVersion edek;

    EncryptionKeyInfo(
        CryptoProtocolVersion protocolVersion, CipherSuite suite,
        String ezKeyName, KeyProviderCryptoExtension.EncryptedKeyVersion edek) {
      this.protocolVersion = protocolVersion;
      this.suite = suite;
      this.ezKeyName = ezKeyName;
      this.edek = edek;
    }
  }

  /**
   * Get the current key version name for the given EZ. This will first drain
   * the provider's local cache, then generate a new edek.
   * <p>
   * The encryption key version of the newly generated edek will be used as
   * the target key version of this re-encryption - meaning all edeks'
   * keyVersion are compared with it, and only sent to the KMS for re-encryption
   * when the version is different.
   * <p>
   * Note: KeyProvider has a getCurrentKey interface, but that is under
   * a different ACL. HDFS should not try to operate on additional ACLs, but
   * rather use the generate ACL it already has.
   */
  static String getCurrentKeyVersion(final FSDirectory dir,
      final FSPermissionChecker pc, final String zone) throws IOException {
    assert dir.getProvider() != null;
    assert !dir.hasReadLock();
    final String keyName = FSDirEncryptionZoneOp.getKeyNameForZone(dir,
        pc, zone);
    if (keyName == null) {
      throw new IOException(zone + " is not an encryption zone.");
    }
    // drain the local cache of the key provider.
    // Do not invalidateCache on the server, since that's the responsibility
    // when rolling the key version.
    dir.getProvider().drain(keyName);
    final EncryptedKeyVersion edek;
    try {
      edek = dir.getProvider().generateEncryptedKey(keyName);
    } catch (GeneralSecurityException gse) {
      throw new IOException(gse);
    }
    Preconditions.checkNotNull(edek);
    return edek.getEncryptionKeyVersionName();
  }

  /**
   * Resolve the zone to an inode, find the encryption zone info associated with
   * that inode, and return the key name. Does not contact the KMS.
   */
  static String getKeyNameForZone(final FSDirectory dir,
      final FSPermissionChecker pc, final String zone) throws IOException {
    assert dir.getProvider() != null;
    final INodesInPath iip;
    dir.getFSNamesystem().readLock();
    try {
      iip = dir.resolvePath(pc, zone, DirOp.READ);
      dir.ezManager.checkEncryptionZoneRoot(iip.getLastINode(), zone);
      return dir.ezManager.getKeyName(iip);
    } finally {
      dir.getFSNamesystem().readUnlock();
    }
  }
}
