CLOUDSTACK-1116 [EC2 Query API] Support for ModifyImageAttribute and ResetImageAttribute

https://reviews.apache.org/r/9213

Add support for EC2 ApiI's ModifyImageAttribute and ResetImageAttribute.
Attributes supported are Description and LaunchPermission.
This commit is contained in:
Prachi Damle 2013-02-07 17:22:16 -08:00
parent 951cba92bb
commit 4e4edc9e42
5 changed files with 193 additions and 107 deletions

View File

@ -87,6 +87,7 @@ import com.amazon.ec2.DetachVolumeResponse;
import com.amazon.ec2.DisassociateAddressResponse;
import com.amazon.ec2.GetPasswordDataResponse;
import com.amazon.ec2.ImportKeyPairResponse;
import com.amazon.ec2.LaunchPermissionItemType;
import com.amazon.ec2.ModifyImageAttributeResponse;
import com.amazon.ec2.RebootInstancesResponse;
import com.amazon.ec2.RegisterImageResponse;
@ -123,10 +124,13 @@ import com.cloud.bridge.service.core.ec2.EC2Engine;
import com.cloud.bridge.service.core.ec2.EC2Filter;
import com.cloud.bridge.service.core.ec2.EC2GroupFilterSet;
import com.cloud.bridge.service.core.ec2.EC2Image;
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission;
import com.cloud.bridge.service.core.ec2.EC2ImportKeyPair;
import com.cloud.bridge.service.core.ec2.EC2InstanceFilterSet;
import com.cloud.bridge.service.core.ec2.EC2IpPermission;
import com.cloud.bridge.service.core.ec2.EC2KeyPairFilterSet;
import com.cloud.bridge.service.core.ec2.EC2ModifyImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2RebootInstances;
import com.cloud.bridge.service.core.ec2.EC2RegisterImage;
import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress;
@ -1021,38 +1025,105 @@ public class EC2RestServlet extends HttpServlet {
serializeResponse(response, EC2response);
}
private void modifyImageAttribute( HttpServletRequest request, HttpServletResponse response )
private void modifyImageAttribute( HttpServletRequest request, HttpServletResponse response )
throws ADBException, XMLStreamException, IOException {
EC2Image image = new EC2Image();
EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute();
// -> its interesting to note that the SOAP API docs has description but the REST API docs do not
String[] imageId = request.getParameterValues( "ImageId" );
if ( null != imageId && 0 < imageId.length )
image.setId( imageId[0] );
else { response.sendError(530, "Missing ImageId parameter" ); return; }
String[] imageId = request.getParameterValues( "ImageId" );
if ( imageId != null && imageId.length > 0 )
ec2request.setImageId( imageId[0]);
else {
response.sendError(530, "Missing ImageId parameter" );
return;
}
String[] description = request.getParameterValues( "Description" );
if ( null != description && 0 < description.length )
image.setDescription( description[0] );
else { response.sendError(530, "Missing Description parameter" ); return; }
String[] description = request.getParameterValues( "Description.Value" );
if ( description != null && description.length > 0 ) {
ec2request.setAttribute(ImageAttribute.description);
ec2request.setDescription(description[0]);
} else {
//add all launch permissions to ec2request
ec2request = addLaunchPermImageAttribute(request, ec2request);
if (ec2request.getLaunchPermissionSet().length > 0)
ec2request.setAttribute(ImageAttribute.launchPermission);
else {
response.sendError(530, "Missing Attribute parameter - Description/LaunchPermission should be provided" );
return;
}
}
// -> execute the request
ModifyImageAttributeResponse EC2response = EC2SoapServiceImpl.toModifyImageAttributeResponse( ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( image ));
ModifyImageAttributeResponse EC2response = EC2SoapServiceImpl.toModifyImageAttributeResponse(
ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( ec2request ));
serializeResponse(response, EC2response);
}
private EC2ModifyImageAttribute addLaunchPermImageAttribute(HttpServletRequest request, EC2ModifyImageAttribute ec2request) {
String[] users = {".UserId", ".Group"};
String[] operations = {"LaunchPermission.Add.", "LaunchPermission.Remove."};
int nCount = 1;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
List<String> launchPermissionList = new ArrayList<String>();
do {
String[] launchPermissionAddGroup = request.getParameterValues( operations[j] + nCount + users[i] );
if (launchPermissionAddGroup != null && launchPermissionAddGroup.length > 0)
launchPermissionList.add(launchPermissionAddGroup[0]);
else
break;
nCount++;
} while (true);
if (nCount != 1) {
EC2ImageLaunchPermission ec2LaunchPermission = new EC2ImageLaunchPermission();
if (operations[j].contains("Add"))
ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add);
else
ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove);
for (String launchPerm : launchPermissionList) {
ec2LaunchPermission.addLaunchPermission(launchPerm);
}
ec2request.addLaunchPermission(ec2LaunchPermission);
nCount = 1;
}
}
}
return ec2request;
}
private void resetImageAttribute( HttpServletRequest request, HttpServletResponse response )
throws ADBException, XMLStreamException, IOException {
EC2Image image = new EC2Image();
EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute();
String[] imageId = request.getParameterValues( "ImageId" );
if ( null != imageId && 0 < imageId.length )
image.setId( imageId[0] );
else { response.sendError(530, "Missing ImageId parameter" ); return; }
if ( imageId != null && imageId.length > 0)
ec2request.setImageId(imageId[0]);
else {
response.sendError(530, "Missing ImageId parameter" );
return;
}
String[] attribute = request.getParameterValues( "Attribute" );
if ( attribute != null && attribute.length > 0 ) {
if (attribute[0].equalsIgnoreCase("launchPermission"))
ec2request.setAttribute(ImageAttribute.launchPermission);
else {
response.sendError(501, "Unsupported Attribute - only launchPermission supported" );
return;
}
} else {
response.sendError(530, "Missing Attribute parameter" );
return;
}
EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset);
ec2request.addLaunchPermission(launchPermission);
// -> execute the request
image.setDescription( "" );
ResetImageAttributeResponse EC2response = EC2SoapServiceImpl.toResetImageAttributeResponse( ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( image ));
ResetImageAttributeResponse EC2response = EC2SoapServiceImpl.toResetImageAttributeResponse(
ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( ec2request ));
serializeResponse(response, EC2response);
}

