~ubuntu-branches/ubuntu/raring/eucalyptus/raring

« back to all changes in this revision

Viewing changes to clc/modules/cluster-manager/src/main/java/com/eucalyptus/images/ImageUtil.java

  • Committer: Package Import Robot
  • Author(s): Brian Thomason
  • Date: 2011-11-29 13:17:52 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 185.
  • Revision ID: package-import@ubuntu.com-20111129131752-rq31al3ntutv2vvl
Tags: upstream-3.0.999beta1
ImportĀ upstreamĀ versionĀ 3.0.999beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 *Copyright (c) 2009  Eucalyptus Systems, Inc.
 
3
 * 
 
4
 *  This program is free software: you can redistribute it and/or modify
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation, only version 3 of the License.
 
7
 * 
 
8
 * 
 
9
 *  This file is distributed in the hope that it will be useful, but WITHOUT
 
10
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
12
 *  for more details.
 
13
 * 
 
14
 *  You should have received a copy of the GNU General Public License along
 
15
 *  with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 * 
 
17
 *  Please contact Eucalyptus Systems, Inc., 130 Castilian
 
18
 *  Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
 
19
 *  if you need additional information or have any questions.
 
20
 * 
 
21
 *  This file may incorporate work covered under the following copyright and
 
22
 *  permission notice:
 
23
 * 
 
24
 *    Software License Agreement (BSD License)
 
25
 * 
 
26
 *    Copyright (c) 2008, Regents of the University of California
 
27
 *    All rights reserved.
 
28
 * 
 
29
 *    Redistribution and use of this software in source and binary forms, with
 
30
 *    or without modification, are permitted provided that the following
 
31
 *    conditions are met:
 
32
 * 
 
33
 *      Redistributions of source code must retain the above copyright notice,
 
34
 *      this list of conditions and the following disclaimer.
 
35
 * 
 
36
 *      Redistributions in binary form must reproduce the above copyright
 
37
 *      notice, this list of conditions and the following disclaimer in the
 
38
 *      documentation and/or other materials provided with the distribution.
 
39
 * 
 
40
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 
41
 *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 
42
 *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
43
 *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 
44
 *    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
45
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
46
 *    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
47
 *    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 
48
 *    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
49
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
50
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
 
51
 *    THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
 
52
 *    LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
 
53
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
 
54
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
 
55
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
 
56
 *    THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
 
57
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
 
58
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
 
59
 *    ANY SUCH LICENSES OR RIGHTS.
 
60
 *******************************************************************************/
 
61
/*
 
62
 * Author: chris grzegorczyk <grze@eucalyptus.com>
 
63
 */
 
64
package com.eucalyptus.images;
 
65
 
 
66
import java.security.PublicKey;
 
67
import java.security.Signature;
 
68
import java.security.cert.X509Certificate;
 
69
import java.util.ArrayList;
 
70
import java.util.List;
 
71
import java.util.zip.Adler32;
 
72
import javax.xml.xpath.XPath;
 
73
import javax.xml.xpath.XPathConstants;
 
74
import javax.xml.xpath.XPathExpressionException;
 
75
import javax.xml.xpath.XPathFactory;
 
76
import org.apache.log4j.Logger;
 
77
import org.w3c.dom.DOMException;
 
78
import org.w3c.dom.Document;
 
79
import org.w3c.dom.NodeList;
 
80
import com.eucalyptus.auth.Accounts;
 
81
import com.eucalyptus.auth.AuthException;
 
82
import com.eucalyptus.auth.util.Hashes;
 
83
import com.eucalyptus.blockstorage.WalrusUtil;
 
84
import com.eucalyptus.cloud.ImageMetadata;
 
85
import com.eucalyptus.cloud.ImageMetadata.Architecture;
 
86
import com.eucalyptus.cloud.ImageMetadata.StaticDiskImage;
 
87
import com.eucalyptus.component.ComponentIds;
 
88
import com.eucalyptus.component.id.Eucalyptus;
 
89
import com.eucalyptus.context.Context;
 
90
import com.eucalyptus.context.Contexts;
 
91
import com.eucalyptus.crypto.Crypto;
 
92
import com.eucalyptus.entities.EntityWrapper;
 
93
import com.eucalyptus.util.EucalyptusCloudException;
 
94
import com.eucalyptus.util.FullName;
 
95
import com.eucalyptus.util.RestrictedTypes;
 
96
import com.google.common.collect.Lists;
 
97
import edu.ucsb.eucalyptus.msgs.BlockDeviceMappingItemType;
 
