Skip to content

Commit 4e4edc9

Browse files
author
Prachi Damle
committed
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.
1 parent 951cba9 commit 4e4edc9

5 files changed

Lines changed: 193 additions & 107 deletions

File tree

awsapi/src/com/cloud/bridge/service/EC2RestServlet.java

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
import com.amazon.ec2.DisassociateAddressResponse;
8888
import com.amazon.ec2.GetPasswordDataResponse;
8989
import com.amazon.ec2.ImportKeyPairResponse;
90+
import com.amazon.ec2.LaunchPermissionItemType;
9091
import com.amazon.ec2.ModifyImageAttributeResponse;
9192
import com.amazon.ec2.RebootInstancesResponse;
9293
import com.amazon.ec2.RegisterImageResponse;
@@ -123,10 +124,13 @@
123124
import com.cloud.bridge.service.core.ec2.EC2Filter;
124125
import com.cloud.bridge.service.core.ec2.EC2GroupFilterSet;
125126
import com.cloud.bridge.service.core.ec2.EC2Image;
127+
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute;
128+
import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission;
126129
import com.cloud.bridge.service.core.ec2.EC2ImportKeyPair;
127130
import com.cloud.bridge.service.core.ec2.EC2InstanceFilterSet;
128131
import com.cloud.bridge.service.core.ec2.EC2IpPermission;
129132
import com.cloud.bridge.service.core.ec2.EC2KeyPairFilterSet;
133+
import com.cloud.bridge.service.core.ec2.EC2ModifyImageAttribute;
130134
import com.cloud.bridge.service.core.ec2.EC2RebootInstances;
131135
import com.cloud.bridge.service.core.ec2.EC2RegisterImage;
132136
import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress;
@@ -1021,38 +1025,105 @@ private void registerImage( HttpServletRequest request, HttpServletResponse resp
10211025
serializeResponse(response, EC2response);
10221026
}
10231027

1024-
private void modifyImageAttribute( HttpServletRequest request, HttpServletResponse response )
1028+
private void modifyImageAttribute( HttpServletRequest request, HttpServletResponse response )
10251029
throws ADBException, XMLStreamException, IOException {
1026-
EC2Image image = new EC2Image();
1030+
EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute();
10271031

1028-
// -> its interesting to note that the SOAP API docs has description but the REST API docs do not
1029-
String[] imageId = request.getParameterValues( "ImageId" );
1030-
if ( null != imageId && 0 < imageId.length )
1031-
image.setId( imageId[0] );
1032-
else { response.sendError(530, "Missing ImageId parameter" ); return; }
1032+
String[] imageId = request.getParameterValues( "ImageId" );
1033+
if ( imageId != null && imageId.length > 0 )
1034+
ec2request.setImageId( imageId[0]);
1035+
else {
1036+
response.sendError(530, "Missing ImageId parameter" );
1037+
return;
1038+
}
10331039

1034-
String[] description = request.getParameterValues( "Description" );
1035-
if ( null != description && 0 < description.length )
1036-
image.setDescription( description[0] );
1037-
else { response.sendError(530, "Missing Description parameter" ); return; }
1040+
String[] description = request.getParameterValues( "Description.Value" );
1041+
if ( description != null && description.length > 0 ) {
1042+
ec2request.setAttribute(ImageAttribute.description);
1043+
ec2request.setDescription(description[0]);
1044+
} else {
1045+
//add all launch permissions to ec2request
1046+
ec2request = addLaunchPermImageAttribute(request, ec2request);
1047+
if (ec2request.getLaunchPermissionSet().length > 0)
1048+
ec2request.setAttribute(ImageAttribute.launchPermission);
1049+
else {
1050+
response.sendError(530, "Missing Attribute parameter - Description/LaunchPermission should be provided" );
1051+
return;
1052+
}
1053+
}
10381054

10391055
// -> execute the request
1040-
ModifyImageAttributeResponse EC2response = EC2SoapServiceImpl.toModifyImageAttributeResponse( ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( image ));
1056+
ModifyImageAttributeResponse EC2response = EC2SoapServiceImpl.toModifyImageAttributeResponse(
1057+
ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( ec2request ));
10411058
serializeResponse(response, EC2response);
10421059
}
10431060

