~ubuntu-branches/ubuntu/maverick/eucalyptus/maverick

« back to all changes in this revision

Viewing changes to clc/modules/image-manager/src/main/java/com/eucalyptus/images/ImageManager.java

  • Committer: Bazaar Package Importer
  • Author(s): Dave Walker (Daviey)
  • Date: 2010-07-21 17:27:10 UTC
  • mfrom: (1.1.38 upstream)
  • Revision ID: james.westby@ubuntu.com-20100721172710-7xv07dmdqgivc3t9
Tags: 2.0~bzr1211-0ubuntu1
* New major upstream version merge, 2.0 (r1211).
* debian/patches/:
  - 01-wsdl-stubs.patch, debian/wsdl.md5sums: wsdl stubs updated.
  - 02-Makefile.patch: Updated to reflect new code layout.
  - 07-local_support_euca_conf-in.patch: Updated to reflect new code layout.
  - 08-ubuntu-default-networking.patch: Refreshed.
  - 09-small-128-192MB.patch: Updated to point to new location.
  - 10-disable-iscsi.patch: Refreshed.
  - 11-state-cleanup-memleakfix.patch: Removed, fixed upstream.
  - 15-fix-default-ramdisk.patch: Updated to point to new location.
  - 16-kvm_libvirt_xml_default_use_kvm.patch: Updated to reflect changes.
  - 17-fix_walrus_OOM_errors.patch: Removed, fixed upstream.
  - 18-priv_security.patch: Updated to reflect upstream changes.
  - 20-brute-force-webui.patch: Updated to reflect upstream changes. 
  - 21-eucalyptus-1.7-with-gwt-1.6.4.patch: New patch, allows 
    eucalyptus-1.7 to be built against gwt 1.6.4. Based on patch courtesy 
    of Dmitrii Zagorodnov, upstream. (LP: #597330)
* debian/eucalyptus-java-common.links: 
  - Changed symlink for groovy, point to groovy.all.jar, making compatiable 
    with groovy versions >1.7. (LP: #595421)
  - Added ant.jar & jetty-rewrite-handler.jar as they are now required.
* debian/control
  - & debian/build-jars: Added libjavassist-java and libjetty-extra-java as 
    build dependencies.
  - Added libjetty-extra-java as a dependency of eucalyptus-java-common
* The binary resulting jar's have been renamed from eucalyptus-*-1.6.2.jar
  to eucalyptus-*-main.jar:    
  - debian/eucalyptus-cc.upstart
  - debian/eucalyptus-cloud.install
  - debian/eucalyptus-common.eucalyptus.upstart
  - debian/eucalyptus-java-common.install
  - debian/eucalyptus-network.upstart
  - debian/eucalyptus-sc.install
  - debian/eucalyptus-walrus.install
* debian/eucalyptus-java-common.install: New upstream jars that have been
  installed:
  - eucalyptus-db-hsqldb-ext-main.jar
  - eucalyptus-component-main.jar
* debian/control:
  - Updated Standards Version to 3.8.4 (no change)
  - Updated the upstream Homepage to: http://open.eucalyptus.com/
  - Changed Vcs-Bzr to reflect new location of Ubuntu hosted development branch.
  - Made the Build Dependency of groovy and the binary eucalyptus-java-common
    package depend on version >=1.7.

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
 
 
65
package com.eucalyptus.images;
 
66
 
 
67
import java.util.ArrayList;
 
68
import java.util.List;
 
69
import java.util.NoSuchElementException;
 
70
import java.util.Set;
 
71
import javax.xml.xpath.XPath;
 
72
import javax.xml.xpath.XPathConstants;
 
73
import javax.xml.xpath.XPathExpressionException;
 
74
import javax.xml.xpath.XPathFactory;
 
75
import org.apache.log4j.Logger;
 
76
import org.w3c.dom.Document;
 
77
import org.w3c.dom.NodeList;
 
78
import com.eucalyptus.auth.GroupEntity;
 
79
import com.eucalyptus.auth.Groups;
 
80
import com.eucalyptus.auth.NoSuchGroupException;
 
81
import com.eucalyptus.auth.NoSuchUserException;
 
82
import com.eucalyptus.auth.UserInfo;
 
83
import com.eucalyptus.auth.UserInfoStore;
 
84
import com.eucalyptus.auth.Users;
 
85
import com.eucalyptus.blockstorage.WalrusUtil;
 
86
import com.eucalyptus.cluster.VmInstance;
 
87
import com.eucalyptus.cluster.VmInstances;
 
88
import com.eucalyptus.entities.EntityWrapper;
 
89
import com.eucalyptus.images.Image;
 
90
import com.eucalyptus.images.ImageInfo;
 
91
import com.eucalyptus.images.ProductCode;
 
92
import com.eucalyptus.util.EucalyptusCloudException;
 
93
import com.google.common.collect.Lists;
 
94
import com.google.common.collect.Sets;
 
95
import edu.ucsb.eucalyptus.cloud.VmAllocationInfo;
 
96
import edu.ucsb.eucalyptus.cloud.VmImageInfo;
 
97
import edu.ucsb.eucalyptus.cloud.VmInfo;
 
98
import edu.ucsb.eucalyptus.cloud.entities.SystemConfiguration;
 
99
import edu.ucsb.eucalyptus.msgs.ConfirmProductInstanceResponseType;
 
100
import edu.ucsb.eucalyptus.msgs.ConfirmProductInstanceType;
 
101
import edu.ucsb.eucalyptus.msgs.DeregisterImageResponseType;
 
102
import edu.ucsb.eucalyptus.msgs.DeregisterImageType;
 
103
import edu.ucsb.eucalyptus.msgs.DescribeImageAttributeResponseType;
 
104
import edu.ucsb.eucalyptus.msgs.DescribeImageAttributeType;
 
105
import edu.ucsb.eucalyptus.msgs.DescribeImagesResponseType;
 
106
import edu.ucsb.eucalyptus.msgs.DescribeImagesType;
 
107
import edu.ucsb.eucalyptus.msgs.ImageDetails;
 
108
import edu.ucsb.eucalyptus.msgs.LaunchPermissionItemType;
 
109
import edu.ucsb.eucalyptus.msgs.ModifyImageAttributeResponseType;
 
110
import edu.ucsb.eucalyptus.msgs.ModifyImageAttributeType;
 
111
import edu.ucsb.eucalyptus.msgs.RegisterImageResponseType;
 
112
import edu.ucsb.eucalyptus.msgs.RegisterImageType;
 
113
import edu.ucsb.eucalyptus.msgs.ResetImageAttributeResponseType;
 
114
import edu.ucsb.eucalyptus.msgs.ResetImageAttributeType;
 
115
import edu.ucsb.eucalyptus.msgs.RunInstancesType;
 
116
 
 
117
public class ImageManager {
 
118
  public static Logger LOG                    = Logger.getLogger( ImageManager.class );
 
119
  public static String IMAGE_MACHINE          = "machine";
 
120
  public static String IMAGE_KERNEL           = "kernel";
 
121
  public static String IMAGE_RAMDISK          = "ramdisk";
 
122
  public static String IMAGE_MACHINE_PREFIX   = "emi";
 
123
  public static String IMAGE_KERNEL_PREFIX    = "eki";
 
124
  public static String IMAGE_RAMDISK_PREFIX   = "eri";
 
125
  
 
126
  public VmImageInfo resolve( VmInfo vmInfo ) throws EucalyptusCloudException {
 
127
    return ImageUtil.resolveImage( vmInfo );
 
128
  }
 
129
  
 
130
  public VmAllocationInfo verify( VmAllocationInfo vmAllocInfo ) throws EucalyptusCloudException {
 
131
    String walrusUrl = ImageUtil.getWalrusUrl( );
 
132
    
 
133
    RunInstancesType msg = vmAllocInfo.getRequest( );
 
134
    ImageInfo searchDiskInfo = new ImageInfo( msg.getImageId( ) );
 
135
    EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
136
    ImageInfo diskInfo = null;
 
137
    ArrayList<String> productCodes = Lists.newArrayList( );
 
138
    try {
 
139
      diskInfo = db.getUnique( searchDiskInfo );
 
140
      for ( ProductCode p : diskInfo.getProductCodes( ) ) {
 
141
        productCodes.add( p.getValue( ) );
 
142
      }
 
143
    } catch ( EucalyptusCloudException e ) {
 
144
      db.rollback( );
 
145
      throw new EucalyptusCloudException( "Failed to find disk image: " + msg.getImageId( ) );
 
146
    }
 
147
    UserInfo user = null;
 
148
    try {
 
149
      user = UserInfoStore.getUserInfo( new UserInfo( msg.getUserId( ) ) );
 
150
    } catch ( NoSuchUserException e1 ) {
 
151
      db.rollback( );
 
152
      throw new EucalyptusCloudException( "Can not find user info for this image." );
 
153
    }
 
154
    if ( !diskInfo.isAllowed( user ) ) {
 
155
      db.rollback( );
 
156
      throw new EucalyptusCloudException( "You do not have permissions to run this image." );
 
157
    }
 
158
    if ( "deregistered".equals( diskInfo.getImageState( ) ) ) {
 
159
      db.delete( diskInfo );
 
160
      db.rollback( );
 
161
      throw new EucalyptusCloudException( "The requested image is deregistered." );
 
162
    }
 
163
    ImageInfo kernelInfo = null;
 
164
    ImageInfo ramdiskInfo = null;
 
165
    String defaultKernelId = null;
 
166
    String defaultRamdiskId = null;
 
167
    try {
 
168
      defaultKernelId = SystemConfiguration.getSystemConfiguration( ).getDefaultKernel( );
 
169
      defaultRamdiskId = SystemConfiguration.getSystemConfiguration( ).getDefaultRamdisk( );
 
170
    } catch ( Exception e1 ) {}
 
171
      String kernelId = ImageUtil.getImageInfobyId( msg.getKernelId( ), diskInfo.getKernelId( ), defaultKernelId );
 
172
      if ( kernelId == null ) {
 
173
        db.rollback( );
 
174
        throw new EucalyptusCloudException( "Unable to determine required kernel image." );
 
175
      }
 
176
      try {
 
177
        kernelInfo = db.getUnique( new ImageInfo( kernelId ) );
 
178
      } catch ( EucalyptusCloudException e ) {
 
179
        db.rollback( );
 
180
        throw new EucalyptusCloudException( "Failed to find kernel image: " + kernelId );
 
181
      }
 
182
      if ( !kernelInfo.isAllowed( user ) ) {
 
183
        db.rollback( );
 
184
        throw new EucalyptusCloudException( "You do not have permission to launch: " + kernelInfo.getImageId( ) );
 
185
      }
 
186
      if ( !"kernel".equals( kernelInfo.getImageType( ) ) ) {
 
187
        db.rollback( );
 
188
        throw new EucalyptusCloudException( "Image specified is not a kernel: " + kernelInfo.toString( ) );
 
189
      }
 
190
      boolean nord = ( ImageUtil.isSet( msg.getKernelId( ) ) && !ImageUtil.isSet( msg.getRamdiskId( ) ) );
 
191
      nord |= ( !ImageUtil.isSet( msg.getKernelId( ) ) && ImageUtil.isSet( diskInfo.getKernelId( ) ) && !ImageUtil.isSet( diskInfo.getRamdiskId( ) ) && !ImageUtil
 
192
                                                                                                                                                                  .isSet( msg
 
193
                                                                                                                                                                             .getRamdiskId( ) ) );
 
194
      String ramdiskId = nord ? null : ImageUtil.getImageInfobyId( msg.getRamdiskId( ), diskInfo.getRamdiskId( ), defaultRamdiskId );
 
195
      if ( !diskInfo.isAllowed( user ) ) {
 
196
        db.rollback( );
 
197
        throw new EucalyptusCloudException( "You do not have permission to launch: " + diskInfo.getImageId( ) );
 
198
      }
 
199
      if ( ramdiskId != null ) {
 
200
        try {
 
201
          ramdiskInfo = db.getUnique( new ImageInfo( ramdiskId ) );
 
202
        } catch ( EucalyptusCloudException e ) {
 
203
          db.rollback( );
 
204
          throw new EucalyptusCloudException( "Failed to find ramdisk image: " + ramdiskId );
 
205
        }
 
206
        if ( !ramdiskInfo.isAllowed( user ) ) {
 
207
          db.rollback( );
 
208
          throw new EucalyptusCloudException( "You do not have permission to launch: " + ramdiskInfo.getImageId( ) );
 
209
        }
 
210
      }
 
211
      db.commit( );
 
212
      if ( ( ramdiskInfo != null ) && !"ramdisk".equals( ramdiskInfo.getImageType( ) ) ) {
 
213
        throw new EucalyptusCloudException( "Image specified is not a ramdisk: " + ramdiskInfo.toString( ) );
 
214
      }
 
215
      ImageUtil.checkStoredImage( ramdiskInfo );
 
216
    ArrayList<String> ancestorIds = ImageUtil.getAncestors( msg.getUserId( ), diskInfo.getImageLocation( ) );
 
217
    Long imgSize = ImageUtil.getSize( msg.getUserId( ), diskInfo.getImageLocation( ) );
 
218
    ImageUtil.checkStoredImage( kernelInfo );
 
219
    ImageUtil.checkStoredImage( diskInfo );
 
220
    
 
221
    // :: get together the required URLs ::/
 
222
    VmImageInfo vmImgInfo = ImageUtil.getVmImageInfo( walrusUrl, diskInfo, kernelInfo, ramdiskInfo, productCodes );
 
223
    vmImgInfo.setAncestorIds( ancestorIds );
 
224
    vmImgInfo.setSize( imgSize );
 
225
    vmAllocInfo.setImageInfo( vmImgInfo );
 
226
    return vmAllocInfo;
 
227
  }
 
228
  
 
229
  public DescribeImagesResponseType describe( DescribeImagesType request ) throws EucalyptusCloudException {
 
230
    DescribeImagesResponseType reply = ( DescribeImagesResponseType ) request.getReply( );
 
231
    ImageUtil.cleanDeregistered( );
 
232
    List<ImageInfo> imgList = Lists.newArrayList( );
 
233
    EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
234
    for ( String imageId : request.getImagesSet( ) ) {
 
235
      try {
 
236
        imgList.add( db.getUnique( ImageInfo.named( imageId ) ) );
 
237
      } catch ( Throwable e ) {}
 
238
    }
 
239
    db.commit( );
 
240
    UserInfo user = null;
 
241
    try {
 
242
      user = UserInfoStore.getUserInfo( new UserInfo( request.getUserId( ) ) );
 
243
    } catch ( NoSuchUserException e ) {
 
244
      throw new EucalyptusCloudException( "Failed to find user information for: " + request.getUserId( ), e );
 
245
    }
 
246
    ArrayList<String> imageList = request.getImagesSet( );
 
247
    ArrayList<String> owners = request.getOwnersSet( );
 
248
    ArrayList<String> executable = request.getExecutableBySet( );
 
249
    if ( owners.isEmpty( ) && executable.isEmpty( ) ) {
 
250
      executable.add( "self" );
 
251
    }
 
252
    Set<ImageDetails> repList = Sets.newHashSet( );
 
253
    if ( !owners.isEmpty( ) ) {
 
254
      repList.addAll( ImageUtil.getImagesByOwner( imgList, user, owners ) );
 
255
    }
 
256
    if ( !executable.isEmpty( ) ) {
 
257
      if ( executable.remove( "self" ) ) {
 
258
        repList.addAll( ImageUtil.getImageOwnedByUser( imgList, user ) );
 
259
      }
 
260
      repList.addAll( ImageUtil.getImagesByExec( user, executable ) );
 
261
    }
 
262
    reply.getImagesSet( ).addAll( repList );
 
263
    return reply;
 
264
  }
 
265
  
 
266
  public RegisterImageResponseType register( RegisterImageType request ) throws EucalyptusCloudException {
 
267
    String imageLocation = request.getImageLocation( );
 
268
    String[] imagePathParts;
 
269
    try {
 
270
      imagePathParts = ImageUtil.getImagePathParts( imageLocation );
 
271
      ImageUtil.checkBucketAcl( request, imagePathParts );
 
272
    } catch ( EucalyptusCloudException e ) {
 
273
      LOG.trace( e, e );
 
274
      throw e;
 
275
    }
 
276
    ImageInfo imageInfo = new ImageInfo( imageLocation, request.getUserId( ), "available", true );
 
277
    try {
 
278
      WalrusUtil.verifyManifestIntegrity( imageInfo );
 
279
    } catch ( EucalyptusCloudException e ) {
 
280
      throw new EucalyptusCloudException( "Image registration failed because the manifest referenced is invalid or unavailable." );
 
281
    }
 
282
    String userName = request.getUserId( );
 
283
    // FIXME: wrap this manifest junk in a helper class.
 
284
    Document inputSource = ImageUtil.getManifestDocument( imagePathParts, userName );
 
285
    XPath xpath = XPathFactory.newInstance( ).newXPath( );
 
286
    String arch = ImageUtil.extractArchitecture( inputSource, xpath );
 
287
    imageInfo.setArchitecture( ( arch == null ) ? "i386" : arch );
 
288
    String kernelId = ImageUtil.extractKernelId( inputSource, xpath );
 
289
    String ramdiskId = ImageUtil.extractRamdiskId( inputSource, xpath );
 
290
    List<ProductCode> prodCodes = extractProductCodes( inputSource, xpath );
 
291
    imageInfo.getProductCodes( ).addAll( prodCodes );
 
292
    
 
293
    if ( "yes".equals( kernelId ) || "true".equals( kernelId ) || imagePathParts[1].startsWith( "vmlinuz" ) ) {
 
294
      if ( !request.isAdministrator( ) ) throw new EucalyptusCloudException( "Only administrators can register kernel images." );
 
295
      imageInfo.setImageType( ImageManager.IMAGE_KERNEL );
 
296
      imageInfo.setImageId( ImageUtil.newImageId( ImageManager.IMAGE_KERNEL_PREFIX, imageInfo.getImageLocation( ) ) );
 
297
    } else if ( "yes".equals( ramdiskId ) || "true".equals( ramdiskId ) || imagePathParts[1].startsWith( "initrd" ) ) {
 
298
      if ( !request.isAdministrator( ) ) throw new EucalyptusCloudException( "Only administrators can register ramdisk images." );
 
299
      imageInfo.setImageType( ImageManager.IMAGE_RAMDISK );
 
300
      imageInfo.setImageId( ImageUtil.newImageId( ImageManager.IMAGE_RAMDISK_PREFIX, imageInfo.getImageLocation( ) ) );
 
301
    } else {
 
302
        if ( kernelId != null ) {
 
303
          try {
 
304
            ImageUtil.getImageInfobyId( kernelId );
 
305
          } catch ( EucalyptusCloudException e ) {
 
306
            throw new EucalyptusCloudException( "Referenced kernel id is invalid: " + kernelId );
 
307
          }
 
308
        }
 
309
        if ( ramdiskId != null ) {
 
310
          try {
 
311
            ImageUtil.getImageInfobyId( ramdiskId );
 
312
          } catch ( EucalyptusCloudException e ) {
 
313
            throw new EucalyptusCloudException( "Referenced ramdisk id is invalid: " + ramdiskId );
 
314
          }
 
315
        }
 
316
      imageInfo.setImageType( ImageManager.IMAGE_MACHINE );
 
317
      imageInfo.setKernelId( kernelId );
 
318
      imageInfo.setRamdiskId( ramdiskId );
 
319
      imageInfo.setImageId( ImageUtil.newImageId( ImageManager.IMAGE_MACHINE_PREFIX, imageInfo.getImageLocation( ) ) );
 
320
    }
 
321
    
 
322
    String signature = null;
 
323
    try {
 
324
      signature = ( String ) xpath.evaluate( "/manifest/signature/text()", inputSource, XPathConstants.STRING );
 
325
    } catch ( XPathExpressionException e ) {
 
326
      LOG.warn( e.getMessage( ) );
 
327
    }
 
328
    imageInfo.setSignature( signature );
 
329
    
 
330
    EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
331
    try {
 
332
      db.add( imageInfo );
 
333
      db.commit( );
 
334
      LOG.info( "Registering image pk=" + imageInfo.getId( ) + " ownerId=" + request.getUserId( ) );
 
335
    } catch ( Exception e ) {
 
336
      db.rollback( );
 
337
      throw new EucalyptusCloudException( "failed to register image." );
 
338
    }
 
339
    try {
 
340
      imageInfo.grantPermission( Users.lookupUser( request.getUserId( ) ) );
 
341
    } catch ( NoSuchUserException e ) {
 
342
      LOG.debug( e, e );
 
343
    }
 
344
    try {
 
345
      imageInfo.grantPermission( Groups.lookupGroup( "all" ) );
 
346
    } catch ( NoSuchGroupException e ) {
 
347
      LOG.error( e, e );
 
348
    }
 
349
    
 
350
    LOG.info( "Triggering cache population in Walrus for: " + imageInfo.getId( ) );
 
351
    WalrusUtil.checkValid( imageInfo );
 
352
    WalrusUtil.triggerCaching( imageInfo );
 
353
    
 
354
    RegisterImageResponseType reply = ( RegisterImageResponseType ) request.getReply( );
 
355
    reply.setImageId( imageInfo.getImageId( ) );
 
356
    return reply;
 
357
  }
 
358
  
 
359
  private List<ProductCode> extractProductCodes( Document inputSource, XPath xpath ) {
 
360
    List<ProductCode> prodCodes = Lists.newArrayList( );
 
361
    NodeList productCodes = null;
 
362
    try {
 
363
      productCodes = ( NodeList ) xpath.evaluate( "/manifest/machine_configuration/product_codes/product_code/text()", inputSource, XPathConstants.NODESET );
 
364
      for ( int i = 0; i < productCodes.getLength( ); i++ ) {
 
365
        for ( String productCode : productCodes.item( i ).getNodeValue( ).split( "," ) ) {
 
366
          prodCodes.add( new ProductCode( productCode ) );
 
367
        }
 
368
      }
 
369
    } catch ( XPathExpressionException e ) {
 
370
      LOG.error( e, e );
 
371
    }
 
372
    return prodCodes;
 
373
  }
 
374
  
 
375
  public DeregisterImageResponseType deregister( DeregisterImageType request ) throws EucalyptusCloudException {
 
376
    DeregisterImageResponseType reply = ( DeregisterImageResponseType ) request.getReply( );
 
377
    EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
378
    
 
379
    ImageInfo imgInfo = null;
 
380
    try {
 
381
      imgInfo = db.getUnique( new ImageInfo( request.getImageId( ) ) );
 
382
      if ( !imgInfo.getImageOwnerId( ).equals( request.getUserId( ) ) && !request.isAdministrator( ) ) throw new EucalyptusCloudException(
 
383
                                                                                                                                           "Only the owner of a registered image or the administrator can deregister it." );
 
384
      WalrusUtil.invalidate( imgInfo );
 
385
      db.commit( );
 
386
      reply.set_return( true );
 
387
    } catch ( EucalyptusCloudException e ) {
 
388
      reply.set_return( false );
 
389
      db.rollback( );
 
390
    }
 
391
    return reply;
 
392
  }
 
393
  
 
394
  public ConfirmProductInstanceResponseType confirmProductInstance( ConfirmProductInstanceType request ) throws EucalyptusCloudException {
 
395
    ConfirmProductInstanceResponseType reply = ( ConfirmProductInstanceResponseType ) request.getReply( );
 
396
    reply.set_return( false );
 
397
    VmInstance vm = null;
 
398
    try {
 
399
      vm = VmInstances.getInstance( ).lookup( request.getInstanceId( ) );
 
400
      EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
401
      try {
 
402
        ImageInfo found = db.getUnique( new ImageInfo( vm.getImageInfo( ).getImageId( ) ) );
 
403
        if ( found.getProductCodes( ).contains( new ProductCode( request.getProductCode( ) ) ) ) {
 
404
          reply.set_return( true );
 
405
          reply.setOwnerId( found.getImageOwnerId( ) );
 
406
        }
 
407
        db.commit( );
 
408
      } catch ( EucalyptusCloudException e ) {
 
409
        db.commit( );
 
410
      }
 
411
    } catch ( NoSuchElementException e ) {}
 
412
    return reply;
 
413
  }
 
414
  
 
415
  public DescribeImageAttributeResponseType describeImageAttribute( DescribeImageAttributeType request ) throws EucalyptusCloudException {
 
416
    DescribeImageAttributeResponseType reply = ( DescribeImageAttributeResponseType ) request.getReply( );
 
417
    reply.setImageId( request.getImageId( ) );
 
418
    
 
419
    if ( request.getAttribute( ) != null ) request.applyAttribute( );
 
420
    
 
421
    EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
422
    try {
 
423
      ImageInfo imgInfo = db.getUnique( new ImageInfo( request.getImageId( ) ) );
 
424
      if ( !imgInfo.isAllowed( UserInfoStore.getUserInfo( new UserInfo( request.getUserId( ) ) ) ) ) throw new EucalyptusCloudException(
 
425
                                                                                                                                         "image attribute: not authorized." );
 
426
      if ( request.getKernel( ) != null ) {
 
427
        reply.setRealResponse( reply.getKernel( ) );
 
428
        if ( imgInfo.getKernelId( ) != null ) {
 
429
          reply.getKernel( ).add( imgInfo.getKernelId( ) );
 
430
        }
 
431
      } else if ( request.getRamdisk( ) != null ) {
 
432
        reply.setRealResponse( reply.getRamdisk( ) );
 
433
        if ( imgInfo.getRamdiskId( ) != null ) {
 
434
          reply.getRamdisk( ).add( imgInfo.getRamdiskId( ) );
 
435
        }
 
436
      } else if ( request.getLaunchPermission( ) != null ) {
 
437
        reply.setRealResponse( reply.getLaunchPermission( ) );
 
438
        for ( ImageAuthorization auth : imgInfo.getUserGroups( ) )
 
439
          reply.getLaunchPermission( ).add( LaunchPermissionItemType.getGroup( auth.getValue( ) ) );
 
440
        for ( ImageAuthorization auth : imgInfo.getPermissions( ) )
 
441
          reply.getLaunchPermission( ).add( LaunchPermissionItemType.getUser( auth.getValue( ) ) );
 
442
      } else if ( request.getProductCodes( ) != null ) {
 
443
        reply.setRealResponse( reply.getProductCodes( ) );
 
444
        for ( ProductCode p : imgInfo.getProductCodes( ) ) {
 
445
          reply.getProductCodes( ).add( p.getValue( ) );
 
446
        }
 
447
      } else if ( request.getBlockDeviceMapping( ) != null ) {
 
448
        reply.setRealResponse( reply.getBlockDeviceMapping( ) );
 
449
        reply.getBlockDeviceMapping( ).add( ImageUtil.EMI );
 
450
        reply.getBlockDeviceMapping( ).add( ImageUtil.EPHEMERAL );
 
451
        reply.getBlockDeviceMapping( ).add( ImageUtil.SWAP );
 
452
        reply.getBlockDeviceMapping( ).add( ImageUtil.ROOT );
 
453
      } else {
 
454
        throw new EucalyptusCloudException( "invalid image attribute request." );
 
455
      }
 
456
    } catch ( EucalyptusCloudException e ) {
 
457
      db.commit( );
 
458
      throw e;
 
459
    } catch ( NoSuchUserException e ) {
 
460
      db.commit( );
 
461
      throw new EucalyptusCloudException( "can not find user info." );
 
462
    }
 
463
    return reply;
 
464
  }
 
465
  
 
466
  public ModifyImageAttributeResponseType modifyImageAttribute( ModifyImageAttributeType request ) throws EucalyptusCloudException {
 
467
    ModifyImageAttributeResponseType reply = ( ModifyImageAttributeResponseType ) request.getReply( );
 
468
    
 
469
    if ( request.getAttribute( ) != null ) request.applyAttribute( );
 
470
    
 
471
    if ( request.getProductCodes( ).isEmpty( ) ) {
 
472
      reply.set_return( ImageUtil.modifyImageInfo( request.getImageId( ), request.getUserId( ), request.isAdministrator( ), request.getAdd( ),
 
473
                                                   request.getRemove( ) ) );
 
474
    } else {
 
475
      EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
476
      ImageInfo imgInfo = null;
 
477
      try {
 
478
        imgInfo = db.getUnique( new ImageInfo( request.getImageId( ) ) );
 
479
        for ( String productCode : request.getProductCodes( ) ) {
 
480
          ProductCode prodCode = new ProductCode( productCode );
 
481
          if ( !imgInfo.getProductCodes( ).contains( prodCode ) ) {
 
482
            imgInfo.getProductCodes( ).add( prodCode );
 
483
          }
 
484
        }
 
485
        db.commit( );
 
486
        reply.set_return( true );
 
487
      } catch ( EucalyptusCloudException e ) {
 
488
        db.rollback( );
 
489
        reply.set_return( false );
 
490
      }
 
491
    }
 
492
    return reply;
 
493
  }
 
494
  
 
495
  public ResetImageAttributeResponseType resetImageAttribute( ResetImageAttributeType request ) throws EucalyptusCloudException {
 
496
    ResetImageAttributeResponseType reply = ( ResetImageAttributeResponseType ) request.getReply( );
 
497
    reply.set_return( true );
 
498
    EntityWrapper<ImageInfo> db = new EntityWrapper<ImageInfo>( );
 
499
    try {
 
500
      ImageInfo imgInfo = db.getUnique( new ImageInfo( request.getImageId( ) ) );
 
501
      if ( request.getUserId( ).equals( imgInfo.getImageOwnerId( ) ) || request.isAdministrator( ) ) {
 
502
        imgInfo.getPermissions( ).clear( );
 
503
        db.commit( );
 
504
        imgInfo.grantPermission( Users.lookupUser( request.getUserId( ) ) );
 
505
        try {
 
506
          imgInfo.grantPermission( Groups.lookupGroup( "all" ) );
 
507
        } catch ( NoSuchGroupException e ) {
 
508
          LOG.error( e, e );
 
509
        }        
 
510
      } else {
 
511
        db.rollback( );
 
512
        reply.set_return( false );
 
513
      }
 
514
    } catch ( EucalyptusCloudException e ) {
 
515
      db.rollback( );
 
516
      reply.set_return( false );
 
517
    } catch ( NoSuchUserException e ) {
 
518
      db.rollback( );
 
519
      reply.set_return( false );
 
520
    }
 
521
    return reply;
 
522
  }
 
523
}