/************************************************************************* * Copyright 2009-2016 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.compute.service; import static com.eucalyptus.util.RestrictedTypes.getIamActionByMessageType; import static com.eucalyptus.util.Strings.append; import static com.eucalyptus.util.Strings.prepend; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.inject.Inject; import javax.persistence.EntityNotFoundException; import org.apache.log4j.Logger; import org.bouncycastle.util.encoders.Base64; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Restrictions; import com.eucalyptus.auth.Accounts; import com.eucalyptus.auth.AuthContextSupplier; import com.eucalyptus.auth.AuthException; import com.eucalyptus.auth.AuthQuotaException; import com.eucalyptus.auth.Permissions; import com.eucalyptus.auth.policy.PolicySpec; import com.eucalyptus.auth.principal.AccountFullName; import com.eucalyptus.auth.principal.User; import com.eucalyptus.auth.principal.UserPrincipal; import com.eucalyptus.auth.type.RestrictedType; import com.eucalyptus.binding.Binding; import com.eucalyptus.binding.BindingException; import com.eucalyptus.binding.BindingManager; import com.eucalyptus.component.Topology; import com.eucalyptus.component.annotation.ComponentNamed; import com.eucalyptus.component.id.Eucalyptus; import com.eucalyptus.compute.common.*; import com.eucalyptus.compute.common.internal.account.IdentityIdFormat; import com.eucalyptus.compute.common.internal.account.IdentityIdFormat.IdResource; import com.eucalyptus.compute.common.internal.account.IdentityIdFormat.IdType; import com.eucalyptus.compute.common.internal.account.IdentityIdFormats; import com.eucalyptus.compute.common.internal.address.AddressI; import com.eucalyptus.compute.common.internal.address.AllocatedAddressEntity; import com.eucalyptus.compute.common.internal.blockstorage.Snapshot; import com.eucalyptus.compute.common.internal.blockstorage.Snapshots; import com.eucalyptus.compute.common.internal.blockstorage.State; import com.eucalyptus.compute.common.internal.blockstorage.Volume; import com.eucalyptus.compute.common.internal.identifier.InvalidResourceIdentifier; import com.eucalyptus.compute.common.internal.identifier.ResourceIdentifiers; import com.eucalyptus.compute.common.internal.images.BlockStorageDeviceMapping; import com.eucalyptus.compute.common.internal.images.BlockStorageImageInfo; import com.eucalyptus.compute.common.internal.images.DeviceMapping; import com.eucalyptus.compute.common.internal.images.ImageInfo; import com.eucalyptus.compute.common.internal.images.Images; import com.eucalyptus.compute.common.internal.images.MachineImageInfo; import com.eucalyptus.compute.common.internal.keys.KeyPairs; import com.eucalyptus.compute.common.internal.keys.SshKeyPair; import com.eucalyptus.compute.common.internal.network.NetworkGroup; import com.eucalyptus.compute.common.internal.network.NetworkGroups; import com.eucalyptus.compute.common.internal.tags.Filter; import com.eucalyptus.compute.common.internal.tags.Filters; import com.eucalyptus.compute.common.internal.tags.InvalidFilterException; import com.eucalyptus.compute.common.internal.tags.Tag; import com.eucalyptus.compute.common.internal.tags.TagSupport; import com.eucalyptus.compute.common.internal.tags.Tags; import com.eucalyptus.compute.common.internal.util.MetadataException; import com.eucalyptus.compute.common.internal.vm.NetworkGroupId; import com.eucalyptus.compute.common.internal.vm.VmBootVolumeAttachment; import com.eucalyptus.compute.common.internal.vm.VmInstance; import com.eucalyptus.compute.common.internal.vm.VmInstances; import com.eucalyptus.compute.common.internal.vm.VmStandardVolumeAttachment; import com.eucalyptus.compute.common.internal.vm.VmVolumeAttachment; import com.eucalyptus.compute.common.internal.vpc.NatGateway; import com.eucalyptus.compute.common.internal.vpc.NatGateways; import com.eucalyptus.compute.common.network.Networking; import com.eucalyptus.compute.common.network.NetworkingFeature; import com.eucalyptus.compute.common.internal.vpc.DhcpOptionSet; import com.eucalyptus.compute.common.internal.vpc.DhcpOptionSets; import com.eucalyptus.compute.common.internal.vpc.InternetGateway; import com.eucalyptus.compute.common.internal.vpc.InternetGateways; import com.eucalyptus.compute.common.internal.vpc.Lister; import com.eucalyptus.compute.common.internal.vpc.NetworkAcl; import com.eucalyptus.compute.common.internal.vpc.NetworkAcls; import com.eucalyptus.compute.common.internal.vpc.NetworkInterface; import com.eucalyptus.compute.common.internal.vpc.NetworkInterfaces; import com.eucalyptus.compute.common.internal.vpc.RouteTable; import com.eucalyptus.compute.common.internal.vpc.RouteTables; import com.eucalyptus.compute.common.internal.vpc.Subnet; import com.eucalyptus.compute.common.internal.vpc.Subnets; import com.eucalyptus.compute.common.internal.vpc.Vpc; import com.eucalyptus.compute.common.internal.vpc.VpcMetadataNotFoundException; import com.eucalyptus.compute.common.internal.vpc.Vpcs; import com.eucalyptus.context.Context; import com.eucalyptus.context.Contexts; import com.eucalyptus.entities.AbstractPersistent; import com.eucalyptus.entities.Entities; import com.eucalyptus.entities.TransactionException; import com.eucalyptus.entities.TransactionResource; import com.eucalyptus.entities.Transactions; import com.eucalyptus.util.Callback; import com.eucalyptus.util.CollectionUtils; import com.eucalyptus.util.EucalyptusCloudException; import com.eucalyptus.util.Exceptions; import com.eucalyptus.auth.principal.OwnerFullName; import com.eucalyptus.util.FUtils; import com.eucalyptus.util.Pair; import com.eucalyptus.util.RestrictedTypes; import com.eucalyptus.util.TypeMappers; import com.eucalyptus.util.async.AsyncExceptions; import com.eucalyptus.util.async.AsyncExceptions.AsyncWebServiceError; import com.eucalyptus.util.async.AsyncRequests; import com.eucalyptus.util.async.Callbacks; import com.eucalyptus.util.async.FailedRequestException; import com.eucalyptus.ws.EucalyptusWebServiceException; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Strings; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Ordering; import com.google.common.collect.Sets; import com.google.common.collect.TreeMultimap; import edu.ucsb.eucalyptus.msgs.BaseMessage; import edu.ucsb.eucalyptus.msgs.BaseMessages; import javaslang.control.Option; /** * */ @SuppressWarnings( { "UnusedDeclaration", "Guava", "StaticPseudoFunctionalStyleMethod" } ) @ComponentNamed public class ComputeService { private static Logger LOG = Logger.getLogger( ComputeService.class ); private final DhcpOptionSets dhcpOptionSets; private final InternetGateways internetGateways; private final NatGateways natGateways; private final NetworkAcls networkAcls; private final NetworkInterfaces networkInterfaces; private final RouteTables routeTables; private final Subnets subnets; private final Vpcs vpcs; @Inject public ComputeService( final DhcpOptionSets dhcpOptionSets, final InternetGateways internetGateways, final NatGateways natGateways, final NetworkAcls networkAcls, final NetworkInterfaces networkInterfaces, final RouteTables routeTables, final Subnets subnets, final Vpcs vpcs ) { this.dhcpOptionSets = dhcpOptionSets; this.internetGateways = internetGateways; this.natGateways = natGateways; this.networkAcls = networkAcls; this.networkInterfaces = networkInterfaces; this.routeTables = routeTables; this.subnets = subnets; this.vpcs = vpcs; } public DescribeImagesResponseType describeImages( final DescribeImagesType request ) throws EucalyptusCloudException, TransactionException { DescribeImagesResponseType reply = request.getReply(); final Context ctx = Contexts.lookup(); final boolean showAllStates = ctx.isAdministrator( ) && request.getImagesSet( ).remove( "verbose" ); final String requestAccountId = ctx.getUserFullName( ).getAccountNumber( ); final List<String> imageIds = normalizeImageIdentifiers( request.getImagesSet() ); final List<String> ownersSet = request.getOwnersSet(); if ( ownersSet.remove( Images.SELF ) ) { ownersSet.add( requestAccountId ); } final Filter filter = Filters.generate( request.getFilterSet(), ImageInfo.class ); final Filter persistenceFilter = getPersistenceFilter( ImageInfo.class, imageIds, "image-id", filter ); final Predicate<? super ImageInfo> requestedAndAccessible = CloudMetadatas.filteringFor( ImageInfo.class ) .byId( imageIds ) .byOwningAccount( request.getOwnersSet() ) .byPredicate( showAllStates ? Predicates.<ImageInfo>alwaysTrue() : Images.standardStatePredicate( ) ) .byPredicate( Images.filterExecutableBy( request.getExecutableBySet() ) ) .byPredicate( filter.asPredicate() ) .byPredicate( Images.FilterPermissions.INSTANCE ) .byPrivilegesWithoutOwner() .buildPredicate(); final List<ImageDetails> imageDetailsList = Transactions.filteredTransform( new ImageInfo( ), persistenceFilter.asCriterion( ), persistenceFilter.getAliases( ), Predicates.and( new TrackingPredicate<ImageInfo>( imageIds ), requestedAndAccessible ), Images.TO_IMAGE_DETAILS ); errorIfNotFound( "InvalidAMIID.NotFound", "image", imageIds ); final Map<String,List<Tag>> tagsMap = TagSupport.forResourceClass( ImageInfo.class ) .getResourceTagMap( AccountFullName.getInstance( ctx.getAccountNumber() ), Iterables.transform( imageDetailsList, ImageDetails.imageId( ) ) ); for ( final ImageDetails details : imageDetailsList ) { Tags.addFromTags( details.getTagSet(), ResourceTag.class, tagsMap.get( details.getImageId() ) ); } reply.getImagesSet( ).addAll( imageDetailsList ); return reply; } public DescribeImageAttributeResponseType describeImageAttribute( final DescribeImageAttributeType request ) throws EucalyptusCloudException { DescribeImageAttributeResponseType reply = request.getReply( ); if ( request.getAttribute( ) != null ) request.applyAttribute( ); try ( final TransactionResource tx = Entities.transactionFor( ImageInfo.class ) ) { final ImageInfo imgInfo = Entities.uniqueResult( Images.exampleWithImageId( imageIdentifier( request.getImageId( ) ) ) ); if ( !canModifyImage( imgInfo ) ) { throw new EucalyptusCloudException( "Not authorized to describe image attribute" ); } reply.setImageId( imgInfo.getDisplayName() ); if ( request.getKernel( ) != null ) { if ( imgInfo instanceof MachineImageInfo ) { if ( ( ( MachineImageInfo ) imgInfo ).getKernelId( ) != null ) { reply.getKernel( ).add( ( ( MachineImageInfo ) imgInfo ).getKernelId( ) ); } } } else if ( request.getRamdisk( ) != null ) { if ( imgInfo instanceof MachineImageInfo ) { if ( ( ( MachineImageInfo ) imgInfo ).getRamdiskId( ) != null ) { reply.getRamdisk( ).add( ( ( MachineImageInfo ) imgInfo ).getRamdiskId( ) ); } } } else if ( request.getLaunchPermission( ) != null ) { if ( imgInfo.getImagePublic( ) ) { reply.getLaunchPermission( ).add( LaunchPermissionItemType.newGroupLaunchPermission() ); } for ( final String permission : imgInfo.getPermissions() ) reply.getLaunchPermission().add( LaunchPermissionItemType.newUserLaunchPermission( permission ) ); } else if ( request.getProductCodes( ) != null ) { reply.getProductCodes( ).addAll( imgInfo.getProductCodes( ) ); } else if ( request.getBlockDeviceMapping( ) != null ) { if ( imgInfo instanceof BlockStorageImageInfo ) { BlockStorageImageInfo bfebsImage = (BlockStorageImageInfo) imgInfo; reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( VmInstances.getEbsRootDeviceName( ), bfebsImage.getRootDeviceName( ) ) ); reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( "root", bfebsImage.getRootDeviceName( ) ) ); int i = 0; for ( DeviceMapping mapping : bfebsImage.getDeviceMappings() ) { if ( mapping.getDeviceName( ).equalsIgnoreCase( bfebsImage.getRootDeviceName( ) ) ) { continue; } switch ( mapping.getDeviceMappingType( ) ) { case blockstorage: BlockStorageDeviceMapping bsdm = ( BlockStorageDeviceMapping ) mapping; BlockDeviceMappingItemType bdmItem = new BlockDeviceMappingItemType( "ebs" + (++i), mapping.getDeviceName( ) ); EbsDeviceMapping ebsItem = new EbsDeviceMapping( ); ebsItem.setSnapshotId( bsdm.getSnapshotId( ) ); ebsItem.setVolumeSize( bsdm.getSize( ) ); ebsItem.setDeleteOnTermination( bsdm.getDelete( ) ); bdmItem.setEbs( ebsItem ); reply.getBlockDeviceMapping( ).add( bdmItem ); break; case ephemeral: reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( mapping.getVirtualName() , mapping.getDeviceName( ) ) ); break; default: break; } } } else { reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( VmInstances.getEbsRootDeviceName( ), "sda1" ) ); reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( "ephemeral0", "sda2" ) ); reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( "swap", "sda3" ) ); reply.getBlockDeviceMapping( ).add( new BlockDeviceMappingItemType( "root", "/dev/sda1" ) ); } } else if ( request.getDescription( ) != null ) { if ( imgInfo.getDescription() != null ) { reply.getDescription().add( imgInfo.getDescription() ); } } else { throw new EucalyptusCloudException( "invalid image attribute request." ); } } catch ( final NoSuchElementException e ) { throw new ComputeServiceClientException( "InvalidAMIID.NotFound", "The image '"+request.getImageId()+"' was not found" ); } catch ( final TransactionException ex ) { throw new EucalyptusCloudException( "Error handling image attribute request: " + ex.getMessage( ), ex ); } return reply; } public DescribeAddressesResponseType describeAddresses( final DescribeAddressesType request ) throws EucalyptusCloudException { final Context ctx = Contexts.lookup( ); final boolean isAdmin = ctx.isAdministrator( ); final boolean verbose = isAdmin && request.getPublicIpsSet( ).contains( "verbose" ) ; if ( verbose ) { // dispatch to back end so all addresses can be described return (DescribeAddressesResponseType) proxy( request ); } // handle stateless describe for users elastic IPs final DescribeAddressesResponseType reply = request.getReply( ); final AccountFullName accountFullName = ctx.getUserFullName( ).asAccountFullName( ); final Filter filter = Filters.generateFor( request.getFilterSet( ), AllocatedAddressEntity.class ) .withOptionalInternalFilter( "public-ip", request.getPublicIpsSet( ) ) .withOptionalInternalFilter( "allocation-id", request.getAllocationIds( ) ) .generate( ); final Predicate<? super AllocatedAddressEntity> requestedAndAccessible = CloudMetadatas.filteringFor( AllocatedAddressEntity.class ) .byId( request.getPublicIpsSet( ) ) .byProperty( request.getAllocationIds( ), AllocatedAddressEntity.allocation( ) ) .byPredicate( filter.asPredicate( ) ) .byOwningAccount( Collections.singleton( accountFullName.getAccountNumber( ) ) ) .byPrivileges( ) .buildPredicate( ); try ( final TransactionResource tx = Entities.readOnlyDistinctTransactionFor( AllocatedAddressEntity.class ) ) { final Iterable<AddressInfoType> addresses = Transactions.filteredTransform( AllocatedAddressEntity.exampleWithOwnerAndAddress( accountFullName, null ), filter.asCriterion( ), filter.getAliases( ), requestedAndAccessible, TypeMappers.lookup( AddressI.class, AddressInfoType.class ) ); Iterables.addAll( reply.getAddressesSet( ), addresses ); } catch ( final Exception e ) { Exceptions.findAndRethrow( e, ComputeServiceException.class ); LOG.error( e ); LOG.debug( e, e ); throw new EucalyptusCloudException( e.getMessage( ) ); } return reply; } public DescribeSecurityGroupsResponseType describeSecurityGroups( final DescribeSecurityGroupsType request ) throws EucalyptusCloudException, MetadataException, TransactionException { final DescribeSecurityGroupsResponseType reply = request.getReply(); final Context ctx = Contexts.lookup(); final boolean showAll = request.getSecurityGroupSet( ).remove( "verbose" ) || request.getSecurityGroupIdSet( ).remove( "verbose" ); NetworkGroups.createDefault( ctx.getUserFullName() ); //ensure the default group exists to cover some old broken installs final List<String> normalizedIds = normalizeGroupIdentifiers( request.getSecurityGroupIdSet( ) ); final Filters.FiltersBuilder builder = Filters.generateFor( request.getFilterSet( ), NetworkGroup.class ); if ( ( request.getSecurityGroupSet( ).isEmpty( ) && !request.getSecurityGroupIdSet( ).isEmpty( ) ) || ( !request.getSecurityGroupSet( ).isEmpty( ) && request.getSecurityGroupIdSet( ).isEmpty( ) )) { builder.withOptionalInternalFilter( "group-name", request.getSecurityGroupSet( ) ); builder.withOptionalInternalFilter( "group-id", normalizedIds ); } final Filter filter = builder.generate( ); final Filter persistenceFilter = getPersistenceFilter( NetworkGroup.class, normalizedIds, "group-id", filter ); final Predicate<? super NetworkGroup> requestedAndAccessible = CloudMetadatas.filteringFor( NetworkGroup.class ) .byPredicate( Predicates.or( request.getSecurityGroupSet( ).isEmpty() && request.getSecurityGroupIdSet( ).isEmpty() ? Predicates.<NetworkGroup>alwaysTrue() : Predicates.<NetworkGroup>alwaysFalse(), request.getSecurityGroupSet( ).isEmpty() ? Predicates.<NetworkGroup>alwaysFalse() : CloudMetadatas.<NetworkGroup>filterById( request.getSecurityGroupSet( ) ), request.getSecurityGroupIdSet( ).isEmpty() ? Predicates.<NetworkGroup>alwaysFalse() : CloudMetadatas.filterByProperty( normalizeGroupIdentifiers( request.getSecurityGroupIdSet( ) ), NetworkGroup.groupId() ) ) ) .byPredicate( filter.asPredicate( ) ) .byPrivileges() .buildPredicate(); final OwnerFullName ownerFn = Contexts.lookup( ).isAdministrator( ) && ( showAll || !normalizedIds.isEmpty( ) ) ? null : AccountFullName.getInstance( ctx.getAccountNumber( ) ); final Iterable<SecurityGroupItemType> securityGroupItems = Entities.asDistinctTransaction( NetworkGroup.class, new Function<Void, Iterable<SecurityGroupItemType>>() { @Nullable @Override public Iterable<SecurityGroupItemType> apply( @Nullable final Void aVoid ) { try { return Transactions.filteredTransform( NetworkGroup.withOwner( ownerFn ), persistenceFilter.asCriterion( ), persistenceFilter.getAliases( ), Predicates.and( new TrackingPredicate<>( NetworkGroup.groupId( ), normalizedIds ), requestedAndAccessible ), TypeMappers.lookup( NetworkGroup.class, SecurityGroupItemType.class ) ); } catch ( TransactionException e ) { if ( Exceptions.isCausedBy( e, EntityNotFoundException.class ) ) { // A rule may have been deleted, retry throw new Entities.RetryTransactionException( e, NetworkGroup.class ); } throw Exceptions.toUndeclared( e ); } } } ).apply( null ); errorIfNotFound( "InvalidGroup.NotFound", "security group", normalizedIds ); final Map<String,List<Tag>> tagsMap = TagSupport.forResourceClass( NetworkGroup.class ) .getResourceTagMap( AccountFullName.getInstance( ctx.getAccountNumber( ) ), Iterables.transform( securityGroupItems, SecurityGroupItemToGroupId.INSTANCE ) ); for ( final SecurityGroupItemType securityGroupItem : securityGroupItems ) { Tags.addFromTags( securityGroupItem.getTagSet(), ResourceTag.class, tagsMap.get( securityGroupItem.getGroupId() ) ); } Iterables.addAll( reply.getSecurityGroupInfo( ), securityGroupItems ); return reply; } public DescribeInstancesResponseType describeInstances( final DescribeInstancesType msg ) throws EucalyptusCloudException { final DescribeInstancesResponseType reply = msg.getReply( ); Context ctx = Contexts.lookup( ); boolean showAll = msg.getInstancesSet( ).remove( "verbose" ) || !msg.getInstancesSet( ).isEmpty( ); final Multimap<String, RunningInstancesItemType> instanceMap = TreeMultimap.create(); final Map<String, ReservationInfoType> reservations = Maps.newHashMap(); final Collection<String> identifiers = normalizeInstanceIdentifiers( msg.getInstancesSet() ); final Filter filter = Filters.generateFor( msg.getFilterSet(), VmInstance.class ) .withOptionalInternalFilter( "instance-id", identifiers ) .generate(); final Filter persistenceFilter = getPersistenceFilter( VmInstance.class, identifiers, "instance-id", filter ); final Predicate<? super VmInstance> requestedAndAccessible = CloudMetadatas.filteringFor( VmInstance.class ) .byId( identifiers ) // filters without wildcard support .byPredicate( filter.asPredicate() ) .byPrivileges() .buildPredicate(); final OwnerFullName ownerFullName = ( ctx.isAdministrator( ) && showAll ) ? null : ctx.getUserFullName( ).asAccountFullName( ); try ( final TransactionResource db = Entities.readOnlyDistinctTransactionFor( VmInstance.class ) ) { final List<VmInstance> instances = VmInstances.list( ownerFullName, persistenceFilter.asCriterionWithConjunction( Restrictions.not( VmInstance.criterion( VmInstance.VmState.BURIED ) ) ), persistenceFilter.getAliases( ), Predicates.and( new TrackingPredicate<VmInstance>( identifiers ), requestedAndAccessible ) ); errorIfNotFound( "InvalidInstanceID.NotFound", "instance ID", identifiers ); final Map<String,List<Tag>> tagsMap = TagSupport.forResourceClass( VmInstance.class ) .getResourceTagMap( AccountFullName.getInstance( ctx.getAccountNumber() ), Iterables.transform( instances, CloudMetadatas.toDisplayName() ) ); for ( final VmInstance vm : instances ) { if ( instanceMap.put( vm.getReservationId( ), VmInstance.transform( vm ) ) && !reservations.containsKey( vm.getReservationId( ) ) ) { reservations.put( vm.getReservationId( ), TypeMappers.transform( vm, ReservationInfoType.class ) ); } } List<ReservationInfoType> replyReservations = reply.getReservationSet( ); for ( ReservationInfoType r : reservations.values( ) ) { Collection<RunningInstancesItemType> instanceSet = instanceMap.get( r.getReservationId( ) ); if ( !instanceSet.isEmpty( ) ) { for ( final RunningInstancesItemType instancesItemType : instanceSet ) { Tags.addFromTags( instancesItemType.getTagSet(), ResourceTag.class, tagsMap.get( instancesItemType.getInstanceId() ) ); } r.getInstancesSet( ).addAll( instanceSet ); replyReservations.add( r ); } } } catch ( final Exception e ) { Exceptions.findAndRethrow( e, ComputeServiceException.class ); LOG.error( e ); LOG.debug( e, e ); throw new EucalyptusCloudException( e.getMessage( ) ); } return reply; } public DescribeInstanceStatusResponseType describeInstanceStatus( final DescribeInstanceStatusType msg ) throws EucalyptusCloudException { final DescribeInstanceStatusResponseType reply = msg.getReply(); final Context ctx = Contexts.lookup(); final boolean showAll = msg.getInstancesSet( ).remove( "verbose" ) || !msg.getInstancesSet( ).isEmpty( ); final boolean includeAllInstances = Objects.firstNonNull( msg.getIncludeAllInstances(), Boolean.FALSE ); final Collection<String> identifiers = normalizeInstanceIdentifiers( msg.getInstancesSet() ); final Filter filter = Filters.generateFor( msg.getFilterSet(), VmInstance.class, "status" ) .withOptionalInternalFilter( "instance-id", identifiers ) .generate(); final Filter persistenceFilter = getPersistenceFilter( VmInstance.class, "status", identifiers, "instance-id", filter ); final Predicate<? super VmInstance> requestedAndAccessible = CloudMetadatas.filteringFor( VmInstance.class ) .byId( identifiers ) // filters without wildcard support .byPredicate( includeAllInstances ? Predicates.<VmInstance>alwaysTrue() : VmInstance.VmState.RUNNING ) .byPredicate( filter.asPredicate() ) .byPrivileges() .buildPredicate(); final OwnerFullName ownerFullName = ( ctx.isAdministrator( ) && showAll ) ? null : ctx.getUserFullName( ).asAccountFullName( ); try { final List<VmInstance> instances = VmInstances.list( ownerFullName, persistenceFilter.asCriterionWithConjunction( Restrictions.not( VmInstance.criterion( VmInstance.VmState.BURIED ) ) ), persistenceFilter.getAliases( ), Predicates.and( new TrackingPredicate<VmInstance>( identifiers ), requestedAndAccessible ) ); errorIfNotFound( "InvalidInstanceID.NotFound", "instance ID", identifiers ); Iterables.addAll( reply.getInstanceStatusSet().getItem(), Iterables.transform( instances, TypeMappers.lookup( VmInstance.class, InstanceStatusItemType.class ) ) ); } catch ( final Exception e ) { Exceptions.findAndRethrow( e, ComputeServiceException.class ); LOG.error( e ); LOG.debug( e, e ); throw new EucalyptusCloudException( e.getMessage( ) ); } return reply; } public DescribeInstanceAttributeResponseType describeInstanceAttribute( final DescribeInstanceAttributeType request ) throws EucalyptusCloudException { final DescribeInstanceAttributeResponseType reply = request.getReply( ); final String instanceId = normalizeInstanceIdentifier( request.getInstanceId() ); final String attribute = request.getAttribute( ); if ( attribute == null ) { throw new ComputeServiceClientException( " MissingParameter", "Attribute parameter is required" ); } try ( final TransactionResource tx = Entities.transactionFor( VmInstance.class ) ) { final VmInstance vm = RestrictedTypes.doPrivileged( instanceId, VmInstance.class ); reply.setInstanceId( instanceId ); switch ( attribute ) { case "blockDeviceMapping": if ( vm.getBootRecord( ).getMachine( ) instanceof BlockStorageImageInfo ) { final BlockStorageImageInfo bfebsInfo = ( BlockStorageImageInfo ) vm.getBootRecord( ).getMachine( ); for ( final VmVolumeAttachment volumeAttachment : vm.getBootRecord().getPersistentVolumes( ) ) { reply.getBlockDeviceMapping( ).add( new InstanceBlockDeviceMapping( volumeAttachment.getIsRootDevice( ) ? bfebsInfo.getRootDeviceName( ) : volumeAttachment.getDevice( ), volumeAttachment.getVolumeId(), volumeAttachment.getStatus(), volumeAttachment.getAttachTime(), volumeAttachment.getDeleteOnTerminate() ) ); } } break; case "disableApiTermination": reply.setDisableApiTermination( Optional.fromNullable( vm.getDisableApiTermination( ) ).or( Boolean.FALSE ) ); break; case "ebsOptimized": reply.setEbsOptimized( false ); break; case "groupSet": Iterables.addAll( reply.getGroupSet( ), Iterables.transform( vm.getNetworkGroupIds( ), TypeMappers.lookup( NetworkGroupId.class, GroupItemType.class ) ) ); break; case "instanceInitiatedShutdownBehavior": reply.setInstanceInitiatedShutdownBehavior( "stop" ); break; case "instanceType": reply.setInstanceType( vm.getBootRecord( ).getVmType( ).getDisplayName( ) ); break; case "kernel": reply.setKernel( vm.getKernelId( ) ); break; case "productCodes": reply.setProductCodes( false ); // set some value so an empty wrapper can be included in the response break; case "ramdisk": reply.setRamdisk( vm.getRamdiskId( ) ); break; case "rootDeviceName": reply.setRootDeviceName( vm.getBootRecord( ).getMachine( ) == null ? null : vm.getBootRecord( ).getMachine( ).getRootDeviceName( ) ); break; case "sourceDestCheck": reply.setSourceDestCheck( true ); if ( vm.getNetworkInterfaces( ) != null ) { for ( final NetworkInterface networkInterface : vm.getNetworkInterfaces( ) ) { if ( networkInterface.getAttachment( ).getDeviceIndex( ) == 0 ) { reply.setSourceDestCheck( networkInterface.getSourceDestCheck( ) ); break; } } } break; case "sriovNetSupport": reply.setSriovNetSupport( false ); break; case "userData": reply.setUserData( vm.getUserData( ) == null ? "" : Base64.toBase64String( vm.getUserData() ) ); break; default: throw new ComputeServiceClientException( " InvalidParameterValue", "Invalid value for attribute ("+attribute+")" ); } } catch ( Exception ex ) { LOG.error( ex ); throw new ComputeServiceClientException("InvalidInstanceID.NotFound", "The instance ID '" + instanceId + "' does not exist"); } return reply; } public DescribeKeyPairsResponseType describeKeyPairs( DescribeKeyPairsType request ) throws Exception { final DescribeKeyPairsResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup( ); final List<String> keyNames = request.getKeySet( ); final boolean showAll = keyNames.remove( "verbose" ); final OwnerFullName ownerFullName = ctx.isAdministrator( ) && showAll ? null : Contexts.lookup( ).getUserFullName( ).asAccountFullName( ); final Filter filter = Filters.generate( request.getFilterSet(), SshKeyPair.class ); final Filter persistenceFilter = getPersistenceFilter( SshKeyPair.class, keyNames, "key-name", filter ); final Predicate<? super SshKeyPair> requestedAndAccessible = CloudMetadatas.filteringFor( SshKeyPair.class ) .byId( keyNames ) .byPredicate( filter.asPredicate() ) .byPrivileges() .buildPredicate(); final Iterable<SshKeyPair> keyPairs = KeyPairs.list( ownerFullName, Predicates.and( new TrackingPredicate<SshKeyPair>( keyNames ), requestedAndAccessible ), persistenceFilter.asCriterion( ), persistenceFilter.getAliases( ) ); for ( final SshKeyPair kp : keyPairs ) { reply.getKeySet( ).add( new DescribeKeyPairsResponseItemType( kp.getDisplayName( ), kp.getFingerPrint( ) ) ); } errorIfNotFound( "InvalidKeyPair.NotFound", "key pair", keyNames ); return reply; } public CopySnapshotResponseType copySnapshot( final CopySnapshotType request ) { final CopySnapshotResponseType reply = request.getReply( ); return reply; } public DescribePlacementGroupsResponseType describePlacementGroups( final DescribePlacementGroupsType request ) { final DescribePlacementGroupsResponseType reply = request.getReply( ); return reply; } public DescribeReservedInstancesResponseType describeReservedInstances( final DescribeReservedInstancesType request ) { return request.getReply( ); } public DescribeReservedInstancesListingsResponseType describeReservedInstancesListings( final DescribeReservedInstancesListingsType request ) { return request.getReply( ); } public DescribeReservedInstancesModificationsResponseType describeReservedInstancesModifications( final DescribeReservedInstancesModificationsType request ) { return request.getReply( ); } public DescribeReservedInstancesOfferingsResponseType describeReservedInstancesListings( final DescribeReservedInstancesOfferingsType request ) { return request.getReply( ); } public CreateReservedInstancesListingResponseType createReservedInstancesListing( final CreateReservedInstancesListingType request ) { return request.getReply( ); } public CancelReservedInstancesListingResponseType cancelReservedInstancesListing( final CancelReservedInstancesListingType request ) { return request.getReply( ); } public ModifyReservedInstancesResponseType modifyReservedInstances( final ModifyReservedInstancesType request ) { return request.getReply( ); } public PurchaseReservedInstancesOfferingResponseType purchaseReservedInstancesOffering( final PurchaseReservedInstancesOfferingType request ) { return request.getReply( ); } public GetReservedInstancesExchangeQuoteResponseType getReservedInstancesExchangeQuote( final GetReservedInstancesExchangeQuoteType request ) { return request.getReply( ); } public AcceptReservedInstancesExchangeQuoteResponseType acceptReservedInstancesExchangeQuote( final AcceptReservedInstancesExchangeQuoteType request ) { return request.getReply( ); } public CancelSpotInstanceRequestsResponseType cancelSpotInstanceRequests( CancelSpotInstanceRequestsType request ) { return request.getReply( ); } public CreateSpotDatafeedSubscriptionResponseType createSpotDatafeedSubscription( CreateSpotDatafeedSubscriptionType request ) { return request.getReply( ); } public DeleteSpotDatafeedSubscriptionResponseType deleteSpotDatafeedSubscription( DeleteSpotDatafeedSubscriptionType request ) { return request.getReply( ); } public DescribeSpotDatafeedSubscriptionResponseType describeSpotDatafeedSubscription( DescribeSpotDatafeedSubscriptionType request ) { return request.getReply( ); } public DescribeSpotInstanceRequestsResponseType describeSpotInstances( DescribeSpotInstanceRequestsType request ) { return request.getReply( ); } public RequestSpotInstancesResponseType requestSpotInstances( RequestSpotInstancesType request ) { return request.getReply( ); } public CancelSpotFleetRequestsResponseType cancelSpotFleetRequests( CancelSpotFleetRequestsType request ) { return request.getReply( ); } public DescribeSpotFleetInstancesResponseType describeSpotFleetInstances( DescribeSpotFleetInstancesType request ) { return request.getReply( ); } public DescribeSpotFleetRequestHistoryResponseType describeSpotFleetRequestHistory( DescribeSpotFleetRequestHistoryType request ) { return request.getReply( ); } public DescribeSpotFleetRequestsResponseType describeSpotFleetRequests( DescribeSpotFleetRequestsType request ) { return request.getReply( ); } public RequestSpotFleetResponseType requestSpotFleet( RequestSpotFleetType request ) { return request.getReply( ); } public ModifySpotFleetRequestResponseType modifySpotFleet( ModifySpotFleetRequestType request ) { return request.getReply( ); } /** * */ public DescribeVolumesResponseType describeVolumes( DescribeVolumesType request ) throws Exception { final DescribeVolumesResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup( ); final boolean showAll = request.getVolumeSet( ).remove( "verbose" ); final Set<String> volumeIds = Sets.newLinkedHashSet( normalizeVolumeIdentifiers( request.getVolumeSet( ) ) ); final AccountFullName ownerFullName = ( ctx.isAdministrator( ) && ( showAll || !volumeIds.isEmpty( ) ) ) ? null : ctx.getUserFullName( ).asAccountFullName( ); final Filters.FiltersBuilder filtersBuilder = Filters.generateFor( request.getFilterSet( ), Volume.class ); if ( !ctx.isAdministrator( ) ) { filtersBuilder.withOptionalInternalFilter( "system-managed", Collections.singleton( "false" ) ); } final Filter filter = filtersBuilder.generate( ); final Filter persistenceFilter = getPersistenceFilter( Volume.class, volumeIds, "volume-id", filter ); final Predicate<? super Volume> requestedAndAccessibleUnfiltered = CloudMetadatas.filteringFor( Volume.class ) .byId( volumeIds ) .byPrivileges() .buildPredicate(); final Predicate<? super Volume> filterPredicate = filter.asPredicate( ); final Function<Set<String>, ArrayList<com.eucalyptus.compute.common.Volume>> populateVolumeSet = new Function<Set<String>, ArrayList<com.eucalyptus.compute.common.Volume>>( ) { public ArrayList<com.eucalyptus.compute.common.Volume> apply( final Set<String> input ) { final ArrayList<com.eucalyptus.compute.common.Volume> replyVolumes = Lists.newArrayList(); final List<Volume> volumes = Entities.query( Volume.named( ownerFullName, null ), true, persistenceFilter.asCriterion( ), persistenceFilter.getAliases( ) ); final Iterable<Volume> filteredVolumes = Iterables.filter( volumes, Predicates.and( new TrackingPredicate<>( volumeIds ), requestedAndAccessibleUnfiltered ) ); // load attachment info final Criterion attachmentCriterion; final Map<String,String> attachmentAliases; if ( Iterables.isEmpty( filteredVolumes ) ) { attachmentCriterion = Restrictions.disjunction( ); attachmentAliases = Collections.emptyMap( ); } else if ( Iterables.size( Iterables.limit( filteredVolumes, 51 ) ) < 50 ) { // small # load by id attachmentCriterion = Restrictions.in( "volumeId", Sets.newHashSet( Iterables.transform( filteredVolumes, RestrictedTypes.toDisplayName( ) ) ) ); attachmentAliases = Collections.emptyMap( ); } else if ( ownerFullName == null ) { // load attachments for all accounts attachmentCriterion = Restrictions.conjunction( ); attachmentAliases = Collections.emptyMap( ); } else { // load all attachments for account attachmentCriterion = Restrictions.eq( "vmInstance.ownerAccountNumber", ownerFullName.getAccountNumber( ) );; attachmentAliases = Collections.singletonMap( "vmInstance", "vmInstance" ); } final Map<String,VmVolumeAttachment> attachmentMap = CollectionUtils.putAll( Iterables.concat( Entities.query( VmBootVolumeAttachment.example( ), true, attachmentCriterion, attachmentAliases ), Entities.query( VmStandardVolumeAttachment.example( ), true, attachmentCriterion, attachmentAliases ) ), Maps.<String,VmVolumeAttachment>newHashMap( ), VmVolumeAttachment.volumeId( ), Functions.<VmVolumeAttachment>identity( ) ); // build response volumes for ( final Volume foundVol : filteredVolumes ) { if ( State.ANNIHILATED.equals( foundVol.getState( ) ) ) { Entities.delete( foundVol ); if ( filterPredicate.apply( foundVol ) ) { replyVolumes.add( foundVol.morph( new com.eucalyptus.compute.common.Volume( ) ) ); } } else if ( State.BUSY.equals( foundVol.getState( ) ) ) { final VmVolumeAttachment attachment = attachmentMap.get( foundVol.getDisplayName( ) ); Option<AttachedVolume> attachedVolume = Option.none( ); if ( attachment != null ) { attachedVolume = Option.some( VmVolumeAttachment.asAttachedVolume( attachment.getVmInstance( ) ).apply( attachment ) ); } else { foundVol.setState( State.EXTANT ); } if ( filterPredicate.apply( foundVol ) ) { final com.eucalyptus.compute.common.Volume msgTypeVolume = foundVol.morph( new com.eucalyptus.compute.common.Volume( ) ); msgTypeVolume.getAttachmentSet( ).addAll( attachedVolume.toJavaList( ) ); replyVolumes.add( msgTypeVolume ); } } else if ( filterPredicate.apply( foundVol ) ) { replyVolumes.add( foundVol.morph( new com.eucalyptus.compute.common.Volume() ) ); } } return replyVolumes; } }; final ArrayList<com.eucalyptus.compute.common.Volume> volumes = Entities.asTransaction( Volume.class, populateVolumeSet ).apply( volumeIds ); errorIfNotFound( "InvalidVolume.NotFound", "volume", volumeIds ); @SuppressWarnings( "ConstantConditions" ) final Set<String> allowedVolumeIds = volumes.stream( ).map( com.eucalyptus.compute.common.Volume::getVolumeId ).collect( Collectors.toSet( ) ); reply.setVolumeSet( volumes ); Map<String,List<Tag>> tagsMap = TagSupport.forResourceClass( Volume.class ) .getResourceTagMap( AccountFullName.getInstance( ctx.getAccountNumber( ) ), allowedVolumeIds ); for ( final com.eucalyptus.compute.common.Volume volume : reply.getVolumeSet() ) { Tags.addFromTags( volume.getTagSet(), ResourceTag.class, tagsMap.get( volume.getVolumeId() ) ); } return reply; } public DescribeVolumeStatusResponseType describeVolumeStatus( final DescribeVolumeStatusType request ) throws EucalyptusCloudException { final DescribeVolumeStatusResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup( ); final boolean showAll = request.getVolumeId( ).remove( "verbose" ); final Set<String> volumeIds = Sets.newLinkedHashSet( normalizeVolumeIdentifiers( request.getVolumeId( ) ) ); final AccountFullName ownerFullName = ( ctx.isAdministrator( ) && ( showAll || !volumeIds.isEmpty( ) ) ) ? null : ctx.getUserFullName( ).asAccountFullName( ); final Filters.FiltersBuilder filtersBuilder = Filters.generateFor( request.getFilterSet( ), Volume.class, "status" ); if ( !ctx.isAdministrator( ) ) { filtersBuilder.withOptionalInternalFilter( "system-managed", Collections.singleton( "false" ) ); } final Filter filter = filtersBuilder.generate( ); final Filter persistenceFilter = getPersistenceFilter( Volume.class, "status", volumeIds, "volume-id", filter ); final Predicate<? super Volume> requestedAndAccessible = CloudMetadatas.filteringFor( Volume.class ) .byId( volumeIds ) .byPredicate( filter.asPredicate() ) .byPrivileges( ) .buildPredicate( ); final Function<Volume,VolumeStatusItemType> volumeTransform = TypeMappers.lookup( Volume.class, VolumeStatusItemType.class ); final Function<Set<String>, ArrayList<VolumeStatusItemType>> populateVolumeSet = new Function<Set<String>, ArrayList<VolumeStatusItemType>>( ) { public ArrayList<VolumeStatusItemType> apply( final Set<String> input ) { final ArrayList<VolumeStatusItemType> replyVolumes = Lists.newArrayList(); final List<Volume> volumes = Entities.query( Volume.named( ownerFullName, null ), true, persistenceFilter.asCriterion( ), persistenceFilter.getAliases( ) ); final Iterable<Volume> filteredVolumes = Iterables.filter( volumes, Predicates.and( new TrackingPredicate<Volume>( volumeIds ), requestedAndAccessible ) ); for ( final Volume foundVol : filteredVolumes ) { if ( State.ANNIHILATED.equals( foundVol.getState( ) ) ) { Entities.delete( foundVol ); } replyVolumes.add( volumeTransform.apply( foundVol ) ); } return replyVolumes; } }; final ArrayList<VolumeStatusItemType> volumeStatusItemTypes = Entities.asTransaction( Volume.class, populateVolumeSet ).apply( volumeIds ); errorIfNotFound( "InvalidVolume.NotFound", "volume", volumeIds ); reply.setVolumeStatusSet( volumeStatusItemTypes ); return reply; } public DescribeSnapshotsResponseType describeSnapshots( final DescribeSnapshotsType request ) throws EucalyptusCloudException { final DescribeSnapshotsResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup(); final String requestAccountId = ctx.getUserFullName( ).getAccountNumber(); // verbose does not have any special functionality for snapshots, but is ignored when passed as an identifier request.getSnapshotSet().remove( "verbose" ); final Set<String> snapshotIds = Sets.newHashSet( normalizeSnapshotIdentifiers( request.getSnapshotSet() ) ); final List<String> ownersSet = request.getOwnersSet( ); if ( ownersSet.remove( Snapshots.SELF ) ) { ownersSet.add( requestAccountId ); } final Filter filter = Filters.generate( request.getFilterSet(), Snapshot.class ); final Filter persistenceFilter = getPersistenceFilter( Snapshot.class, snapshotIds, "snapshot-id", filter ); try ( final TransactionResource tx = Entities.readOnlyDistinctTransactionFor( Snapshot.class ) ){ final List<Snapshot> unfilteredSnapshots = Entities.query( Snapshot.named( null, null ), true, persistenceFilter.asCriterion(), persistenceFilter.getAliases() ); final Predicate<? super Snapshot> requestedAndAccessible = CloudMetadatas.filteringFor( Snapshot.class ) .byId( snapshotIds ) .byOwningAccount( request.getOwnersSet( ) ) .byPredicate( Snapshots.filterRestorableBy( request.getRestorableBySet( ), requestAccountId ) ) .byPredicate( filter.asPredicate( ) ) .byPredicate( Snapshots.FilterPermissions.INSTANCE ) .byPrivilegesWithoutOwner( ) .buildPredicate( ); final List<Snapshot> snapshots = Lists.newArrayList( Iterables.filter( unfilteredSnapshots, Predicates.and( new TrackingPredicate<>( snapshotIds ), requestedAndAccessible ) ) ); errorIfNotFound( "InvalidSnapshot.NotFound", "snapshot", snapshotIds ); final Map<String,List<Tag>> tagsMap = TagSupport.forResourceClass( Snapshot.class ) .getResourceTagMap( AccountFullName.getInstance( ctx.getAccountNumber( ) ), Iterables.transform( snapshots, CloudMetadatas.toDisplayName() ) ); for ( final Snapshot snap : snapshots ) { try { final com.eucalyptus.compute.common.Snapshot snapReply = snap.morph( new com.eucalyptus.compute.common.Snapshot( ) ); Tags.addFromTags( snapReply.getTagSet(), ResourceTag.class, tagsMap.get( snapReply.getSnapshotId() ) ); snapReply.setVolumeId( snap.getParentVolume( ) ); snapReply.setOwnerId( snap.getOwnerAccountNumber( ) ); reply.getSnapshotSet( ).add( snapReply ); } catch ( NoSuchElementException e ) { LOG.warn( "Error getting snapshot information from the Storage Controller: " + e ); LOG.debug( e, e ); } } } return reply; } public DescribeSnapshotAttributeResponseType describeSnapshotAttribute( DescribeSnapshotAttributeType request ) throws EucalyptusCloudException { DescribeSnapshotAttributeResponseType reply = request.getReply( ); reply.setSnapshotId(request.getSnapshotId()); final Context ctx = Contexts.lookup(); final String snapshotId = normalizeSnapshotIdentifier( request.getSnapshotId() ); try (TransactionResource db = Entities.transactionFor(Snapshot.class)) { Snapshot result = Entities.uniqueResult( Snapshot.named( ctx.isAdministrator() ? null : ctx.getUserFullName().asAccountFullName(), snapshotId ) ); if( !RestrictedTypes.filterPrivileged( ).apply( result ) ) { throw new EucalyptusCloudException("Not authorized to describe attributes for snapshot " + request.getSnapshotId()); } ArrayList<CreateVolumePermissionItemType> permissions = Lists.newArrayList(); for(String id : result.getPermissions()) { permissions.add(new CreateVolumePermissionItemType(id, null)); } if(result.getSnapshotPublic()) { permissions.add(new CreateVolumePermissionItemType(null, "all")); } if(result.getProductCodes() != null) { reply.setProductCodes(new ArrayList<>(result.getProductCodes())); } reply.setCreateVolumePermission(permissions); } catch ( NoSuchElementException ex2 ) { throw new ComputeServiceClientException( "InvalidSnapshot.NotFound", "The snapshot '"+request.getSnapshotId( )+"' does not exist." ); } catch ( ExecutionException ex1 ) { throw new EucalyptusCloudException( ex1.getCause( ) ); } return reply; } public DescribeVolumeAttributeResponseType describeVolumeAttribute( final DescribeVolumeAttributeType request ) throws EucalyptusCloudException { if ( request.getAttribute( ) == null ) { throw new ComputeServiceClientException( "InvalidParameterCombination", "No attributes specified" ); } final DescribeVolumeAttributeResponseType reply = request.getReply( ); final String volumeId = normalizeVolumeIdentifier( request.getVolumeId( ) ); reply.setVolumeId( volumeId ); if ( "autoEnableIO".equals( request.getAttribute( ) ) ) { reply.setAutoEnableIO( false ); } else { reply.setProductCodes( false ); } return reply; } public CancelImportTaskResponseType cancelImportTask( CancelImportTaskType request ) { return request.getReply( ); } public DescribeImportImageTasksResponseType describeImportImageTasks( DescribeImportImageTasksType request ) { return request.getReply( ); } public DescribeImportSnapshotTasksResponseType describeImportSnapshotTasks( DescribeImportSnapshotTasksType request ) { return request.getReply( ); } public ImportImageResponseType importImage( ImportImageType request ) { return request.getReply( ); } public ImportSnapshotResponseType importSnapshot( ImportSnapshotType request ) { return request.getReply( ); } public DescribeTagsResponseType describeTags( final DescribeTagsType request ) throws Exception { final DescribeTagsResponseType reply = request.getReply( ); final Context context = Contexts.lookup(); final Filter filter = Filters.generate( request.getFilterSet(), Tag.class ); final Predicate<? super Tag> requestedAndAccessible = CloudMetadatas.filteringFor(Tag.class) .byPredicate( filter.asPredicate( ) ) .byPrivileges( ) .buildPredicate( ); final Ordering<Tag> ordering = Ordering.natural().onResultOf( Tags.resourceId() ) .compound( Ordering.natural().onResultOf( Tags.key() ) ) .compound( Ordering.natural().onResultOf( Tags.value() ) ); Iterables.addAll( reply.getTagSet(), Iterables.transform( ordering.sortedCopy( Tags.list( context.getUserFullName().asAccountFullName(), requestedAndAccessible, filter.asCriterion(), filter.getAliases() ) ), TypeMappers.lookup( Tag.class, TagInfo.class ) ) ); return reply; } public DescribeAccountAttributesResponseType describeAccountAttributes(final DescribeAccountAttributesType request) throws EucalyptusCloudException { final DescribeAccountAttributesResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup( ); final AccountFullName accountFullName = ctx.getUserFullName( ).asAccountFullName( ); final List<String> platforms = Lists.newArrayList( ); final Set<NetworkingFeature> features = Networking.getInstance().describeFeatures( ); if ( features.contains( NetworkingFeature.Classic ) ) platforms.add( "EC2" ); if ( features.contains( NetworkingFeature.Vpc ) ) platforms.add( "VPC" ); String vpcId = "none"; try { vpcId = vpcs.lookupDefault( accountFullName, CloudMetadatas.toDisplayName( ) ); } catch ( VpcMetadataNotFoundException e) { // no default vpc } catch ( Exception e ) { throw handleException( e ); } final Map<String,List<String>> attributes = ImmutableMap.of( "supported-platforms", platforms, "default-vpc", Lists.newArrayList( vpcId ) ); final Set<String> requestedAttributes = Sets.newHashSet( request.attributeNames( ) ); for ( final Map.Entry<String,List<String>> attributeEntry : attributes.entrySet( ) ) { if ( requestedAttributes.isEmpty( ) || requestedAttributes.contains( attributeEntry.getKey( ) ) ) { reply.getAccountAttributeSet().getItem().add( new AccountAttributeSetItemType( attributeEntry.getKey( ), attributeEntry.getValue( ) ) ); } } return reply; } public DescribeCustomerGatewaysResponseType describeCustomerGateways(DescribeCustomerGatewaysType request) throws EucalyptusCloudException { DescribeCustomerGatewaysResponseType reply = request.getReply( ); return reply; } public DescribeDhcpOptionsResponseType describeDhcpOptions( final DescribeDhcpOptionsType request ) throws EucalyptusCloudException { final DescribeDhcpOptionsResponseType reply = request.getReply( ); describe( Identifier.dopt, request.dhcpOptionsIds( ), request.getFilterSet( ), DhcpOptionSet.class, DhcpOptionsType.class, reply.getDhcpOptionsSet( ).getItem( ), DhcpOptionsType.id( ), dhcpOptionSets ); return reply; } public DescribeInternetGatewaysResponseType describeInternetGateways( final DescribeInternetGatewaysType request ) throws EucalyptusCloudException { final DescribeInternetGatewaysResponseType reply = request.getReply( ); describe( Identifier.igw, request.internetGatewayIds( ), request.getFilterSet( ), InternetGateway.class, InternetGatewayType.class, reply.getInternetGatewaySet( ).getItem( ), InternetGatewayType.id( ), internetGateways ); return reply; } public DescribeNatGatewaysResponseType describeNatGateways( final DescribeNatGatewaysType request ) throws EucalyptusCloudException { final DescribeNatGatewaysResponseType reply = request.getReply( ); describe( Identifier.nat, request.natGatewayIds( ), request.getFilterSet( ), NatGateway.class, NatGatewayType.class, reply.getNatGatewaySet( ).getItem( ), natGateways ); return reply; } public DescribeNetworkAclsResponseType describeNetworkAcls( final DescribeNetworkAclsType request ) throws EucalyptusCloudException { final DescribeNetworkAclsResponseType reply = request.getReply( ); describe( Identifier.acl, request.networkAclIds(), request.getFilterSet( ), NetworkAcl.class, NetworkAclType.class, reply.getNetworkAclSet().getItem( ), NetworkAclType.id( ), networkAcls ); return reply; } public DescribeNetworkInterfaceAttributeResponseType describeNetworkInterfaceAttribute(final DescribeNetworkInterfaceAttributeType request) throws EucalyptusCloudException { final DescribeNetworkInterfaceAttributeResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup( ); final AccountFullName accountFullName = ctx.getUserFullName( ).asAccountFullName( ); try { final NetworkInterface networkInterface = networkInterfaces.lookupByName( accountFullName, Identifier.eni.normalize( request.getNetworkInterfaceId() ), new Function<NetworkInterface,NetworkInterface>( ){ @Override public NetworkInterface apply( final NetworkInterface networkInterface ) { Entities.initialize( networkInterface.getNetworkGroups( ) ); return networkInterface; } } ); if ( RestrictedTypes.filterPrivileged( ).apply( networkInterface ) ) { reply.setNetworkInterfaceId( networkInterface.getDisplayName( ) ); switch ( request.getAttribute() ) { case "attachment": if ( networkInterface.isAttached( ) ) reply.setAttachment( TypeMappers.transform( networkInterface.getAttachment( ), NetworkInterfaceAttachmentType.class ) ); break; case "description": reply.setDescription( new NullableAttributeValueType( ) ); reply.getDescription().setValue( networkInterface.getDescription( ) ); break; case "groupSet": reply.setGroupSet( new GroupSetType( Collections2.transform( networkInterface.getNetworkGroups( ), TypeMappers.lookup( NetworkGroup.class, GroupItemType.class ) ) ) ); break; case "sourceDestCheck": reply.setSourceDestCheck( new AttributeBooleanValueType() ); reply.getSourceDestCheck().setValue( networkInterface.getSourceDestCheck( ) ); break; default: throw new ComputeServiceClientException( "InvalidParameterValue", "Value ("+request.getAttribute( )+") for parameter attribute is invalid. Unknown network interface attribute" ); } } } catch ( final Exception e ) { throw handleException( e ); } return reply; } public DescribeNetworkInterfacesResponseType describeNetworkInterfaces( final DescribeNetworkInterfacesType request ) throws EucalyptusCloudException { final DescribeNetworkInterfacesResponseType reply = request.getReply( ); describe( Identifier.eni, request.networkInterfaceIds(), request.getFilterSet( ), NetworkInterface.class, NetworkInterfaceType.class, reply.getNetworkInterfaceSet().getItem( ), NetworkInterfaceType.id( ), networkInterfaces ); return reply; } public DescribeRouteTablesResponseType describeRouteTables( final DescribeRouteTablesType request ) throws EucalyptusCloudException { final DescribeRouteTablesResponseType reply = request.getReply( ); describe( Identifier.rtb, request.routeTableIds( ), request.getFilterSet( ), RouteTable.class, RouteTableType.class, reply.getRouteTableSet( ).getItem( ), RouteTableType.id( ), routeTables ); return reply; } public DescribeSubnetsResponseType describeSubnets( final DescribeSubnetsType request ) throws EucalyptusCloudException { final DescribeSubnetsResponseType reply = request.getReply( ); describe( Identifier.subnet, request.subnetIds(), request.getFilterSet( ), Subnet.class, SubnetType.class, reply.getSubnetSet().getItem( ), SubnetType.id( ), subnets ); return reply; } public DescribeVpcAttributeResponseType describeVpcAttribute(final DescribeVpcAttributeType request) throws EucalyptusCloudException { final DescribeVpcAttributeResponseType reply = request.getReply( ); final Context ctx = Contexts.lookup( ); final AccountFullName accountFullName = ctx.getUserFullName( ).asAccountFullName( ); try { final Vpc vpc = vpcs.lookupByName( accountFullName, Identifier.vpc.normalize( request.getVpcId( ) ), Functions.<Vpc>identity() ); if ( RestrictedTypes.filterPrivileged( ).apply( vpc ) ) { reply.setVpcId( vpc.getDisplayName( ) ); switch ( request.getAttribute( ) ) { case "enableDnsSupport": reply.setEnableDnsSupport( new AttributeBooleanValueType( ) ); reply.getEnableDnsSupport( ).setValue( vpc.getDnsEnabled( ) ); break; case "enableDnsHostnames": reply.setEnableDnsHostnames( new AttributeBooleanValueType( ) ); reply.getEnableDnsHostnames( ).setValue( vpc.getDnsHostnames( ) ); break; default: throw new ComputeServiceClientException( "InvalidParameterValue", "Value ("+request.getAttribute( )+") for parameter attribute is invalid. Unknown vpc attribute" ); } } } catch ( final Exception e ) { throw handleException( e ); } return reply; } public DescribeVpcPeeringConnectionsResponseType describeVpcPeeringConnections(DescribeVpcPeeringConnectionsType request) throws EucalyptusCloudException { DescribeVpcPeeringConnectionsResponseType reply = request.getReply( ); return reply; } public ModifyVpcPeeringConnectionOptionsResponseType modifyVpcPeeringConnectionOptions(ModifyVpcPeeringConnectionOptionsType request) throws EucalyptusCloudException { ModifyVpcPeeringConnectionOptionsResponseType reply = request.getReply( ); return reply; } public DescribeSecurityGroupReferencesResponseType describeSecurityGroupReferences(DescribeSecurityGroupReferencesType request) throws EucalyptusCloudException { DescribeSecurityGroupReferencesResponseType reply = request.getReply( ); return reply; } public DescribeStaleSecurityGroupsResponseType describeStaleSecurityGroups(DescribeStaleSecurityGroupsType request) throws EucalyptusCloudException { DescribeStaleSecurityGroupsResponseType reply = request.getReply( ); return reply; } public DescribeVpcsResponseType describeVpcs( final DescribeVpcsType request ) throws EucalyptusCloudException { final DescribeVpcsResponseType reply = request.getReply( ); describe( Identifier.vpc, request.vpcIds( ), request.getFilterSet( ), Vpc.class, VpcType.class, reply.getVpcSet( ).getItem( ), VpcType.id( ), vpcs ); return reply; } public DescribeVpnConnectionsResponseType describeVpnConnections(DescribeVpnConnectionsType request) throws EucalyptusCloudException { DescribeVpnConnectionsResponseType reply = request.getReply( ); return reply; } public DescribeVpnGatewaysResponseType describeVpnGateways(DescribeVpnGatewaysType request) throws EucalyptusCloudException { DescribeVpnGatewaysResponseType reply = request.getReply( ); return reply; } public DescribeMovingAddressesResponseType describeMovingAddresses( DescribeMovingAddressesType request ) { return request.getReply( ); } public MoveAddressToVpcResponseType moveAddressToVpc( MoveAddressToVpcType request ) { return request.getReply( ); } public RestoreAddressToClassicResponseType restoreAddressToClassic( RestoreAddressToClassicType request ) { return request.getReply( ); } public AttachClassicLinkVpcResponseType attachClassicLinkVpc( AttachClassicLinkVpcType request ) { return request.getReply( ); } public DescribeClassicLinkInstancesResponseType describeClassicLinkInstances( DescribeClassicLinkInstancesType request ) { return request.getReply( ); } public DescribeVpcClassicLinkResponseType describeVpcClassicLink( DescribeVpcClassicLinkType request ) { return request.getReply( ); } public DetachClassicLinkVpcResponseType detachClassicLinkVpc( DetachClassicLinkVpcType request ) { return request.getReply( ); } public DisableVpcClassicLinkResponseType disableVpcClassicLink( DisableVpcClassicLinkType request ) { return request.getReply( ); } public EnableVpcClassicLinkResponseType enableVpcClassicLink( EnableVpcClassicLinkType request ) { return request.getReply( ); } public DescribeVpcClassicLinkDnsSupportResponseType describeVpcClassicLinkDnsSupport( DescribeVpcClassicLinkDnsSupportType request ) { return request.getReply( ); } public DisableVpcClassicLinkDnsSupportResponseType disableVpcClassicLinkDnsSupport( DisableVpcClassicLinkDnsSupportType request ) { return request.getReply( ); } public EnableVpcClassicLinkDnsSupportResponseType enableVpcClassicLinkDnsSupport( EnableVpcClassicLinkDnsSupportType request ) { return request.getReply( ); } public CreateVpcEndpointResponseType createVpcEndpoint( CreateVpcEndpointType request ) { return request.getReply( ); } public DeleteVpcEndpointsResponseType deleteVpcEndpoints( DeleteVpcEndpointsType request ) { return request.getReply( ); } public DescribePrefixListsResponseType describePrefixLists( DescribePrefixListsType request ) { return request.getReply( ); } public DescribeVpcEndpointServicesResponseType describeVpcEndpointServices( DescribeVpcEndpointServicesType request ) { return request.getReply( ); } public DescribeVpcEndpointsResponseType describeVpcEndpoints( DescribeVpcEndpointsType request ) { return request.getReply( ); } public ModifyVpcEndpointResponseType modifyVpcEndpoint( ModifyVpcEndpointType request ) { return request.getReply( ); } public CreateFlowLogsResponseType createFlowLogs( final CreateFlowLogsType request ) { return request.getReply( ); } public DeleteFlowLogsResponseType deleteFlowLogs( final DeleteFlowLogsType request ) { return request.getReply( ); } public DescribeFlowLogsResponseType describeFlowLogs( final DescribeFlowLogsType request ) { return request.getReply( ); } public DescribeIdentityIdFormatResponseType describeIdentityIdFormat( final DescribeIdentityIdFormatType request ) throws EucalyptusCloudException { final Context context = checkAuthorized( ); final DescribeIdentityIdFormatResponseType response = request.getReply( ); final Pair<IdType,String> identity = verifyIdentity( context.getAccountNumber( ), request.getPrincipalArn( ), false ); final Optional<String> resource = Optional.fromNullable( verifyIdentifierResource( request.getResource( ) ) ); response.setStatuses( Lists.newArrayList( Iterables.transform( IdentityIdFormats.listIdFormatsWithDefaults( context.getAccountNumber( ), identity.getLeft( ), identity.getRight( ), resource.transform( FUtils.valueOfFunction( IdResource.class ) ) ), TypeMappers.lookup( IdentityIdFormat.class, IdFormatItemType.class ) ) ) ); return response; } public ModifyIdentityIdFormatResponseType modifyIdentityIdFormat( final ModifyIdentityIdFormatType request ) throws EucalyptusCloudException { final ModifyIdentityIdFormatResponseType response = request.getReply( ); final Context context = checkAuthorized( ); final Pair<IdType,String> identity = verifyIdentity( context.getAccountNumber( ), request.getPrincipalArn( ), true ); final Optional<String> resource = Optional.fromNullable( verifyIdentifierResource( request.getResource( ) ) ); final Boolean useLongIds = request.getUseLongIds( ); if ( !IdentityIdFormats.saveIdFormat( context.getAccountNumber( ), identity.getLeft( ), identity.getRight( ), IdResource.valueOf( resource.get( ) ), useLongIds ) ) { response.markFailed( ); } return response; } public DescribeIdFormatResponseType describeIdFormat( final DescribeIdFormatType request ) throws EucalyptusCloudException { final Context context = checkAuthorized( ); final DescribeIdFormatResponseType response = request.getReply( ); final Pair<IdType,String> identity = getRequestIdentity( context ); final Optional<String> resource = Optional.fromNullable( verifyIdentifierResource( request.getResource( ) ) ); response.setStatuses( Lists.newArrayList( Iterables.transform( IdentityIdFormats.listIdFormatsWithDefaults( context.getAccountNumber( ), identity.getLeft( ), identity.getRight( ), resource.transform( FUtils.valueOfFunction( IdResource.class ) ) ), TypeMappers.lookup( IdentityIdFormat.class, IdFormatItemType.class ) ) ) ); return response; } public ModifyIdFormatResponseType modifyIdFormat( final ModifyIdFormatType request ) throws EucalyptusCloudException { final ModifyIdFormatResponseType response = request.getReply( ); final Context context = checkAuthorized( ); final Pair<IdType,String> identity = getRequestIdentity( context ); final Optional<String> resource = Optional.fromNullable( verifyIdentifierResource( request.getResource( ) ) ); final Boolean useLongIds = request.getUseLongIds( ); if ( !IdentityIdFormats.saveIdFormat( context.getAccountNumber( ), identity.getLeft( ), identity.getRight( ), IdResource.valueOf( resource.get( ) ), useLongIds ) ) { response.markFailed( ); } return response; } public AllocateHostsResponseType allocateHosts( final AllocateHostsType request ) throws EucalyptusCloudException { final AllocateHostsResponseType response = request.getReply( ); return response; } public DescribeHostReservationOfferingsResponseType describeHostReservationOfferings( final DescribeHostReservationOfferingsType request ) throws EucalyptusCloudException { final DescribeHostReservationOfferingsResponseType response = request.getReply( ); return response; } public DescribeHostReservationsResponseType describeHostReservations( final DescribeHostReservationsType request ) throws EucalyptusCloudException { final DescribeHostReservationsResponseType response = request.getReply( ); return response; } public DescribeHostsResponseType describeHosts( final DescribeHostsType request ) throws EucalyptusCloudException { final DescribeHostsResponseType response = request.getReply( ); return response; } public GetHostReservationPurchasePreviewResponseType getHostReservationPurchasePreview( final GetHostReservationPurchasePreviewType request ) throws EucalyptusCloudException { final GetHostReservationPurchasePreviewResponseType response = request.getReply( ); return response; } public ModifyHostsResponseType modifyHosts( final ModifyHostsType request ) throws EucalyptusCloudException { final ModifyHostsResponseType response = request.getReply( ); return response; } public PurchaseHostReservationResponseType purchaseHostReservation( final PurchaseHostReservationType request ) throws EucalyptusCloudException { final PurchaseHostReservationResponseType response = request.getReply( ); return response; } public ReleaseHostsResponseType releaseHosts( final ReleaseHostsType request ) throws EucalyptusCloudException { final ReleaseHostsResponseType response = request.getReply( ); return response; } public DescribeScheduledInstanceAvailabilityResponseType describeScheduledInstanceAvailability( final DescribeScheduledInstanceAvailabilityType request ) throws EucalyptusCloudException { final DescribeScheduledInstanceAvailabilityResponseType response = request.getReply( ); return response; } public DescribeScheduledInstancesResponseType describeScheduledInstances( final DescribeScheduledInstancesType request ) throws EucalyptusCloudException { final DescribeScheduledInstancesResponseType response = request.getReply( ); return response; } public PurchaseScheduledInstancesResponseType purchaseScheduledInstances( final PurchaseScheduledInstancesType request ) throws EucalyptusCloudException { final PurchaseScheduledInstancesResponseType response = request.getReply( ); return response; } public RunScheduledInstancesResponseType runScheduledInstances( final RunScheduledInstancesType request ) throws EucalyptusCloudException { final RunScheduledInstancesResponseType response = request.getReply( ); return response; } public AssignIpv6AddressesResponseType assignIpv6AddressesType( final AssignIpv6AddressesType request ) throws EucalyptusCloudException { final AssignIpv6AddressesResponseType response = request.getReply( ); return response; } public AssociateSubnetCidrBlockResponseType associateSubnetCidrBlock( final AssociateSubnetCidrBlockType request ) throws EucalyptusCloudException { final AssociateSubnetCidrBlockResponseType response = request.getReply( ); return response; } public AssociateVpcCidrBlockResponseType associateVpcCidrBlock( final AssociateVpcCidrBlockType request ) throws EucalyptusCloudException { final AssociateVpcCidrBlockResponseType response = request.getReply( ); return response; } public CreateEgressOnlyInternetGatewayResponseType createEgressOnlyInternetGateway( final CreateEgressOnlyInternetGatewayType request ) throws EucalyptusCloudException { final CreateEgressOnlyInternetGatewayResponseType response = request.getReply( ); return response; } public DeleteEgressOnlyInternetGatewayResponseType deleteEgressOnlyInternetGateway( final DeleteEgressOnlyInternetGatewayType request ) throws EucalyptusCloudException { final DeleteEgressOnlyInternetGatewayResponseType response = request.getReply( ); return response; } public DescribeEgressOnlyInternetGatewaysResponseType describeEgressOnlyInternetGateways( final DescribeEgressOnlyInternetGatewaysType request ) throws EucalyptusCloudException { final DescribeEgressOnlyInternetGatewaysResponseType response = request.getReply( ); return response; } public DisassociateSubnetCidrBlockResponseType disassociateSubnetCidrBlock( final DisassociateSubnetCidrBlockType request ) throws EucalyptusCloudException { final DisassociateSubnetCidrBlockResponseType response = request.getReply( ); return response; } public DisassociateVpcCidrBlockResponseType disassociateVpcCidrBlock( final DisassociateVpcCidrBlockType request ) throws EucalyptusCloudException { final DisassociateVpcCidrBlockResponseType response = request.getReply( ); return response; } public UnassignIpv6AddressesResponseType unassignIpv6Addresses( final UnassignIpv6AddressesType request ) throws EucalyptusCloudException { final UnassignIpv6AddressesResponseType response = request.getReply( ); return response; } public AssociateIamInstanceProfileResponseType associateIamInstanceProfile( final AssociateIamInstanceProfileType request ) throws EucalyptusCloudException { final AssociateIamInstanceProfileResponseType response = request.getReply( ); return response; } public DescribeIamInstanceProfileAssociationsResponseType describeIamInstanceProfileAssociations( final DescribeIamInstanceProfileAssociationsType request ) throws EucalyptusCloudException { final DescribeIamInstanceProfileAssociationsResponseType response = request.getReply( ); return response; } public DisassociateIamInstanceProfileResponseType disassociateIamInstanceProfile( final DisassociateIamInstanceProfileType request ) throws EucalyptusCloudException { final DisassociateIamInstanceProfileResponseType response = request.getReply( ); return response; } public ReplaceIamInstanceProfileAssociationResponseType replaceIamInstanceProfileAssociation( final ReplaceIamInstanceProfileAssociationType request ) throws EucalyptusCloudException { final ReplaceIamInstanceProfileAssociationResponseType response = request.getReply( ); return response; } public ComputeMessage proxy( final ComputeMessage request ) throws EucalyptusCloudException { // Dispatch try { BaseMessage backendRequest = BaseMessages.deepCopy( request, getBackendMessageClass( request ) ); final BaseMessage backendResponse = send( backendRequest ); final ComputeMessage response = (ComputeMessage) BaseMessages.deepCopy( backendResponse, request.getReply( ).getClass( ) ); response.setCorrelationId( request.getCorrelationId() ); return response; } catch ( Exception e ) { handleServiceException( e ); Exceptions.findAndRethrow( e, EucalyptusWebServiceException.class, EucalyptusCloudException.class ); throw new EucalyptusCloudException( e ); } } private static <AP extends AbstractPersistent & CloudMetadata, AT> void describe( final Identifier identifier, final Collection<String> ids, final Collection<com.eucalyptus.compute.common.Filter> filters, final Class<AP> persistent, final Class<AT> api, final List<AT> results, final Lister<AP> lister ) throws EucalyptusCloudException { describe( identifier, ids, filters, persistent, api, results, Callbacks.<AccountFullName>noop( ), lister ); } private static <AP extends AbstractPersistent & CloudMetadata, AT> void describe( final Identifier identifier, final Collection<String> ids, final Collection<com.eucalyptus.compute.common.Filter> filters, final Class<AP> persistent, final Class<AT> api, final List<AT> results, final Callback<AccountFullName> resultsDecorator, final Lister<AP> lister ) throws EucalyptusCloudException { final boolean showAll = ids.remove( "verbose" ); final List<String> normalizedIds = identifier.normalize( ids ); final Context ctx = Contexts.lookup( ); final AccountFullName accountFullName = ctx.getUserFullName( ).asAccountFullName( ); final OwnerFullName ownerFullName = ctx.isAdministrator( ) && ( showAll || !normalizedIds.isEmpty( ) ) ? null : accountFullName; final Filter filter = Filters.generate( filters, persistent ); final Filter persistenceFilter = getPersistenceFilter( persistent, normalizedIds, identifier.getFilterName( ), filter ); final Predicate<? super AP> requestedAndAccessible = CloudMetadatas.filteringFor( persistent ) .byId( normalizedIds ) .byPredicate( filter.asPredicate( ) ) .byPrivileges() .buildPredicate(); try ( final TransactionResource tx = Entities.readOnlyDistinctTransactionFor( persistent ) ) { results.addAll( lister.list( ownerFullName, persistenceFilter.asCriterion( ), persistenceFilter.getAliases( ), Predicates.and( new TrackingPredicate<>( normalizedIds ), requestedAndAccessible ), TypeMappers.lookup( persistent, api ) ) ); identifier.errorIfNotFound( normalizedIds ); resultsDecorator.fire( accountFullName ); } catch ( Exception e ) { throw handleException( e ); } } private static <AP extends AbstractPersistent & CloudMetadata, AT extends VpcTagged> void describe( final Identifier identifier, final Collection<String> ids, final Collection<com.eucalyptus.compute.common.Filter> filters, final Class<AP> persistent, final Class<AT> api, final List<AT> results, final Function<AT,String> idFunction, final Lister<AP> lister ) throws EucalyptusCloudException { describe( identifier, ids, filters, persistent, api, results, new Callback<AccountFullName>( ) { @Override public void fire( final AccountFullName accountFullName ) { populateTags( accountFullName, persistent, results, idFunction ); } }, lister ); } private static <AP extends AbstractPersistent> Filter getPersistenceFilter( final Class<AP> persistent, final Collection<String> identifiers, final String identifierFilterName, final Filter filter ) throws InvalidFilterException { return getPersistenceFilter( persistent, Filters.DEFAULT_FILTERS, identifiers, identifierFilterName, filter ); } private static <AP extends AbstractPersistent> Filter getPersistenceFilter( final Class<AP> persistent, final String qualifier, final Collection<String> identifiers, final String identifierFilterName, final Filter filter ) throws InvalidFilterException { return !identifiers.isEmpty( ) ? Filters.generateFor( Collections.<com.eucalyptus.compute.common.Filter>emptySet( ), persistent, qualifier ).withOptionalInternalFilter( identifierFilterName, identifiers ).generate( ) : filter; } private static Context checkAuthorized( ) throws EucalyptusCloudException { final Context ctx = Contexts.lookup( ); final User requestUser = ctx.getUser( ); final AuthContextSupplier requestUserSupplier = ctx.getAuthContext( ); if ( !Permissions.isAuthorized( PolicySpec.VENDOR_EC2, "", "", null, getIamActionByMessageType( ), requestUserSupplier ) ) { throw new ComputeServiceAuthorizationException( "UnauthorizedOperation", "You are not authorized to perform this operation." ); } return ctx; } private static boolean canModifyImage( final ImageInfo imgInfo ) { final Context ctx = Contexts.lookup( ); final String requestAccountId = ctx.getUserFullName( ).getAccountNumber( ); return ( ctx.isAdministrator( ) || imgInfo.getOwnerAccountNumber( ).equals( requestAccountId ) ) && RestrictedTypes.filterPrivileged( ).apply( imgInfo ); } private static <VT extends VpcTagged> void populateTags( final AccountFullName accountFullName, final Class<? extends CloudMetadata> resourceType, final List<? extends VT> items, final Function<? super VT, String> idFunction ) { final Map<String,List<Tag>> tagsMap = TagSupport.forResourceClass( resourceType ) .getResourceTagMap( accountFullName, Iterables.transform( items, idFunction ) ); for ( final VT item : items ) { final ResourceTagSetType tags = new ResourceTagSetType( ); Tags.addFromTags( tags.getItem(), ResourceTagSetItemType.class, tagsMap.get( idFunction.apply( item ) ) ); if ( !tags.getItem().isEmpty() ) { item.setTagSet( tags ); } } } private static Pair<IdType,String> getRequestIdentity( final Context context ) { final UserPrincipal principal = context.getUser( ); return Accounts.isRoleIdentifier( principal.getAuthenticatedId( ) ) ? Pair.pair( IdType.role, Accounts.getAuthenticatedFullName( principal ) ): Pair.pair( IdType.user, Accounts.getUserFullName( principal ) ); } private static Pair<IdType,String> verifyIdentity( final String accountNumber, final String arn, final boolean checkExists ) throws ComputeServiceClientException { final Optional<Pair<IdType,String>> identityOption = IdentityIdFormats.tryParseIdentity( accountNumber, arn ).transform( Pair.right( ) ); if ( !identityOption.isPresent( ) ) { throw new ComputeServiceClientException( "InvalidTargetArn.Unknown", "Invalid TargetArn: " + arn ); } final Pair<IdType,String> identity = identityOption.get( ); if ( checkExists ) { try { final String name = Accounts.getNameFromFullName( identity.getRight( ) ); switch ( identity.getLeft( ) ) { case user: Accounts.lookupPrincipalByAccountNumberAndUsername( accountNumber, name ); break; case role: Accounts.lookupRoleByName( accountNumber, name ); break; } } catch ( final AuthException e ) { throw new ComputeServiceClientException( "InvalidTargetArn.Unknown", "Invalid TargetArn: " + arn ); } } return identity; } private static String verifyIdentifierResource( final String resource ) throws ComputeServiceClientException { if ( resource != null && !IdentityIdFormats.isValidResource( resource ) ) { throw new ComputeServiceClientException( "InvalidParameterValue", "Invalid resource type: " + resource ); } return resource; } private static String imageIdentifier( final String identifier ) throws EucalyptusCloudException { if( !CloudMetadatas.isImageIdentifier( identifier ) ) throw new EucalyptusCloudException( "Invalid id: " + "\"" + identifier + "\"" ); return normalizeImageIdentifier( identifier ); } private static String normalizeInstanceIdentifier( final String identifier ) throws EucalyptusCloudException { try { return ResourceIdentifiers.parse( VmInstance.ID_PREFIX, identifier ).getIdentifier( ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidInstanceID.Malformed", "Invalid id: \""+e.getIdentifier()+"\"" ); } } private static List<String> normalizeInstanceIdentifiers( final List<String> identifiers ) throws EucalyptusCloudException { try { return ResourceIdentifiers.normalize( VmInstance.ID_PREFIX, identifiers ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidInstanceID.Malformed", "Invalid id: \""+e.getIdentifier()+"\"" ); } } private static String normalizeIdentifier( final String identifier, final String prefix, final boolean required, final String message ) throws ComputeServiceClientException { try { return Strings.emptyToNull( identifier ) == null && !required ? null : ResourceIdentifiers.parse( prefix, identifier ).getIdentifier( ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidParameterValue", String.format( message, e.getIdentifier( ) ) ); } } private static String normalizeImageIdentifier( final String identifier ) throws EucalyptusCloudException { return normalizeIdentifier( identifier, null, true, "Value (%s) for parameter image is invalid." ); } @Nullable private static String normalizeOptionalImageIdentifier( final String identifier ) throws EucalyptusCloudException { return normalizeIdentifier( identifier, null, false, "Value (%s) for parameter image is invalid." ); } private static List<String> normalizeImageIdentifiers( final List<String> identifiers ) throws EucalyptusCloudException { try { return ResourceIdentifiers.normalize( identifiers ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidParameterValue", "Value ("+e.getIdentifier()+") for parameter images is invalid." ); } } private static String normalizeVolumeIdentifier( final String identifier ) throws EucalyptusCloudException { try { return ResourceIdentifiers.parse( Volume.ID_PREFIX, identifier ).getIdentifier( ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidParameterValue", "Value (%s) for parameter volumeId is invalid." ); } } private static List<String> normalizeVolumeIdentifiers( final List<String> identifiers ) throws EucalyptusCloudException { try { return ResourceIdentifiers.normalize( Volume.ID_PREFIX, identifiers ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidParameterValue", "Value ("+e.getIdentifier()+") for parameter volumes is invalid. Expected: 'vol-...'." ); } } private static String normalizeSnapshotIdentifier( final String identifier ) throws EucalyptusCloudException { return normalizeIdentifier( identifier, Snapshot.ID_PREFIX, true, "Value (%s) for parameter snapshotId is invalid. Expected: 'snap-...'." ); } private static List<String> normalizeSnapshotIdentifiers( final List<String> identifiers ) throws EucalyptusCloudException { try { return ResourceIdentifiers.normalize( Snapshot.ID_PREFIX, identifiers ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidParameterValue", "Value ("+e.getIdentifier()+") for parameter snapshots is invalid. Expected: 'snap-...'." ); } } private enum Identifier { acl( "networkAcl", "network-acl-id", "InvalidNetworkAclID.NotFound" ), dopt( "DHCPOption", "dhcp-options-id", "InvalidDhcpOptionID.NotFound" ), eni( "networkInterface", "network-interface-id", "InvalidNetworkInterfaceID.NotFound" ), igw( "internetGateway", "internet-gateway-id", "InvalidInternetGatewayID.NotFound" ), nat( "natGateway", "natGateways", "nat-gateway-id", "NatGatewayNotFound", "NatGatewayMalformed" ), rtb( "routeTable", "route-table-id", "InvalidRouteTableID.NotFound" ), subnet( "subnet", "subnet-id", "InvalidSubnetID.NotFound" ), vpc( "vpc", "vpc-id", "InvalidVpcID.NotFound" ), ; private final String code; private final String defaultParameter; private final String defaultListParameter; private final String filterName; private final String notFoundErrorCode; Identifier( final String defaultParameter, final String filterName, final String notFoundErrorCode ) { this( defaultParameter, defaultParameter + "s", filterName, notFoundErrorCode ); } Identifier( final String defaultParameter, final String defaultListParameter, final String filterName, final String notFoundErrorCode ) { this( defaultParameter, defaultListParameter, filterName, notFoundErrorCode, "InvalidParameterValue" ); } Identifier( final String defaultParameter, final String defaultListParameter, final String filterName, final String notFoundErrorCode, final String malformedErrorCode ) { this.defaultParameter = defaultParameter; this.defaultListParameter = defaultListParameter; this.filterName = filterName; this.notFoundErrorCode = notFoundErrorCode; this.code = malformedErrorCode; } public String getFilterName( ) { return filterName; } public String generate( ) { return ResourceIdentifiers.generateString( name( ) ); } public String normalize( final String identifier ) throws EucalyptusCloudException { return normalize( identifier, defaultParameter ); } public String normalize( final String identifier, final String parameter ) throws EucalyptusCloudException { return normalize( Collections.singleton( identifier ), parameter ).get( 0 ); } public List<String> normalize( final Iterable<String> identifiers ) throws EucalyptusCloudException { return normalize( identifiers, defaultListParameter ); } public List<String> normalize( final Iterable<String> identifiers, final String parameter ) throws EucalyptusCloudException { try { return ResourceIdentifiers.normalize( name( ), identifiers ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( code, "Value ("+e.getIdentifier()+") for parameter "+parameter+" is invalid. Expected: '"+name()+"-...'." ); } } public void errorIfNotFound( final Iterable<String> identifiers ) throws EucalyptusCloudException { ComputeService.errorIfNotFound( notFoundErrorCode, defaultParameter + " ID", identifiers ); if ( Iterables.size( identifiers ) == 1 ) { throw new ComputeServiceClientException( notFoundErrorCode, "The "+defaultParameter+" ID '"+Iterables.getOnlyElement( identifiers )+"' does not exist" ); } else if ( !Iterables.isEmpty( identifiers ) ) { final Iterable<String> quotedIdentifiers = Iterables.transform( identifiers, Functions.compose( append( "'" ), prepend( "'" ) ) ); throw new ComputeServiceClientException( notFoundErrorCode, "The "+defaultParameter+" IDs "+ Joiner.on( ", ").join( quotedIdentifiers ) +" do not exist" ); } } } private static void errorIfNotFound( final String notFoundErrorCode, final String identifierDescription, final Iterable<String> identifiers ) throws EucalyptusCloudException { if ( Iterables.size( identifiers ) == 1 ) { throw new ComputeServiceClientException( notFoundErrorCode, "The "+identifierDescription+" '"+Iterables.getOnlyElement( identifiers )+"' does not exist" ); } else if ( !Iterables.isEmpty( identifiers ) ) { final Iterable<String> quotedIdentifiers = Iterables.transform( identifiers, Functions.compose( append( "'" ), prepend( "'" ) ) ); throw new ComputeServiceClientException( notFoundErrorCode, "The "+identifierDescription+"s "+ Joiner.on( ", ").join( quotedIdentifiers ) +" do not exist" ); } } private static List<String> normalizeGroupIdentifiers( final List<String> identifiers ) throws EucalyptusCloudException { try { return ResourceIdentifiers.normalize( NetworkGroup.ID_PREFIX, identifiers ); } catch ( final InvalidResourceIdentifier e ) { throw new ComputeServiceClientException( "InvalidGroupId.Malformed", "Invalid id: \""+e.getIdentifier()+"\" (expecting \"sg-...\")" ); } } private enum SecurityGroupItemToGroupId implements Function<SecurityGroupItemType, String> { INSTANCE { @Override public String apply( SecurityGroupItemType securityGroupItemType ) { return securityGroupItemType.getGroupId(); } } } private static Class getBackendMessageClass( final BaseMessage request ) throws BindingException { final Binding binding = BindingManager.getDefaultBinding( ); return binding.getElementClass( "Eucalyptus." + request.getClass( ).getSimpleName( ) ); } private static BaseMessage send( final BaseMessage request ) throws Exception { try { return AsyncRequests.sendSyncWithCurrentIdentity( Topology.lookup( Eucalyptus.class ), request ); } catch ( final NoSuchElementException e ) { throw new ComputeServiceUnavailableException( "Service Unavailable" ); } catch ( final FailedRequestException e ) { if ( request.getReply( ).getClass( ).isInstance( e.getRequest( ) ) ) { return e.getRequest( ); } throw e.getRequest( ) == null ? e : new ComputeServiceException( "InternalError", "Internal error " + e.getRequest().getClass().getSimpleName() + ":false" ); } } @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" ) private void handleServiceException( final Exception e ) throws EucalyptusCloudException { final Optional<AsyncWebServiceError> serviceErrorOption = AsyncExceptions.asWebServiceError( e ); if ( serviceErrorOption.isPresent( ) ) { final AsyncWebServiceError serviceError = serviceErrorOption.get( ); switch( serviceError.getHttpErrorCode( ) ) { case 400: throw new ComputeServiceClientException( serviceError.getCode(), serviceError.getMessage( ) ); case 403: throw new ComputeServiceAuthorizationException( serviceError.getCode(), serviceError.getMessage( ) ); case 503: throw new ComputeServiceUnavailableException( serviceError.getMessage( ) ); default: throw new ComputeServiceException( serviceError.getCode( ), serviceError.getMessage( ) ); } } } /** * Method always throws, signature allows use of "throw handleException ..." */ private static ComputeServiceException handleException( final Exception e ) throws ComputeServiceException { final ComputeServiceException cause = Exceptions.findCause( e, ComputeServiceException.class ); if ( cause != null ) { throw cause; } final AuthQuotaException quotaCause = Exceptions.findCause( e, AuthQuotaException.class ); if ( quotaCause != null ) { String code = "ResourceLimitExceeded"; switch( quotaCause.getType( ) ) { case "vpc": code = "VpcLimitExceeded"; break; case "internet-gateway": code = "InternetGatewayLimitExceeded"; break; } throw new ComputeServiceClientException( code, "Request would exceed quota for type: " + quotaCause.getType() ); } LOG.error( e, e ); final ComputeServiceException exception = new ComputeServiceException( "InternalError", String.valueOf(e.getMessage()) ); if ( Contexts.lookup( ).hasAdministrativePrivileges() ) { exception.initCause( e ); } throw exception; } private static class TrackingPredicate<T extends RestrictedType> implements Predicate<T> { private final Function<? super T,String> idFunction; private final Collection<String> identifiers; public TrackingPredicate( final Collection<String> identifiers ) { this( CloudMetadatas.toDisplayName( ), identifiers ); } public TrackingPredicate( final Function<? super T, String> idFunction, final Collection<String> identifiers ) { this.idFunction = idFunction; this.identifiers = identifiers; } @Override public boolean apply( @Nullable final T t ) { if ( t != null ) { //noinspection StatementWithEmptyBody while ( identifiers.remove( idFunction.apply( t ) ) ); } return true; } } }