1061+
private EC2ModifyImageAttribute addLaunchPermImageAttribute(HttpServletRequest request, EC2ModifyImageAttribute ec2request) {
1062+
String[] users = {".UserId", ".Group"};
1063+
String[] operations = {"LaunchPermission.Add.", "LaunchPermission.Remove."};
1064+
int nCount = 1;
1065+
1066+
for (int i = 0; i < 2; i++) {
1067+
for (int j = 0; j < 2; j++) {
1068+
List<String> launchPermissionList = new ArrayList<String>();
1069+
do {
1070+
String[] launchPermissionAddGroup = request.getParameterValues( operations[j] + nCount + users[i] );
1071+
if (launchPermissionAddGroup != null && launchPermissionAddGroup.length > 0)
1072+
launchPermissionList.add(launchPermissionAddGroup[0]);
1073+
else
1074+
break;
1075+
nCount++;
1076+
} while (true);
1077+
if (nCount != 1) {
1078+
EC2ImageLaunchPermission ec2LaunchPermission = new EC2ImageLaunchPermission();
1079+
if (operations[j].contains("Add"))
1080+
ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add);
1081+
else
1082+
ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove);
1083+
for (String launchPerm : launchPermissionList) {
1084+
ec2LaunchPermission.addLaunchPermission(launchPerm);
1085+
}
1086+
ec2request.addLaunchPermission(ec2LaunchPermission);
1087+
nCount = 1;
1088+
}
1089+
}
1090+
}
1091+
1092+
return ec2request;
1093+
}
1094+
10441095
private void resetImageAttribute( HttpServletRequest request, HttpServletResponse response )
10451096
throws ADBException, XMLStreamException, IOException {
1046-
EC2Image image = new EC2Image();
1097+
EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute();
10471098

10481099
String[] imageId = request.getParameterValues( "ImageId" );
1049-
if ( null != imageId && 0 < imageId.length )
1050-
image.setId( imageId[0] );
1051-
else { response.sendError(530, "Missing ImageId parameter" ); return; }
1100+
if ( imageId != null && imageId.length > 0)
1101+
ec2request.setImageId(imageId[0]);
1102+
else {
1103+
response.sendError(530, "Missing ImageId parameter" );
1104+
return;
1105+
}
1106+
1107+
String[] attribute = request.getParameterValues( "Attribute" );
1108+
if ( attribute != null && attribute.length > 0 ) {
1109+
if (attribute[0].equalsIgnoreCase("launchPermission"))
1110+
ec2request.setAttribute(ImageAttribute.launchPermission);
1111+
else {
1112+
response.sendError(501, "Unsupported Attribute - only launchPermission supported" );
1113+
return;
1114+
}
1115+
} else {
1116+
response.sendError(530, "Missing Attribute parameter" );
1117+
return;
1118+
}
1119+
1120+
EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
1121+
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset);
1122+
ec2request.addLaunchPermission(launchPermission);
10521123

10531124
// -> execute the request
1054-
image.setDescription( "" );
1055-
ResetImageAttributeResponse EC2response = EC2SoapServiceImpl.toResetImageAttributeResponse( ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( image ));
1125+
ResetImageAttributeResponse EC2response = EC2SoapServiceImpl.toResetImageAttributeResponse(
1126+
ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute( ec2request ));
10561127
serializeResponse(response, EC2response);
10571128
}
10581129

awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.cloud.bridge.service.core.ec2.EC2DescribeInstancesResponse;
4848
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs;
4949
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairsResponse;
50+
import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission;
5051
import com.cloud.bridge.service.core.ec2.EC2ResourceTag;
5152
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups;
5253
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroupsResponse;
@@ -595,31 +596,32 @@ public ModifyImageAttributeResponse modifyImageAttribute(ModifyImageAttribute mo
595596
request.setImageId(miat.getImageId());
596597
request.setAttribute(ImageAttribute.launchPermission);
597598
if(launchPermOp.getAdd() != null){
598-
request.setLaunchPermOperation(EC2ModifyImageAttribute.Operation.add);
599-
setAccountOrGroupList(launchPermOp.getAdd().getItem(), request);
599+
setAccountOrGroupList(launchPermOp.getAdd().getItem(), request, "add");
600600
}else if(launchPermOp.getRemove() != null){
601-
request.setLaunchPermOperation(EC2ModifyImageAttribute.Operation.remove);
602-
setAccountOrGroupList(launchPermOp.getRemove().getItem(), request);
601+
setAccountOrGroupList(launchPermOp.getRemove().getItem(), request, "remove");
603602
}
604603
return toModifyImageAttributeResponse( engine.modifyImageAttribute( request ));
605604
}
606605
throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - can only modify image description or launchPermission");
607606
}
608607

609-
private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request){
610-
611-
List<String> launchPermissionAccountsOrGroupList = new ArrayList<String>();
612-
608+
private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request, String operation){
609+
EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
610+
611+
if (operation.equalsIgnoreCase("add"))
612+
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add);
613+
else
614+
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove);
615+
613616
for (LaunchPermissionItemType lpItem : items) {
614617
if(lpItem.getGroup() != null){
615-
launchPermissionAccountsOrGroupList.add(lpItem.getGroup());
618+
launchPermission.addLaunchPermission(lpItem.getGroup());
616619
}else if(lpItem.getUserId() != null){
617-
launchPermissionAccountsOrGroupList.add(lpItem.getUserId());
620+
launchPermission.addLaunchPermission(lpItem.getUserId());
618621
}
619622
}
620-
621-
request.setLaunchPermissionAccountsOrGroupList(launchPermissionAccountsOrGroupList);
622623

