/*************************************************************************
* Copyright 2009-2015 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.auth.euare;
import java.io.StringWriter;
import java.net.URI;
import java.util.Set;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.log4j.Logger;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import com.eucalyptus.auth.euare.common.identity.Identity;
import com.eucalyptus.auth.euare.common.identity.IdentityMessage;
import com.eucalyptus.auth.euare.common.identity.TunnelActionResponseType;
import com.eucalyptus.auth.euare.common.identity.TunnelActionType;
import com.eucalyptus.auth.euare.identity.region.RegionInfo;
import com.eucalyptus.binding.Binding;
import com.eucalyptus.binding.BindingManager;
import com.eucalyptus.binding.HoldMe;
import com.eucalyptus.component.ComponentIds;
import com.eucalyptus.component.EphemeralConfiguration;
import com.eucalyptus.component.ServiceConfiguration;
import com.eucalyptus.component.annotation.ComponentNamed;
import com.eucalyptus.context.Contexts;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.LockResource;
import com.eucalyptus.util.async.AsyncExceptions;
import com.eucalyptus.util.async.AsyncExceptions.AsyncWebServiceError;
import com.eucalyptus.util.async.AsyncRequests;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
/**
*
*/
@ComponentNamed
public class EuareRemoteRegionService {
private static final Logger logger = Logger.getLogger( EuareRemoteRegionService.class );
public EuareMessage callRemote( final EuareMessage euareRequest ) throws EucalyptusCloudException {
final Optional<RegionInfo> regionInfo = EuareRemoteRegionFilter.getRegion( euareRequest );
final String previousUserId = euareRequest.getUserId( );
final Binding binding = BindingManager.getDefaultBinding( );
try {
euareRequest.setUserId( Contexts.lookup( ).getUser( ).getAuthenticatedId( ) );
final StringWriter writer = new StringWriter();
try ( final LockResource lock = LockResource.lock( HoldMe.canHas ) ) {
final OMElement message = binding.toOM( euareRequest );
final OMOutputFormat format = new OMOutputFormat();
format.setIgnoreXMLDeclaration( true );
message.serialize( writer );
}
final TunnelActionType tunnelAction = new TunnelActionType( );
tunnelAction.setContent( writer.toString( ) );
final TunnelActionResponseType tunnelActionResponse = send( regionInfo, tunnelAction );
final String responseContent = tunnelActionResponse.getTunnelActionResult( ).getContent( );
final EuareMessage euareResponse; //TODO:STEVE: move this message marshalling to a helper (BaseMessages? also IdentityService#tunnelAction)
try ( final LockResource lock = LockResource.lock( HoldMe.canHas ) ) {
final StAXOMBuilder omBuilder = HoldMe.getStAXOMBuilder( HoldMe.getXMLStreamReader( responseContent ) );
final OMElement message = omBuilder.getDocumentElement( );
final Class<?> messageType = binding.getElementClass( message.getLocalName( ) );
euareResponse = (EuareMessage) binding.fromOM( message, messageType ); //TODO:STEVE: allow for (subminor?) version differences
}
euareResponse.setCorrelationId( euareRequest.getCorrelationId( ) );
return euareResponse;
} catch ( Exception e ) {
final Optional<AsyncWebServiceError> error = AsyncExceptions.asWebServiceError( e );
if ( error.isPresent( ) ) {
final AsyncWebServiceError webServiceError = error.get( );
throw new EuareException( HttpResponseStatus.valueOf( webServiceError.getHttpErrorCode( ) ), webServiceError.getCode( ), webServiceError.getMessage( ) );
}
throw new EucalyptusCloudException( e );
} finally {
euareRequest.setUserId( previousUserId );
}
}
private <R extends IdentityMessage> R send( //TODO:STEVE: move send to a helper (also RemoteIdentityProvider#send)
final Optional<RegionInfo> region,
final IdentityMessage request ) throws Exception {
final Optional<Set<String>> endpoints = region.transform( RegionInfo.serviceEndpoints( "identity" ) );
final ServiceConfiguration config = new EphemeralConfiguration(
ComponentIds.lookup( Identity.class ),
"identity",
"identity",
URI.create( Iterables.get( endpoints.get( ), 0 ) ) ); //TODO:STEVE: endpoint handling
return AsyncRequests.sendSync( config, request );
}
}