View File

@ -47,6 +47,7 @@ import com.cloud.bridge.service.core.ec2.EC2DescribeInstances;
import com.cloud.bridge.service.core.ec2.EC2DescribeInstancesResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs;
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairsResponse;
import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission;
import com.cloud.bridge.service.core.ec2.EC2ResourceTag;
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups;
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroupsResponse;
@ -595,31 +596,32 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
request.setImageId(miat.getImageId());
request.setAttribute(ImageAttribute.launchPermission);
if(launchPermOp.getAdd() != null){
request.setLaunchPermOperation(EC2ModifyImageAttribute.Operation.add);
setAccountOrGroupList(launchPermOp.getAdd().getItem(), request);
setAccountOrGroupList(launchPermOp.getAdd().getItem(), request, "add");
}else if(launchPermOp.getRemove() != null){
request.setLaunchPermOperation(EC2ModifyImageAttribute.Operation.remove);
setAccountOrGroupList(launchPermOp.getRemove().getItem(), request);
setAccountOrGroupList(launchPermOp.getRemove().getItem(), request, "remove");
}
return toModifyImageAttributeResponse( engine.modifyImageAttribute( request ));
}
throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - can only modify image description or launchPermission");
}
private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request){
List<String> launchPermissionAccountsOrGroupList = new ArrayList<String>();
private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request, String operation){
EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
if (operation.equalsIgnoreCase("add"))
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add);
else
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove);
for (LaunchPermissionItemType lpItem : items) {
if(lpItem.getGroup() != null){
launchPermissionAccountsOrGroupList.add(lpItem.getGroup());
launchPermission.addLaunchPermission(lpItem.getGroup());
}else if(lpItem.getUserId() != null){
launchPermissionAccountsOrGroupList.add(lpItem.getUserId());
launchPermission.addLaunchPermission(lpItem.getUserId());
}
}
request.setLaunchPermissionAccountsOrGroupList(launchPermissionAccountsOrGroupList);
request.addLaunchPermission(launchPermission);
}
/**
* Did not find a matching service offering so for now we just return disabled
@ -702,7 +704,9 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
if(elementType != null){
request.setImageId( riat.getImageId());
request.setAttribute(ImageAttribute.launchPermission);
request.setLaunchPermOperation(EC2ModifyImageAttribute.Operation.reset);
EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset);
request.addLaunchPermission(launchPermission);
return toResetImageAttributeResponse( engine.modifyImageAttribute( request ));
}
throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - can only reset image launchPermission" );

View File

@ -535,32 +535,6 @@ public class EC2Engine extends ManagerBase {
}
/** REST API calls this method.
* Modify an existing template
*
* @param request
* @return
*/
public boolean modifyImageAttribute( EC2Image request )
{
// TODO: This is incomplete
EC2DescribeImagesResponse images = new EC2DescribeImagesResponse();
try {
images = listTemplates( request.getId(), images );
EC2Image[] imageSet = images.getImageSet();
CloudStackTemplate resp = getApi().updateTemplate(request.getId(), null, request.getDescription(), null, imageSet[0].getName(), null, null);
if (resp != null) {
return true;
}
return false;
} catch( Exception e ) {
logger.error( "EC2 ModifyImage - ", e);
throw new EC2ServiceException(ServerError.InternalError, e.getMessage());
}
}
/**
* Modify an existing template
@ -572,32 +546,35 @@ public class EC2Engine extends ManagerBase {
{
try {
if(request.getAttribute().equals(ImageAttribute.launchPermission)){
String accounts = "";
Boolean isPublic = null;
EC2ModifyImageAttribute.Operation operation = request.getLaunchPermOperation();
List<String> accountOrGroupList = request.getLaunchPermissionAccountsList();
if(accountOrGroupList != null && !accountOrGroupList.isEmpty()){
boolean first = true;
for(String accountOrGroup : accountOrGroupList){
if("all".equalsIgnoreCase(accountOrGroup)){
if(operation.equals(EC2ModifyImageAttribute.Operation.add)){
isPublic = true;
EC2ImageLaunchPermission[] launchPermissions = request.getLaunchPermissionSet();
for (EC2ImageLaunchPermission launchPermission : launchPermissions) {
String accounts = "";
Boolean isPublic = null;
EC2ImageLaunchPermission.Operation operation = launchPermission.getLaunchPermOp();
List<String> accountOrGroupList = launchPermission.getLaunchPermissionList();
if(accountOrGroupList != null && !accountOrGroupList.isEmpty()){
boolean first = true;
for(String accountOrGroup : accountOrGroupList){
if("all".equalsIgnoreCase(accountOrGroup)){
if(operation.equals(EC2ImageLaunchPermission.Operation.add)){
isPublic = true;
}else{
isPublic = false;
}
}else{
isPublic = false;
if(!first){
accounts = accounts + ",";
}
accounts = accounts + accountOrGroup;
first = false;
}
}else{
if(!first){
accounts = accounts + ",";
}
accounts = accounts + accountOrGroup;
first = false;
}
}
CloudStackInfoResponse resp = getApi().updateTemplatePermissions(request.getImageId(), accounts, null, null, isPublic, operation.toString());
if (!resp.getSuccess())
return false;
}
CloudStackInfoResponse resp = getApi().updateTemplatePermissions(request.getImageId(), accounts, null, null, isPublic, operation.toString());
return resp.getSuccess();
return true;
}else if(request.getAttribute().equals(ImageAttribute.description)){
CloudStackTemplate resp = getApi().updateTemplate(request.getImageId(), null, request.getDescription(), null, null, null, null);
if (resp != null) {

View File

@ -0,0 +1,53 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.bridge.service.core.ec2;
import java.util.ArrayList;
import java.util.List;
public class EC2ImageLaunchPermission {
private Operation launchPermOperation;
public enum Operation{
add,
remove,
reset;
}
private List<String> launchPermissionList = new ArrayList<String>();
public EC2ImageLaunchPermission() {
launchPermOperation = null;
}
public void addLaunchPermission(String launchPermission) {
launchPermissionList.add(launchPermission);
}
public List<String> getLaunchPermissionList() {
return launchPermissionList;
}
public void setLaunchPermOp( Operation launchPermOperation ) {
this.launchPermOperation = launchPermOperation;
}
public Operation getLaunchPermOp() {
return this.launchPermOperation;
}
}

View File

@ -16,7 +16,7 @@
// under the License.
package com.cloud.bridge.service.core.ec2;
import java.util.ArrayList;
import java.util.List;
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute;
@ -28,15 +28,7 @@ public class EC2ModifyImageAttribute {
private String description;
private Boolean isPublic = null;
private Operation launchPermOperation = null;
public enum Operation{
add,
remove,
reset;
}
private List<String> launchPermissionAccountsOrGroupList;
private List<EC2ImageLaunchPermission> launchPermissionList = new ArrayList<EC2ImageLaunchPermission>();
public EC2ModifyImageAttribute() {
}
@ -65,31 +57,20 @@ public class EC2ModifyImageAttribute {
return this.description;
}
public void setLaunchPermissionAccountsOrGroupList(List<String> launchPermissionAccountsOrGroupList) {
this.launchPermissionAccountsOrGroupList = launchPermissionAccountsOrGroupList;
}
public List<String> getLaunchPermissionAccountsList() {
return launchPermissionAccountsOrGroupList;
}
public void setLaunchPermOperation( Operation launchPermOperation ) {
this.launchPermOperation = launchPermOperation;
}
public Operation getLaunchPermOperation() {
return this.launchPermOperation;
}
public void setIsPublic(Boolean isPublic) {
this.isPublic = isPublic;
}
public Boolean getIsPublic() {
return isPublic;
}
public void addLaunchPermission( EC2ImageLaunchPermission param ) {
launchPermissionList.add( param );
}
public EC2ImageLaunchPermission[] getLaunchPermissionSet() {
return launchPermissionList.toArray(new EC2ImageLaunchPermission[0]);
}
}