624+
request.addLaunchPermission(launchPermission);
623625
}
624626
/**
625627
* Did not find a matching service offering so for now we just return disabled
@@ -702,7 +704,9 @@ public ResetImageAttributeResponse resetImageAttribute(ResetImageAttribute reset
702704
if(elementType != null){
703705
request.setImageId( riat.getImageId());
704706
request.setAttribute(ImageAttribute.launchPermission);
705-
request.setLaunchPermOperation(EC2ModifyImageAttribute.Operation.reset);
707+
EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
708+
launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset);
709+
request.addLaunchPermission(launchPermission);
706710
return toResetImageAttributeResponse( engine.modifyImageAttribute( request ));
707711
}
708712
throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - can only reset image launchPermission" );

awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -535,32 +535,6 @@ public boolean deleteSnapshot(String snapshotId) {
535535
}
536536

537537

538-
/** REST API calls this method.
539-
* Modify an existing template
540-
*
541-
* @param request
542-
* @return
543-
*/
544-
public boolean modifyImageAttribute( EC2Image request )
545-
{
546-
// TODO: This is incomplete
547-
EC2DescribeImagesResponse images = new EC2DescribeImagesResponse();
548-
549-
try {
550-
images = listTemplates( request.getId(), images );
551-
EC2Image[] imageSet = images.getImageSet();
552-
553-
CloudStackTemplate resp = getApi().updateTemplate(request.getId(), null, request.getDescription(), null, imageSet[0].getName(), null, null);
554-
if (resp != null) {
555-
return true;
556-
}
557-
return false;
558-
} catch( Exception e ) {
559-
logger.error( "EC2 ModifyImage - ", e);
560-
throw new EC2ServiceException(ServerError.InternalError, e.getMessage());
561-
}
562-
}
563-
564538

565539
/**
566540
* Modify an existing template
@@ -572,32 +546,35 @@ public boolean modifyImageAttribute( EC2ModifyImageAttribute request )
572546
{
573547
try {
574548
if(request.getAttribute().equals(ImageAttribute.launchPermission)){
575-
576-
String accounts = "";
577-
Boolean isPublic = null;
578-
EC2ModifyImageAttribute.Operation operation = request.getLaunchPermOperation();
579-
580-
List<String> accountOrGroupList = request.getLaunchPermissionAccountsList();
581-
if(accountOrGroupList != null && !accountOrGroupList.isEmpty()){
582-
boolean first = true;
583-
for(String accountOrGroup : accountOrGroupList){
584-
if("all".equalsIgnoreCase(accountOrGroup)){
585-
if(operation.equals(EC2ModifyImageAttribute.Operation.add)){
586-
isPublic = true;
549+
EC2ImageLaunchPermission[] launchPermissions = request.getLaunchPermissionSet();
550+
for (EC2ImageLaunchPermission launchPermission : launchPermissions) {
551+
String accounts = "";
552+
Boolean isPublic = null;
553+
EC2ImageLaunchPermission.Operation operation = launchPermission.getLaunchPermOp();
554+
List<String> accountOrGroupList = launchPermission.getLaunchPermissionList();
555+
if(accountOrGroupList != null && !accountOrGroupList.isEmpty()){
556+
boolean first = true;
557+
for(String accountOrGroup : accountOrGroupList){
558+
if("all".equalsIgnoreCase(accountOrGroup)){
559+
if(operation.equals(EC2ImageLaunchPermission.Operation.add)){
560+
isPublic = true;
561+
}else{
562+
isPublic = false;
563+
}
587564
}else{
588-
isPublic = false;
565+
if(!first){
566+
accounts = accounts + ",";
567+
}
568+
accounts = accounts + accountOrGroup;
569+
first = false;
589570
}
590-
}else{
591-
if(!first){
592-
accounts = accounts + ",";
593-
}
594-
accounts = accounts + accountOrGroup;
595-
first = false;
596571
}
597572
}
573+
CloudStackInfoResponse resp = getApi().updateTemplatePermissions(request.getImageId(), accounts, null, null, isPublic, operation.toString());
574+
if (!resp.getSuccess())
575+
return false;
598576
}
599-
CloudStackInfoResponse resp = getApi().updateTemplatePermissions(request.getImageId(), accounts, null, null, isPublic, operation.toString());
600-
return resp.getSuccess();
577+
return true;
601578
}else if(request.getAttribute().equals(ImageAttribute.description)){
602579
CloudStackTemplate resp = getApi().updateTemplate(request.getImageId(), null, request.getDescription(), null, null, null, null);
603580
if (resp != null) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.bridge.service.core.ec2;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
22+
public class EC2ImageLaunchPermission {
23+
24+
private Operation launchPermOperation;
25+
public enum Operation{
26+
add,
27+
remove,
28+
reset;
29+
}
30+
31+
private List<String> launchPermissionList = new ArrayList<String>();
32+
33+
public EC2ImageLaunchPermission() {
34+
launchPermOperation = null;
35+
}
36+
37+
public void addLaunchPermission(String launchPermission) {
38+
launchPermissionList.add(launchPermission);
39+
}
40+
41+
public List<String> getLaunchPermissionList() {
42+
return launchPermissionList;
43+
}
44+
45+
public void setLaunchPermOp( Operation launchPermOperation ) {
46+
this.launchPermOperation = launchPermOperation;
47+
}
48+
49+
public Operation getLaunchPermOp() {
50+
return this.launchPermOperation;
51+
}
52+
53+
}

0 commit comments

Comments
 (0)