@Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   if (allocInfo.getRequest().getKeyName() == null
       || "".equals(allocInfo.getRequest().getKeyName())) {
     if (ImageMetadata.Platform.windows.equals(
         allocInfo.getBootSet().getMachine().getPlatform())) {
       throw new InvalidMetadataException(
           "You must specify a keypair when running a windows vm: "
               + allocInfo.getRequest().getImageId());
     } else {
       allocInfo.setSshKeyPair(KeyPairs.noKey());
       return true;
     }
   }
   Context ctx = allocInfo.getContext();
   RunInstancesType request = allocInfo.getRequest();
   String keyName = request.getKeyName();
   SshKeyPair key = KeyPairs.lookup(ctx.getUserFullName().asAccountFullName(), keyName);
   if (!ctx.hasAdministrativePrivileges() && !RestrictedTypes.filterPrivileged().apply(key)) {
     throw new IllegalMetadataAccessException(
         "Not authorized to use keypair " + keyName + " by " + ctx.getUser().getName());
   }
   allocInfo.setSshKeyPair(key);
   return true;
 }
    @Override
    public boolean apply(Allocation allocInfo) throws MetadataException {
      Context ctx = allocInfo.getContext();
      NetworkGroups.lookup(
          ctx.getUserFullName().asAccountFullName(), NetworkGroups.defaultNetworkName());

      Set<String> networkNames = Sets.newHashSet(allocInfo.getRequest().getGroupSet());
      if (networkNames.isEmpty()) {
        networkNames.add(NetworkGroups.defaultNetworkName());
      }

      Map<String, NetworkGroup> networkRuleGroups = Maps.newHashMap();
      for (String groupName : networkNames) {
        NetworkGroup group =
            NetworkGroups.lookup(ctx.getUserFullName().asAccountFullName(), groupName);
        if (!ctx.hasAdministrativePrivileges()
            && !RestrictedTypes.filterPrivileged().apply(group)) {
          throw new IllegalMetadataAccessException(
              "Not authorized to use network group "
                  + groupName
                  + " for "
                  + ctx.getUser().getName());
        }
        networkRuleGroups.put(groupName, group);
      }
      Set<String> missingNets = Sets.difference(networkNames, networkRuleGroups.keySet());
      if (!missingNets.isEmpty()) {
        throw new NoSuchMetadataException("Failed to find security group info for: " + missingNets);
      } else {
        allocInfo.setNetworkRules(networkRuleGroups);
      }
      return true;
    }
 @Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   if (allocInfo.getRequest().getKeyName() == null
       || "".equals(allocInfo.getRequest().getKeyName())) {
     allocInfo.setSshKeyPair(KeyPairs.noKey());
     return true;
   }
   UserFullName ownerFullName = allocInfo.getOwnerFullName();
   RunInstancesType request = allocInfo.getRequest();
   String keyName = request.getKeyName();
   SshKeyPair key = KeyPairs.lookup(ownerFullName.asAccountFullName(), keyName);
   if (!RestrictedTypes.filterPrivileged().apply(key)) {
     throw new IllegalMetadataAccessException(
         "Not authorized to use keypair " + keyName + " by " + ownerFullName.getUserName());
   }
   allocInfo.setSshKeyPair(key);
   return true;
 }
    @Override
    public boolean apply(Allocation allocInfo)
        throws MetadataException, AuthException, VerificationException {
      RunInstancesType msg = allocInfo.getRequest();
      String imageId = msg.getImageId();
      VmType vmType = allocInfo.getVmType();
      try {
        BootableSet bootSet = Emis.newBootableSet(imageId);
        allocInfo.setBootableSet(bootSet);

        // Add (1024L * 1024L * 10) to handle NTFS min requirements.
        if (!bootSet.isBlockStorage()) {
          if (Platform.windows.equals(bootSet.getMachine().getPlatform())
              && bootSet.getMachine().getImageSizeBytes()
                  > ((1024L * 1024L * 1024L * vmType.getDisk()) + (1024L * 1024L * 10))) {
            throw new ImageInstanceTypeVerificationException(
                "Unable to run instance "
                    + bootSet.getMachine().getDisplayName()
                    + " in which the size "
                    + bootSet.getMachine().getImageSizeBytes()
                    + " bytes of the instance is greater than the vmType "
                    + vmType.getDisplayName()
                    + " size "
                    + vmType.getDisk()
                    + " GB.");
          } else if (bootSet.getMachine().getImageSizeBytes()
              > ((1024L * 1024L * 1024L * vmType.getDisk()))) {
            throw new ImageInstanceTypeVerificationException(
                "Unable to run instance "
                    + bootSet.getMachine().getDisplayName()
                    + " in which the size "
                    + bootSet.getMachine().getImageSizeBytes()
                    + " bytes of the instance is greater than the vmType "
                    + vmType.getDisplayName()
                    + " size "
                    + vmType.getDisk()
                    + " GB.");
          }
        }
      } catch (VerificationException e) {
        throw e;
      } catch (MetadataException ex) {
        LOG.error(ex);
        throw ex;
      } catch (RuntimeException ex) {
        LOG.error(ex);
        throw new VerificationException(
            "Failed to verify references for request: "
                + msg.toSimpleString()
                + " because of: "
                + ex.getMessage(),
            ex);
      }
      return true;
    }
 @Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   Context ctx = allocInfo.getContext();
   User user = ctx.getUser();
   String instanceType = allocInfo.getRequest().getInstanceType();
   VmType vmType = VmTypes.lookup(instanceType);
   if (!ctx.hasAdministrativePrivileges() && !RestrictedTypes.filterPrivileged().apply(vmType)) {
     throw new IllegalMetadataAccessException(
         "Not authorized to allocate vm type " + instanceType + " for " + ctx.getUserFullName());
   }
   allocInfo.setVmType(vmType);
   return true;
 }
 @Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   String instanceType = allocInfo.getRequest().getInstanceType();
   VmType vmType = VmTypes.lookup(instanceType);
   if (!RestrictedTypes.filterPrivileged().apply(vmType)) {
     throw new IllegalMetadataAccessException(
         "Not authorized to allocate vm type "
             + instanceType
             + " for "
             + allocInfo.getOwnerFullName());
   }
   allocInfo.setVmType(vmType);
   return true;
 }
 @Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   RunInstancesType request = allocInfo.getRequest();
   String zoneName = request.getAvailabilityZone();
   if (Clusters.getInstance().listValues().isEmpty()) {
     LOG.debug("enabled values: " + Joiner.on("\n").join(Clusters.getInstance().listValues()));
     LOG.debug("disabled values: " + Joiner.on("\n").join(Clusters.getInstance().listValues()));
     throw new VerificationException(
         "Not enough resources: no cluster controller is currently available to run instances.");
   } else if (Partitions.exists(zoneName)) {
     Partition partition = Partitions.lookupByName(zoneName);
     allocInfo.setPartition(partition);
   } else if (Partition.DEFAULT_NAME.equals(zoneName)) {
     Partition partition = Partition.DEFAULT;
     allocInfo.setPartition(partition);
   } else {
     throw new VerificationException(
         "Not enough resources: no cluster controller is currently available to run instances.");
   }
   return true;
 }
    @Override
    public boolean apply(Allocation allocInfo) throws MetadataException {

      BootableImageInfo imageInfo = allocInfo.getBootSet().getMachine();
      final ArrayList<BlockDeviceMappingItemType> instanceMappings =
          allocInfo.getRequest().getBlockDeviceMapping() != null
              ? allocInfo.getRequest().getBlockDeviceMapping()
              : new ArrayList<BlockDeviceMappingItemType>();
      List<DeviceMapping> imageMappings =
          new ArrayList<DeviceMapping>(((ImageInfo) imageInfo).getDeviceMappings());

      // Figure out the final set of mappings for this instance and add it to the request before
      // verifying the mappings.

      //    for ( DeviceMapping imageMapping : imageMappings ) {
      //  	if( !Iterables.any( instanceMappings, Images.findBlockDeviceMappingItempType(
      // imageMapping.getDeviceName() ) ) ) {
      //  	  instanceMappings.add(Images.DeviceMappingDetails.INSTANCE.apply(imageMapping));
      //  	}
      //    }

      // Is this an overkill?? Should I rather go with the above logic. Damn complexity seems
      // same...
      // probably m * n where m is the number of image mappings and n is the number of instance
      // mappings
      instanceMappings.addAll(
          Lists.transform(
              Lists.newArrayList(
                  Iterables.filter(
                      imageMappings,
                      new Predicate<DeviceMapping>() {
                        @Override
                        public boolean apply(DeviceMapping arg0) {
                          return !Iterables.any(
                              instanceMappings,
                              Images.findBlockDeviceMappingItempType(arg0.getDeviceName()));
                        }
                      })),
              Images.DeviceMappingDetails.INSTANCE));

      if (imageInfo instanceof BlockStorageImageInfo) { // bfebs image

        if (!instanceMappings.isEmpty()) {

          // Verify all block device mappings. Dont fuss if both snapshot id and volume size are
          // left blank
          Images.isDeviceMappingListValid(instanceMappings, Boolean.TRUE, Boolean.TRUE);

          BlockStorageImageInfo bfebsImage = (BlockStorageImageInfo) imageInfo;
          Integer imageSizeGB = (int) (bfebsImage.getImageSizeBytes() / BYTES_PER_GB);
          Integer userRequestedSizeGB = null;

          // Find the root block device mapping in the run instance request. Validate it
          BlockDeviceMappingItemType rootBlockDevice =
              Iterables.find(
                  instanceMappings,
                  Images.findEbsRootOptionalSnapshot(bfebsImage.getRootDeviceName()),
                  null);
          if (rootBlockDevice != null) {
            // Ensure that root device is not mapped to a different snapshot, logical device or
            // suppressed.
            // Verify that the root device size is not smaller than the image size
            if (StringUtils.isNotBlank(rootBlockDevice.getEbs().getSnapshotId())
                && !StringUtils.equals(
                    rootBlockDevice.getEbs().getSnapshotId(), bfebsImage.getSnapshotId())) {
              throw new InvalidMetadataException(
                  "Snapshot ID cannot be modified for the root device. "
                      + "Source snapshot from the image registration will be used for creating the root device");
            } else if (StringUtils.isNotBlank(rootBlockDevice.getVirtualName())) {
              throw new InvalidMetadataException(
                  "Logical type cannot be modified for the root device. "
                      + "Source snapshot from the image registration will be used for creating the root device");
            } else if (rootBlockDevice.getNoDevice() != null && rootBlockDevice.getNoDevice()) {
              throw new InvalidMetadataException(
                  "Root device cannot be suppressed. "
                      + "Source snapshot from the image registration will be used for creating the root device");
            } else if ((userRequestedSizeGB = rootBlockDevice.getEbs().getVolumeSize()) != null
                && userRequestedSizeGB < imageSizeGB) {
              throw new InvalidMetadataException(
                  "Root device volume cannot be smaller than the image size");
            }

            // Gather all the information for the root device mapping and populate it in the run
            // instance request
            if (rootBlockDevice.getEbs().getSnapshotId() == null) {
              rootBlockDevice.getEbs().setSnapshotId(bfebsImage.getSnapshotId());
            }
            if (rootBlockDevice.getEbs().getVolumeSize() == null) {
              rootBlockDevice.getEbs().setVolumeSize(imageSizeGB);
            }
            if (rootBlockDevice.getEbs().getDeleteOnTermination() == null) {
              rootBlockDevice.getEbs().setDeleteOnTermination(bfebsImage.getDeleteOnTerminate());
            }
          } else {
            // This should never happen. Root device mapping will always exist in the block storage
            // image and or run instance request
            throw new InvalidMetadataException("Root block device mapping not found\n");
          }
        }
      } else { // Instance store image
        // Verify all block device mappings. EBS mappings must be considered invalid since AWS
        // doesn't support it
        Images.isDeviceMappingListValid(instanceMappings, Boolean.TRUE, Boolean.FALSE);
      }

      // Set the final list of block device mappings in the run instance request (necessary if the
      // instance mappings were null). Checked with grze that its okay
      allocInfo.getRequest().setBlockDeviceMapping(instanceMappings);
      return true;
    }
    @Override
    public boolean apply(final Allocation allocInfo) throws MetadataException {
      final UserFullName ownerFullName = allocInfo.getOwnerFullName();
      final String instanceProfileArn = allocInfo.getRequest().getIamInstanceProfileArn();
      final String instanceProfileName = allocInfo.getRequest().getIamInstanceProfileName();
      if (!Strings.isNullOrEmpty(instanceProfileArn)
          || !Strings.isNullOrEmpty(instanceProfileName)) {

        final String profileAccount;
        final String profileName;
        if (!Strings.isNullOrEmpty(instanceProfileArn))
          try {
            final Ern name = Ern.parse(instanceProfileArn);
            if (!(name instanceof EuareResourceName)) {
              throw new InvalidInstanceProfileMetadataException(
                  "Invalid IAM instance profile ARN: " + instanceProfileArn);
            }
            profileAccount = name.getAccount();
            profileName = ((EuareResourceName) name).getName();

          } catch (JSONException e) {
            throw new InvalidInstanceProfileMetadataException(
                "Invalid IAM instance profile ARN: " + instanceProfileArn, e);
          }
        else {
          profileAccount = ownerFullName.getAccountNumber();
          profileName = instanceProfileName;
        }

        final InstanceProfile profile;
        try {
          profile = Accounts.lookupInstanceProfileByName(profileAccount, profileName);
        } catch (AuthException e) {
          throw new InvalidInstanceProfileMetadataException(
              "Invalid IAM instance profile: " + profileAccount + "/" + profileName, e);
        }

        if (!Strings.isNullOrEmpty(instanceProfileName)
            && !instanceProfileName.equals(profile.getName())) {
          throw new InvalidInstanceProfileMetadataException(
              String.format(
                  "Invalid IAM instance profile name '%s' for ARN: %s",
                  profileName, instanceProfileArn));
        }

        try {
          final AuthContextSupplier user = allocInfo.getAuthContext();
          if (!Permissions.isAuthorized(
              PolicySpec.VENDOR_IAM,
              PolicySpec.IAM_RESOURCE_INSTANCE_PROFILE,
              Accounts.getInstanceProfileFullName(profile),
              AccountFullName.getInstance(profile.getAccountNumber()),
              PolicySpec.IAM_LISTINSTANCEPROFILES,
              user)) {
            throw new IllegalMetadataAccessException(
                String.format(
                    "Not authorized to access instance profile with ARN %s for %s",
                    profile.getInstanceProfileArn(), ownerFullName));
          }

          final Role role = profile.getRole();
          if (role != null
              && !Permissions.isAuthorized(
                  PolicySpec.VENDOR_IAM,
                  PolicySpec.IAM_RESOURCE_ROLE,
                  Accounts.getRoleFullName(role),
                  AccountFullName.getInstance(role.getAccountNumber()),
                  PolicySpec.IAM_PASSROLE,
                  user)) {
            throw new IllegalMetadataAccessException(
                String.format(
                    "Not authorized to pass role with ARN %s for %s",
                    role.getRoleArn(), ownerFullName));
          }

          if (role != null) {
            allocInfo.setInstanceProfileArn(profile.getInstanceProfileArn());
            allocInfo.setIamInstanceProfileId(profile.getInstanceProfileId());
            allocInfo.setIamRoleArn(role.getRoleArn());
          } else {
            throw new InvalidInstanceProfileMetadataException(
                "Role not found for IAM instance profile ARN: " + profile.getInstanceProfileArn());
          }
        } catch (AuthException e) {
          throw new MetadataException("IAM instance profile error", e);
        }
      }
      return true;
    }