From f45886abed5f04728561d5c8f97423a8036806fc Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 30 Aug 2016 18:02:43 +0200 Subject: Implement global image exchange with satellite servers --- .../thrift/server/MasterServerHandler.java | 160 ++++++++++++++++----- 1 file changed, 125 insertions(+), 35 deletions(-) (limited to 'src/main/java/org/openslx/imagemaster/thrift/server/MasterServerHandler.java') diff --git a/src/main/java/org/openslx/imagemaster/thrift/server/MasterServerHandler.java b/src/main/java/org/openslx/imagemaster/thrift/server/MasterServerHandler.java index 60f4ccb..3bdbd3f 100644 --- a/src/main/java/org/openslx/imagemaster/thrift/server/MasterServerHandler.java +++ b/src/main/java/org/openslx/imagemaster/thrift/server/MasterServerHandler.java @@ -13,7 +13,9 @@ import org.apache.log4j.Logger; import org.apache.thrift.TException; import org.openslx.bwlp.thrift.iface.AuthorizationError; import org.openslx.bwlp.thrift.iface.ClientSessionData; +import org.openslx.bwlp.thrift.iface.ImageDetailsRead; import org.openslx.bwlp.thrift.iface.ImagePublishData; +import org.openslx.bwlp.thrift.iface.ImageSummaryRead; import org.openslx.bwlp.thrift.iface.InvocationError; import org.openslx.bwlp.thrift.iface.MasterServer; import org.openslx.bwlp.thrift.iface.MasterSoftware; @@ -29,9 +31,11 @@ import org.openslx.bwlp.thrift.iface.TInvocationException; import org.openslx.bwlp.thrift.iface.TNotFoundException; import org.openslx.bwlp.thrift.iface.TTransferRejectedException; import org.openslx.bwlp.thrift.iface.TransferInformation; +import org.openslx.bwlp.thrift.iface.TransferStatus; import org.openslx.bwlp.thrift.iface.UserInfo; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.encryption.AsymKeyHolder; +import org.openslx.filetransfer.util.ChunkList; import org.openslx.filetransfer.util.FileChunk; import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.db.Database; @@ -43,7 +47,6 @@ import org.openslx.imagemaster.db.mappers.DbPendingSatellite; import org.openslx.imagemaster.db.mappers.DbSatellite; import org.openslx.imagemaster.db.mappers.DbUser; import org.openslx.imagemaster.db.models.LocalSatellite; -import org.openslx.imagemaster.db.models.LocalUser; import org.openslx.imagemaster.serverconnection.ConnectionHandler; import org.openslx.imagemaster.serverconnection.IncomingTransfer; import org.openslx.imagemaster.serversession.ServerAuthenticator; @@ -52,7 +55,9 @@ import org.openslx.imagemaster.serversession.ServerSessionManager; import org.openslx.imagemaster.session.Authenticator; import org.openslx.imagemaster.session.Session; import org.openslx.imagemaster.session.SessionManager; +import org.openslx.imagemaster.util.UserUtil; import org.openslx.imagemaster.util.Util; +import org.openslx.thrifthelper.ImagePublishDataEx; public class MasterServerHandler implements MasterServer.Iface { @@ -131,11 +136,33 @@ public class MasterServerHandler implements MasterServer.Iface } @Override - public List getPublicImages( String sessionId, int page ) + public List getPublicImages( String sessionId, int page ) throws TAuthorizationException, TInvocationException { - // TODO Auto-generated method stub - return null; + Session session = SessionManager.getSessionFromSessionId( sessionId ); + if ( session == null ) + throw new TAuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "Session ID not valid" ); + UserUtil.assertTutor( session.getUserInfo() ); + try { + return DbImage.getPublicList( page ); + } catch ( SQLException e ) { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database failure" ); + } + } + + @Override + public ImageDetailsRead getImageDetails( String sessionId, String imageBaseId ) + throws TAuthorizationException, TNotFoundException, TInvocationException + { + Session session = SessionManager.getSessionFromSessionId( sessionId ); + if ( session == null ) + throw new TAuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "Session ID not valid" ); + UserUtil.assertTutor( session.getUserInfo() ); + try { + return DbImage.getImageDetails( imageBaseId ); + } catch ( SQLException e ) { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database failure" ); + } } @Override @@ -214,8 +241,15 @@ public class MasterServerHandler implements MasterServer.Iface public ImagePublishData getImageData( String serverSessionId, String imageVersionId ) throws TAuthorizationException, TInvocationException, TNotFoundException { - // TODO Auto-generated method stub - return null; + Session session = SessionManager.getSessionFromSessionIdOrToken( serverSessionId ); + if ( session == null ) + throw new TAuthorizationException( AuthorizationError.INVALID_TOKEN, "Unknown session id/token" ); + UserUtil.assertTutor( session.getUserInfo() ); + try { + return DbImage.getImageVersion( imageVersionId ); + } catch ( SQLException e ) { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database error" ); + } } @Override @@ -226,6 +260,9 @@ public class MasterServerHandler implements MasterServer.Iface Session session = SessionManager.getSessionFromToken( userToken ); if ( session == null ) throw new TAuthorizationException( AuthorizationError.INVALID_TOKEN, "Given user token not known to the server" ); + UserUtil.assertTutor( session.getUserInfo() ); + img.owner = UserUtil.getFirstPublishingUser( img.owner, img.uploader, session.getUserInfo() ); + img.uploader = UserUtil.getFirstPublishingUserOrDummy( img.uploader, session.getUserInfo() ); // check image data if ( Util.isEmpty( img.imageName ) ) throw new TInvocationException( InvocationError.INVALID_DATA, "Image name not set" ); @@ -235,8 +272,10 @@ public class MasterServerHandler implements MasterServer.Iface throw new TInvocationException( InvocationError.MISSING_DATA, "ImagePublishData has invalid imageBaseId" ); if ( !Util.isUUID( img.imageVersionId ) ) throw new TInvocationException( InvocationError.MISSING_DATA, "ImagePublishData has invalid imageVersionId" ); - if ( img.user == null || img.user.userId == null ) - throw new TInvocationException( InvocationError.MISSING_DATA, "Missing user id" ); + if ( img.owner == null || img.owner.userId == null ) + throw new TInvocationException( InvocationError.MISSING_DATA, "Missing owner or owner is anonymous" ); + if ( img.uploader == null || img.uploader.userId == null ) + throw new TInvocationException( InvocationError.MISSING_DATA, "Missing uploader or uploader is anonymous" ); // check for complete block hash list boolean listComplete = false; if ( blockHashes != null && blockHashes.size() == FileChunk.fileSizeToChunkCount( img.fileSize ) ) { @@ -253,48 +292,53 @@ public class MasterServerHandler implements MasterServer.Iface // Check if an upload is already assigned IncomingTransfer existingUpload = ConnectionHandler.getExistingUpload( img, blockHashes ); if ( existingUpload != null ) { + LOGGER.info( "Satellite tried to register already existing upload for version " + img.imageVersionId + " - is " + + existingUpload.getId() ); return existingUpload.getTransferInfo(); } + // Check if version already exists + ImagePublishDataEx existing; + try { + existing = DbImage.getImageVersion( img.imageVersionId ); + if ( existing != null ) { + if ( existing.fileSize != img.fileSize ) + throw new TInvocationException( InvocationError.INVALID_DATA, "Image already exists; file size mismatch" ); + List existingHashes = DbImageBlock.getBlockHashes( img.imageVersionId ); + if ( !ChunkList.hashListsEqualBbBb( blockHashes, existingHashes ) ) + throw new TInvocationException( InvocationError.INVALID_DATA, "Image already exists; block hashes mismatch" ); + } + } catch ( SQLException e ) { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Internal database error" ); + } // No existing upload - create new one // checks that hit the db if ( !DbOsVirt.osExists( img.osId ) ) throw new TInvocationException( InvocationError.INVALID_DATA, "Content operating system not set" ); if ( !DbOsVirt.virtExists( img.virtId ) ) throw new TInvocationException( InvocationError.INVALID_DATA, "Content virtualizer system not set" ); - try { - LocalUser user = DbUser.forUserId( img.user.userId ); - if ( user == null ) { - user = DbUser.forUserId( session.getUserInfo().userId ); - if ( user != null ) { - img.user = user.toUserInfo(); - } - } - if ( user == null ) - throw new TInvocationException( InvocationError.UNKNOWN_USER, "Unknown user id " + img.user.userId ); - if ( user.isAnonymous() ) - throw new TInvocationException( InvocationError.UNKNOWN_USER, "The owner of the image does not participate in image exchange" ); - } catch ( SQLException e ) { - throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database error" ); - } // Make sure we have a destination to write to if ( !new File( Globals.getImageDir() ).isDirectory() ) throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Storage offline" ); // Try to register an upload - IncomingTransfer transfer = ConnectionHandler.registerUpload( img, blockHashes ); + IncomingTransfer transfer = ConnectionHandler.registerUpload( img, blockHashes, existing ); try { DbImage.createImageBase( img ); } catch ( TException t ) { transfer.cancel(); + ConnectionHandler.removeUpload( transfer ); throw t; } - try { - DbImage.createImageVersion( img, transfer.getRelativePath() ); - } catch ( SQLException e1 ) { - transfer.cancel(); - if ( Database.isDuplicateKeyException( e1 ) ) { - throw new TInvocationException( InvocationError.INVALID_DATA, "The image already exists on the server" ); - } else { - throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database error" ); + if ( existing == null ) { + try { + DbImage.createImageVersion( img, transfer.getRelativePath() ); + } catch ( SQLException e1 ) { + transfer.cancel(); + ConnectionHandler.removeUpload( transfer ); + if ( Database.isDuplicateKeyException( e1 ) ) { + throw new TInvocationException( InvocationError.INVALID_DATA, "The image already exists on the server" ); + } else { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database error" ); + } } } try { @@ -307,10 +351,27 @@ public class MasterServerHandler implements MasterServer.Iface @Override public TransferInformation downloadImage( String sessionId, String imageVersionId ) - throws TAuthorizationException, TInvocationException, TNotFoundException + throws TAuthorizationException, TInvocationException, TNotFoundException, TTransferRejectedException { - // TODO Auto-generated method stub - return null; + // Valid submit session? + Session session = SessionManager.getSessionFromToken( sessionId ); + if ( session == null ) + throw new TAuthorizationException( AuthorizationError.INVALID_TOKEN, "Given user token not known to the server" ); + UserUtil.assertTutor( session.getUserInfo() ); + ImagePublishDataEx img; + List blockHashes; + try { + img = DbImage.getImageVersion( imageVersionId ); + blockHashes = DbImageBlock.getBlockHashes( img.imageVersionId ); + } catch ( SQLException e ) { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database error" ); + } + if ( img == null || !img.exIsValid ) + throw new TNotFoundException(); + TransferInformation ti = ConnectionHandler.registerDownload( img ); + ti.machineDescription = img.machineDescription; + ti.blockHashes = blockHashes; + return ti; } @Override @@ -398,4 +459,33 @@ public class MasterServerHandler implements MasterServer.Iface return false; } + @Override + public TransferStatus queryUploadStatus( String uploadToken ) throws TInvalidTokenException + { + IncomingTransfer upload = ConnectionHandler.getUploadByToken( uploadToken ); + if ( upload == null ) + throw new TInvalidTokenException(); + return upload.getStatus(); + } + + @Override + public UserInfo getUser( String userToken, String userId ) + throws TAuthorizationException, TNotFoundException, TInvocationException + { + Session session = SessionManager.getSessionFromToken( userToken ); + if ( session == null ) + throw new TAuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "No valid user token" ); + UserInfo userInfo = session.getUserInfo(); + UserUtil.assertTutor( userInfo ); + UserInfo queriedUser; + try { + queriedUser = DbUser.getUserInfo( userToken ); + } catch ( SQLException e ) { + throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database broken" ); + } + if ( UserUtil.getFirstPublishingUser( queriedUser ) == null ) + throw new TNotFoundException( "Unknown userid" ); + return queriedUser; + } + } -- cgit v1.2.3-55-g7522