98
import edu.ucsb.eucalyptus.msgs.GetBucketAccessControlPolicyResponseType;
 
99
import edu.ucsb.eucalyptus.msgs.LaunchPermissionItemType;
 
100
import edu.ucsb.eucalyptus.msgs.ModifyImageAttributeType;
 
101
import edu.ucsb.eucalyptus.msgs.RegisterImageType;
 
102
 
 
103
public class ImageUtil {
 
104
  private static Logger LOG = Logger.getLogger( ImageUtil.class );
 
105
  
 
106
  public static String newImageId( final String imagePrefix, final String imageLocation ) {
 
107
    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
108
    String testId = Crypto.generateId( imageLocation, imagePrefix );
 
109
    ImageInfo query = Images.exampleWithImageId( testId );
 
110
    LOG.info( "Trying to lookup using created AMI id=" + query.getDisplayName( ) );
 
111
    for ( ; db.query( query ).size( ) != 0; query.setDisplayName( Crypto.generateId( imageLocation, imagePrefix ) ) );
 
112
    db.commit( );
 
113
    LOG.info( "Assigning imageId=" + query.getDisplayName( ) );
 
114
    return query.getDisplayName( );
 
115
  }
 
116
  
 
117
  public static boolean verifyManifestSignature( final X509Certificate cert, final String signature, String pad ) {
 
118
    Signature sigVerifier;
 
119
    try {
 
120
      sigVerifier = Signature.getInstance( "SHA1withRSA" );
 
121
      PublicKey publicKey = cert.getPublicKey( );
 
122
      sigVerifier.initVerify( publicKey );
 
123
      sigVerifier.update( ( pad ).getBytes( ) );
 
124
      return sigVerifier.verify( Hashes.hexToBytes( signature ) );
 
125
    } catch ( Exception ex ) {
 
126
      LOG.error( ex, ex );
 
127
      return false;
 
128
    }
 
129
  }
 
130
  
 
131
  public static ArrayList<String> getAncestors( String userId, String manifestPath ) {
 
132
    ArrayList<String> ancestorIds = Lists.newArrayList( );
 
133
    try {
 
134
      String[] imagePathParts = manifestPath.split( "/" );
 
135
      Document inputSource = WalrusUtil.getManifestData( ComponentIds.lookup( Eucalyptus.class ).getFullName( ), imagePathParts[0], imagePathParts[1] );
 
136
      XPath xpath = XPathFactory.newInstance( ).newXPath( );
 
137
      NodeList ancestors = null;
 
138
      try {
 
139
        ancestors = ( NodeList ) xpath.evaluate( "/manifest/image/ancestry/ancestor_ami_id/text()", inputSource, XPathConstants.NODESET );
 
140
        if ( ancestors == null ) return ancestorIds;
 
141
        for ( int i = 0; i < ancestors.getLength( ); i++ ) {
 
142
          for ( String ancestorId : ancestors.item( i ).getNodeValue( ).split( "," ) ) {
 
143
            ancestorIds.add( ancestorId );
 
144
          }
 
145
        }
 
146
      } catch ( XPathExpressionException e ) {
 
147
        LOG.error( e, e );
 
148
      }
 
149
    } catch ( EucalyptusCloudException e ) {
 
150
      LOG.error( e, e );
 
151
    } catch ( DOMException e ) {
 
152
      LOG.error( e, e );
 
153
    }
 
154
    return ancestorIds;
 
155
  }
 
156
  
 
157
  public static Long getSize( String manifestPath ) {
 
158
    Long size = 0l;
 
159
    try {
 
160
      String[] imagePathParts = manifestPath.split( "/" );
 
161
      Document inputSource = WalrusUtil.getManifestData( ComponentIds.lookup( Eucalyptus.class ).getFullName( ), imagePathParts[0], imagePathParts[1] );
 
162
      XPath xpath = XPathFactory.newInstance( ).newXPath( );
 
163
      String rootSize = "0";
 
164
      try {
 
165
        rootSize = ( String ) xpath.evaluate( "/manifest/image/size/text()", inputSource, XPathConstants.STRING );
 
166
        try {
 
167
          size = Long.parseLong( rootSize );
 
168
        } catch ( NumberFormatException e ) {
 
169
          LOG.error( e, e );
 
170
        }
 
171
      } catch ( XPathExpressionException e ) {
 
172
        LOG.error( e, e );
 
173
      }
 
174
    } catch ( EucalyptusCloudException e ) {
 
175
      LOG.error( e, e );
 
176
    }
 
177
    return size;
 
178
  }
 
179
  
 
180
  public static void checkStoredImage( final ImageMetadata.StaticDiskImage imgInfo ) throws EucalyptusCloudException {
 
181
    if ( imgInfo != null ) try {
 
182
      Document inputSource = null;
 
183
      try {
 
184
        String[] imagePathParts = imgInfo.getManifestLocation( ).split( "/" );
 
185
        inputSource = WalrusUtil.getManifestData( imgInfo.getOwner( ), imagePathParts[0], imagePathParts[1] );
 
186
      } catch ( EucalyptusCloudException e ) {
 
187
        throw e;
 
188
      }
 
189
      XPath xpath = null;
 
190
      xpath = XPathFactory.newInstance( ).newXPath( );
 
191
      String signature = null;
 
192
      try {
 
193
        signature = ( String ) xpath.evaluate( "/manifest/signature/text()", inputSource, XPathConstants.STRING );
 
194
      } catch ( XPathExpressionException e ) {}
 
195
      if ( imgInfo.getSignature( ) != null && !imgInfo.getSignature( ).equals( signature ) ) throw new EucalyptusCloudException( "Manifest signature has changed since registration." );
 
196
      LOG.info( "Triggering caching: " + imgInfo.getManifestLocation( ) );
 
197
      try {
 
198
        if( imgInfo instanceof ImageMetadata.StaticDiskImage ) {
 
199
          WalrusUtil.triggerCaching( ( StaticDiskImage ) imgInfo );
 
200
        }
 
201
      } catch ( Exception e ) {}
 
202
      } catch ( EucalyptusCloudException e ) {
 
203
      LOG.error( e );
 
204
      LOG.error( "Failed bukkit check! Invalidating registration: " + imgInfo.getManifestLocation( ) );
 
205
      //TODO: we need to consider if this is a good semantic or not, it can have ugly side effects
 
206
      //        invalidateImageById( imgInfo.getImageId() );
 
207
      throw new EucalyptusCloudException( "Failed check! Invalidating registration: " + imgInfo.getManifestLocation( ) );
 
208
      }
 
209
  }
 
210
  
 
211
  public static boolean isSet( String id ) {
 
212
    return id != null && !"".equals( id );
 
213
  }
 
214
  
 
215
  /*
 
216
  private static boolean userHasImagePermission( final UserInfo user, final ImageInfo img ) {
 
217
    try {
 
218
      if ( !user.getUserName( ).equals( img.getImageOwnerId( ) )
 
219
           && !Users.lookupUser( user.getUserName( ) ).isAdministrator( ) && !img.getPermissions( ).contains( user ) ) return true;
 
220
    } catch ( NoSuchUserException e ) {
 
221
      return false;
 
222
    }
 
223
    return false;
 
224
  }
 
225
  */
 
226
//  private static void invalidateImageById( String searchId ) throws EucalyptusCloudException {
 
227
//    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
228
//    if ( isSet( searchId ) ) try {
 
229
//      ImageInfo img = db.getUnique( Images.exampleWithImageId( searchId ) );
 
230
//      WalrusUtil.invalidate( img );
 
231
//      db.commit( );
 
232
//      } catch ( EucalyptusCloudException e ) {
 
233
//      db.rollback( );
 
234
//      throw new EucalyptusCloudException( "Failed to find registered image with id " + searchId, e );
 
235
//      }
 
236
//  }
 
237
  
 
238
  public static ImageInfo getImageInfobyId( String searchId ) throws EucalyptusCloudException {
 
239
    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
240
    if ( isSet( searchId ) ) try {
 
241
      ImageInfo imgInfo = db.getUnique( Images.exampleWithImageId( searchId ) );
 
242
      db.commit( );
 
243
      return imgInfo;
 
244
      } catch ( EucalyptusCloudException e ) {
 
245
      LOG.error( e, e );
 
246
      db.commit( );
 
247
      throw new EucalyptusCloudException( "Failed to find registered image with id " + searchId, e );
 
248
      } catch ( Exception t ) {
 
249
      LOG.error( t, t );
 
250
      db.commit( );
 
251
      }
 
252
    LOG.error( "Failed to find registered image with id " + searchId );
 
253
    throw new EucalyptusCloudException( "Failed to find registered image with id " + searchId );
 
254
  }
 
255
  
 
256
  public static String getImageInfobyId( String userSuppliedId, String imageDefaultId, String systemDefaultId ) {
 
257
    String searchId = null;
 
258
    if ( isSet( userSuppliedId ) )
 
259
      searchId = userSuppliedId;
 
260
    else if ( isSet( imageDefaultId ) )
 
261
      searchId = imageDefaultId;
 
262
    else if ( isSet( systemDefaultId ) ) searchId = systemDefaultId;
 
263
    return searchId;
 
264
  }
 
265
  
 
266
  public static BlockDeviceMappingItemType EMI       = new BlockDeviceMappingItemType( "emi", "sda1" );
 
267
  public static BlockDeviceMappingItemType EPHEMERAL = new BlockDeviceMappingItemType( "ephemeral0", "sda2" );
 
268
  public static BlockDeviceMappingItemType SWAP      = new BlockDeviceMappingItemType( "swap", "sda3" );
 
269
  public static BlockDeviceMappingItemType ROOT      = new BlockDeviceMappingItemType( "root", "/dev/sda1" );
 
270
  
 
271
  public static Architecture extractArchitecture( Document inputSource, XPath xpath ) {
 
272
    String arch = null;
 
273
    try {
 
274
      arch = ( String ) xpath.evaluate( "/manifest/machine_configuration/architecture/text()", inputSource, XPathConstants.STRING );
 
275
    } catch ( XPathExpressionException e ) {
 
276
      LOG.warn( e.getMessage( ) );
 
277
    }
 
278
    String architecture = ( ( arch == null )
 
279
        ? "i386"
 
280
        : arch );
 
281
    return ImageMetadata.Architecture.valueOf( architecture );
 
282
  }
 
283
  
 
284
  public static String extractRamdiskId( Document inputSource, XPath xpath ) {
 
285
    String ramdiskId = null;
 
286
    try {
 
287
      ramdiskId = ( String ) xpath.evaluate( "/manifest/machine_configuration/ramdisk_id/text()", inputSource, XPathConstants.STRING );
 
288
    } catch ( XPathExpressionException e ) {
 
289
      LOG.warn( e.getMessage( ) );
 
290
    }
 
291
    if ( !isSet( ramdiskId ) ) ramdiskId = null;
 
292
    return ramdiskId;
 
293
  }
 
294
  
 
295
  public static String extractKernelId( Document inputSource, XPath xpath ) {
 
296
    String kernelId = null;
 
297
    try {
 
298
      kernelId = ( String ) xpath.evaluate( "/manifest/machine_configuration/kernel_id/text()", inputSource, XPathConstants.STRING );
 
299
    } catch ( XPathExpressionException e ) {
 
300
      LOG.warn( e.getMessage( ) );
 
301
    }
 
302
    if ( !isSet( kernelId ) ) kernelId = null;
 
303
    return kernelId;
 
304
  }
 
305
  
 
306
  public static void checkBucketAcl( RegisterImageType request, String[] imagePathParts ) throws EucalyptusCloudException {
 
307
    String userName = null;
 
308
    Context ctx = Contexts.lookup( );
 
309
    if ( !ctx.hasAdministrativePrivileges( ) ) {
 
310
      GetBucketAccessControlPolicyResponseType reply = WalrusUtil.getBucketAcl( request, imagePathParts );
 
311
      if ( reply != null ) {
 
312
        if ( !Contexts.lookup( ).getUserFullName( ).getUserId( ).equals( reply.getAccessControlPolicy( ).getOwner( ).getDisplayName( ) ) ) throw new EucalyptusCloudException(
 
313
                                                                                                                                                                               "Image registration failed: you must own the bucket containing the image." );
 
314
        userName = reply.getAccessControlPolicy( ).getOwner( ).getDisplayName( );
 
315
      }
 
316
    }
 
317
  }
 
318
  
 
319
  public static void applyImageAttributes( final EntityWrapper<ImageInfo> db, final ImageInfo imgInfo, final List<LaunchPermissionItemType> changeList, final boolean adding ) throws EucalyptusCloudException {
 
320
    for ( LaunchPermissionItemType perm : changeList ) {
 
321
      if ( perm.isGroup( ) ) {
 
322
        try {
 
323
          if ( adding ) {
 
324
            //TODO:GRZE:RESTORE            imgInfo.grantPermission( new ImageUserGroup( perm.getGroup( ) ) );
 
325
          } else {
 
326
            //TODO:GRZE:RESTORE            imgInfo.revokePermission( new ImageUserGroup( perm.getGroup( ) ) );
 
327
          }
 
328
        } catch ( Exception e ) {
 
329
          LOG.debug( e, e );
 
330
          throw new EucalyptusCloudException( "Modify image attribute failed because of: " + e.getMessage( ) );
 
331
        }
 
332
      } else if ( perm.isUser( ) ) {
 
333
        try {
 
334
          if ( adding ) {
 
335
            imgInfo.grantPermission( Accounts.lookupAccountById( perm.getUserId( ) ) );
 
336
          } else {
 
337
            imgInfo.revokePermission( Accounts.lookupAccountById( perm.getUserId( ) ) );
 
338
          }
 
339
        } catch ( AuthException e ) {
 
340
          LOG.debug( e, e );
 
341
          throw new EucalyptusCloudException( "Modify image attribute failed because of: " + e.getMessage( ) );
 
342
        }
 
343
      }
 
344
    }
 
345
  }
 
346
  
 
347
  public static boolean modifyImageInfo( ModifyImageAttributeType request ) {
 
348
    final String imageId = request.getImageId( );
 
349
    final List<LaunchPermissionItemType> addList = request.getAdd( );
 
350
    final List<LaunchPermissionItemType> remList = request.getRemove( );
 
351
    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
352
    ImageInfo imgInfo = null;
 
353
    try {
 
354
      imgInfo = db.getUnique( Images.exampleWithImageId( imageId ) );
 
355
    } catch ( EucalyptusCloudException e ) {
 
356
      db.rollback( );
 
357
      return false;
 
358
    }
 
359
    if ( RestrictedTypes.filterPrivileged( ).apply( imgInfo ) ) {
 
360
      return false;
 
361
    }
 
362
    try {
 
363
      applyImageAttributes( db, imgInfo, addList, true );
 
364
      applyImageAttributes( db, imgInfo, remList, false );
 
365
      db.commit( );
 
366
      return true;
 
367
    } catch ( EucalyptusCloudException e ) {
 
368
      LOG.warn( e );
 
369
      db.rollback( );
 
370
      return false;
 
371
    }
 
372
  }
 
373
  
 
374
  public static Document getManifestDocument( String[] imagePathParts, FullName userName ) throws EucalyptusCloudException {
 
375
    Document inputSource = null;
 
376
    try {
 
377
      inputSource = WalrusUtil.getManifestData( userName, imagePathParts[0], imagePathParts[1] );
 
378
    } catch ( EucalyptusCloudException e ) {
 
379
      throw e;
 
380
    }
 
381
    return inputSource;
 
382
  }
 
383
  
 
384
  public static void cleanDeregistered( ) {
 
385
    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
386
    try {
 
387
      List<ImageInfo> imgList = db.query( Images.exampleWithImageState( ImageMetadata.State.deregistered ) );
 
388
      for ( ImageInfo deregImg : imgList ) {
 
389
        try {
 
390
          db.delete( deregImg );
 
391
        } catch ( Exception e1 ) {}
 
392
      }
 
393
      db.commit( );
 
394
    } catch ( Exception e1 ) {
 
395
      db.rollback( );
 
396
    }
 
397
  }
 
398
  
 
399
  public static int countByAccount( String accountId ) throws AuthException {
 
400
    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
401
    try {
 
402
      List<ImageInfo> images = db.query( new ImageInfo( ) );
 
403
      int imageNum = 0;
 
404
      for ( ImageInfo img : images ) {
 
405
        if ( img.getOwnerAccountNumber( ).equals( accountId ) ) {
 
406
          imageNum ++;
 
407
        }
 
408
      }
 
409
      db.commit( );
 
410
      return imageNum;
 
411
    } catch ( Exception e ) {
 
412
      db.rollback( );
 
413
      throw new AuthException( "Image database query failed", e );
 
414
    }
 
415
  }
 
416
  
 
417
  public static int countByUser( String userId ) throws AuthException {
 
418
    EntityWrapper<ImageInfo> db = EntityWrapper.get( ImageInfo.class );
 
419
    try {
 
420
      List<ImageInfo> images = db.query( new ImageInfo( ) );
 
421
      int imageNum = 0;
 
422
      for ( ImageInfo img : images ) {
 
423
        if ( img.getOwnerUserId( ).equals( userId ) ) {
 
424
          imageNum ++;
 
425
        }
 
426
      }
 
427
      db.commit( );
 
428
      return imageNum;
 
429
    } catch ( Exception e ) {
 
430
      db.rollback( );
 
431
      throw new AuthException( "Image database query failed", e );
 
432
    }
 
433
  }
 
434
  
 
435
}