diff --git a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java index 222ef49084f..4f11c7c5d42 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java +++ b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java @@ -32,6 +32,7 @@ import com.cloud.bridge.service.core.ec2.EC2CreateImage; import com.cloud.bridge.service.core.ec2.EC2CreateImageResponse; import com.cloud.bridge.service.core.ec2.EC2CreateKeyPair; import com.cloud.bridge.service.core.ec2.EC2CreateVolume; +import com.cloud.bridge.service.core.ec2.EC2Tags; import com.cloud.bridge.service.core.ec2.EC2DeleteKeyPair; import com.cloud.bridge.service.core.ec2.EC2DescribeAddresses; import com.cloud.bridge.service.core.ec2.EC2DescribeAddressesResponse; @@ -45,10 +46,13 @@ 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.EC2ResourceTag; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroupsResponse; import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshots; import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshotsResponse; +import com.cloud.bridge.service.core.ec2.EC2DescribeTags; +import com.cloud.bridge.service.core.ec2.EC2DescribeTagsResponse; import com.cloud.bridge.service.core.ec2.EC2DescribeVolumes; import com.cloud.bridge.service.core.ec2.EC2DescribeVolumesResponse; import com.cloud.bridge.service.core.ec2.EC2DisassociateAddress; @@ -68,6 +72,8 @@ import com.cloud.bridge.service.core.ec2.EC2PasswordData; import com.cloud.bridge.service.core.ec2.EC2RebootInstances; import com.cloud.bridge.service.core.ec2.EC2RegisterImage; import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress; +import com.cloud.bridge.service.core.ec2.EC2TagKeyValue; +import com.cloud.bridge.service.core.ec2.EC2TagTypeId; import com.cloud.bridge.service.core.ec2.EC2RunInstances; import com.cloud.bridge.service.core.ec2.EC2RunInstancesResponse; import com.cloud.bridge.service.core.ec2.EC2SSHKeyPair; @@ -78,6 +84,7 @@ import com.cloud.bridge.service.core.ec2.EC2StartInstances; import com.cloud.bridge.service.core.ec2.EC2StartInstancesResponse; import com.cloud.bridge.service.core.ec2.EC2StopInstances; import com.cloud.bridge.service.core.ec2.EC2StopInstancesResponse; +import com.cloud.bridge.service.core.ec2.EC2TagsFilterSet; import com.cloud.bridge.service.core.ec2.EC2Volume; import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet; import com.cloud.bridge.service.exception.EC2ServiceException; @@ -198,6 +205,89 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { return toCreateVolumeResponse( engine.createVolume( request )); } + public CreateTagsResponse createTags(CreateTags createTags) { + EC2Tags request = new EC2Tags(); + CreateTagsType ctt = createTags.getCreateTags(); + + ResourceIdSetType resourceIds = ctt.getResourcesSet(); + ResourceTagSetType resourceTags = ctt.getTagSet(); + request = toResourceTypeAndIds(resourceIds); + //add resource tag's to the request + if (resourceTags != null) { + ResourceTagSetItemType[] items = resourceTags.getItem(); + if (items != null) { + for( int i=0; i < items.length; i++ ) { + EC2TagKeyValue param1 = new EC2TagKeyValue(); + param1.setKey(items[i].getKey()); + param1.setValue(items[i].getValue()); + request.addResourceTag(param1); + } + } + } + return toCreateTagsResponse( engine.modifyTags( request, "create")); + } + + public DeleteTagsResponse deleteTags(DeleteTags deleteTags) { + EC2Tags request = new EC2Tags(); + DeleteTagsType dtt = deleteTags.getDeleteTags(); + + ResourceIdSetType resourceIds = dtt.getResourcesSet(); + DeleteTagsSetType resourceTags = dtt.getTagSet(); + request = toResourceTypeAndIds(resourceIds); + //add resource tag's to the request + if (resourceTags != null) { + DeleteTagsSetItemType[] items = resourceTags.getItem(); + if (items != null) { + for( int i=0; i < items.length; i++ ) { + EC2TagKeyValue param1 = new EC2TagKeyValue(); + param1.setKey(items[i].getKey()); + if (items[i].getValue() != null) + param1.setValue(items[i].getValue()); + request.addResourceTag(param1); + } + } + } + return toDeleteTagsResponse( engine.modifyTags( request, "delete")); + } + + private EC2Tags toResourceTypeAndIds(ResourceIdSetType resourceIds) { + EC2Tags request = new EC2Tags(); + //add resource-type and resource-id's to the request + if (resourceIds != null) { + ResourceIdSetItemType[] items = resourceIds.getItem(); + List resourceTypeList = new ArrayList(); + if (items != null) { + for( int i=0; i < items.length; i++ ) { + String resourceType = items[i].getResourceId().split(":")[0]; + if (resourceTypeList.isEmpty()) + resourceTypeList.add(resourceType); + else { + Boolean existsInList = false; + for (String addedResourceType : resourceTypeList) { + if (addedResourceType.equalsIgnoreCase(resourceType)) { + existsInList = true; + break; + } + } + if (!existsInList) + resourceTypeList.add(resourceType); + } + } + for (String resourceType : resourceTypeList){ + EC2TagTypeId param1 = new EC2TagTypeId(); + param1.setResourceType(resourceType); + for( int i=0; i < items.length; i++ ) { + String[] resourceTag = items[i].getResourceId().split(":"); + if (resourceType.equals(resourceTag[0])) + param1.addResourceId(resourceTag[1]); + } + request.addResourceType(param1); + } + } + } + return request; + } + public DeleteSecurityGroupResponse deleteSecurityGroup(DeleteSecurityGroup deleteSecurityGroup) { DeleteSecurityGroupType sgt = deleteSecurityGroup.getDeleteSecurityGroup(); return toDeleteSecurityGroupResponse( engine.deleteSecurityGroup( sgt.getGroupName())); @@ -433,7 +523,18 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { return toDescribeSnapshotsResponse(engine.handleRequest(request)); } - + public DescribeTagsResponse describeTags(DescribeTags decsribeTags) { + EC2DescribeTags request = new EC2DescribeTags(); + DescribeTagsType dtt = decsribeTags.getDescribeTags(); + + FilterSetType fst = dtt.getFilterSet(); + + if (fst != null) + request.setFilterSet( toTagsFilterSet( fst )); + + return toDescribeTagsResponse(engine.describeTags(request)); + } + public DescribeVolumesResponse describeVolumes(DescribeVolumes describeVolumes) { EC2DescribeVolumes request = new EC2DescribeVolumes(); @@ -1093,8 +1194,28 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { } return azfs; } - - + + private EC2TagsFilterSet toTagsFilterSet( FilterSetType fst ) { + EC2TagsFilterSet tfs = new EC2TagsFilterSet(); + + FilterType[] items = fst.getItem(); + if (items != null) { + for (FilterType item : items) { + EC2Filter oneFilter = new EC2Filter(); + String filterName = item.getName(); + oneFilter.setName( filterName ); + + ValueSetType vft = item.getValueSet(); + ValueType[] valueItems = vft.getItem(); + for (ValueType valueItem : valueItems) { + oneFilter.addValueEncoded( valueItem.getValue()); + } + tfs.addFilter( oneFilter ); + } + } + return tfs; + } + // toMethods public static DescribeVolumesResponse toDescribeVolumesResponse( EC2DescribeVolumesResponse engineResponse ) { @@ -1930,7 +2051,48 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { response.setRevokeSecurityGroupIngressResponse( param1 ); return response; } - + + public static CreateTagsResponse toCreateTagsResponse( boolean success ) { + CreateTagsResponse response = new CreateTagsResponse(); + CreateTagsResponseType param1 = new CreateTagsResponseType(); + + param1.set_return(success); + param1.setRequestId( UUID.randomUUID().toString()); + response.setCreateTagsResponse(param1); + return response; + } + + public static DeleteTagsResponse toDeleteTagsResponse( boolean success ) { + DeleteTagsResponse response = new DeleteTagsResponse(); + DeleteTagsResponseType param1 = new DeleteTagsResponseType(); + + param1.set_return(success); + param1.setRequestId( UUID.randomUUID().toString()); + response.setDeleteTagsResponse(param1); + return response; + } + + public static DescribeTagsResponse toDescribeTagsResponse( EC2DescribeTagsResponse engineResponse) { + DescribeTagsResponse response = new DescribeTagsResponse(); + DescribeTagsResponseType param1 = new DescribeTagsResponseType(); + + EC2ResourceTag[] tags = engineResponse.getTagsSet(); + TagSetType param2 = new TagSetType(); + for (EC2ResourceTag tag : tags) { + TagSetItemType param3 = new TagSetItemType(); + param3.setResourceId(tag.getResourceId()); + param3.setResourceType(tag.getResourceType()); + param3.setKey(tag.getKey()); + if (tag.getValue() != null) + param3.setValue(tag.getValue()); + param2.addItem(param3); + } + param1.setTagSet(param2); + param1.setRequestId( UUID.randomUUID().toString()); + response.setDescribeTagsResponse(param1); + return response; + } + public DescribeKeyPairsResponse describeKeyPairs(DescribeKeyPairs describeKeyPairs) { EC2DescribeKeyPairs ec2Request = new EC2DescribeKeyPairs(); @@ -2115,10 +2277,6 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public CreateSubnetResponse createSubnet(CreateSubnet createSubnet) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } - - public CreateTagsResponse createTags(CreateTags createTags) { - throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); - } public CreateVpcResponse createVpc(CreateVpc createVpc) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); @@ -2155,10 +2313,6 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public DeleteSubnetResponse deleteSubnet(DeleteSubnet deleteSubnet) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } - - public DeleteTagsResponse deleteTags(DeleteTags deleteTags) { - throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); - } public DeleteVpcResponse deleteVpc(DeleteVpc deleteVpc) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); @@ -2228,10 +2382,6 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } - public DescribeTagsResponse describeTags(DescribeTags describeTags) { - throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); - } - public DescribeVpcsResponse describeVpcs(DescribeVpcs describeVpcs) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } @@ -2283,4 +2433,4 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public ResetSnapshotAttributeResponse resetSnapshotAttribute(ResetSnapshotAttribute resetSnapshotAttribute) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } -} \ No newline at end of file +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeTags.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeTags.java new file mode 100644 index 00000000000..ee609ad87cf --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeTags.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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; + +public class EC2DescribeTags { + + private EC2TagsFilterSet tfs = null; + + public EC2DescribeTags() { + } + + public EC2TagsFilterSet getFilterSet() { + return tfs; + } + + public void setFilterSet( EC2TagsFilterSet param ) { + tfs = param; + } +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeTagsResponse.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeTagsResponse.java new file mode 100644 index 00000000000..6ca6357e18a --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeTagsResponse.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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 EC2DescribeTagsResponse { + + private List tagsSet = new ArrayList(); + + public EC2DescribeTagsResponse() { + } + + public void addTags( EC2ResourceTag param ) { + tagsSet.add( param ); + } + + public EC2ResourceTag[] getTagsSet() { + return tagsSet.toArray(new EC2ResourceTag[0]); + } +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java index 3c14b893a9d..df869561293 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java @@ -58,6 +58,7 @@ import com.cloud.stack.models.CloudStackNic; import com.cloud.stack.models.CloudStackOsType; import com.cloud.stack.models.CloudStackPasswordData; import com.cloud.stack.models.CloudStackResourceLimit; +import com.cloud.stack.models.CloudStackResourceTag; import com.cloud.stack.models.CloudStackSecurityGroup; import com.cloud.stack.models.CloudStackSecurityGroupIngress; import com.cloud.stack.models.CloudStackServiceOffering; @@ -1310,6 +1311,80 @@ public class EC2Engine { } } + /** + * Create/Delete tags + * + * @param request + * @param operation + * @return + */ + public boolean modifyTags( EC2Tags request, String operation) { + try { + List resourceTagList = new ArrayList(); + for ( EC2TagKeyValue resourceTag : request.getResourceTags()){ + CloudStackKeyValue pair = new CloudStackKeyValue(); + pair.setKeyValue(resourceTag.getKey(), resourceTag.getValue()); + resourceTagList.add(pair); + } + EC2TagTypeId[] resourceTypeSet = request.getResourceTypeSet(); + for (EC2TagTypeId resourceType : resourceTypeSet) { + String cloudStackResourceType = mapToCloudStackResourceType(resourceType.getResourceType()); + List resourceIdList = new ArrayList(); + for ( String resourceId : resourceType.getResourceIds()) + resourceIdList.add(resourceId); + CloudStackInfoResponse resp = new CloudStackInfoResponse(); + if (operation.equalsIgnoreCase("create")) + resp = getApi().createTags(cloudStackResourceType, resourceIdList, resourceTagList); + else if(operation.equalsIgnoreCase("delete")) + resp = getApi().deleteTags(cloudStackResourceType, resourceIdList, resourceTagList); + else + throw new EC2ServiceException( ServerError.InternalError, "Unknown operation." ); + if (resp.getSuccess() == false) + return false; + } + return true; + } catch (Exception e){ + logger.error( "EC2 Create/Delete Tags - ", e); + throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? + e.getMessage() : "An unexpected error occurred."); + } + } + + /** + * Describe tags + * + * @param request + * @return + */ + public EC2DescribeTagsResponse describeTags (EC2DescribeTags request) { + try { + EC2DescribeTagsResponse tagResponse = new EC2DescribeTagsResponse(); + List resourceTagList = getApi().listTags(null, null, null, true, null); + + List tagList = new ArrayList(); + if (resourceTagList != null && resourceTagList.size() > 0) { + for (CloudStackResourceTag resourceTag: resourceTagList) { + EC2ResourceTag tag = new EC2ResourceTag(); + tag.setResourceId(resourceTag.getResourceId()); + tag.setResourceType(mapToAmazonResourceType(resourceTag.getResourceType())); + tag.setKey(resourceTag.getKey()); + if (resourceTag.getValue() != null) + tag.setValue(resourceTag.getValue()); + tagResponse.addTags(tag); + } + } + + EC2TagsFilterSet tfs = request.getFilterSet(); + if (tfs == null) + return tagResponse; + else + return tfs.evaluate(tagResponse); + } catch(Exception e) { + logger.error("EC2 DescribeTags - ", e); + throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + } + } + /** * Reboot an instance or instances * @@ -2244,6 +2319,36 @@ public class EC2Engine { return "error"; } + /** + * Map Amazon resourceType to CloudStack resourceType + * + * @param Amazon resourceType + * @return CloudStack resourceType + */ + private String mapToCloudStackResourceType( String resourceType) { + if (resourceType.equalsIgnoreCase("image")) + return("template"); + else if(resourceType.equalsIgnoreCase("instance")) + return("userVm"); + else + return resourceType; + } + + /** + * Map Amazon resourceType to CloudStack resourceType + * + * @param CloudStack resourceType + * @return Amazon resourceType + */ + private String mapToAmazonResourceType( String resourceType) { + if (resourceType.equalsIgnoreCase("template")) + return("image"); + else if(resourceType.equalsIgnoreCase("userVm")) + return("instance"); + else + return (resourceType.toLowerCase()); + } + /** * Stop an instance * Wait until one specific VM has stopped diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ResourceTag.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ResourceTag.java new file mode 100644 index 00000000000..0cf0cb1a07a --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ResourceTag.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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; + +public class EC2ResourceTag { + private String resourceId; + private String resourceType; + private String key; + private String value; + + public EC2ResourceTag() { + resourceId = null; + resourceType = null; + key = null; + value = null; + } + + public void setResourceId( String resourceId ) { + this.resourceId = resourceId; + } + + public String getResourceId() { + return this.resourceId; + } + + public void setResourceType( String resourceType ) { + this.resourceType = resourceType; + } + + public String getResourceType() { + return this.resourceType; + } + + public void setKey( String key ) { + this.key = key; + } + + public String getKey() { + return this.key; + } + + public void setValue( String value ) { + this.value = value; + } + + public String getValue() { + return this.value; + } +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagKeyValue.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagKeyValue.java new file mode 100644 index 00000000000..159e2282c95 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagKeyValue.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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; + +public class EC2TagKeyValue { + private String key; + private String value; + + public EC2TagKeyValue() { + key = null; + value = null; + } + + public void setKey( String key ) { + this.key = key; + } + + public String getKey() { + return this.key; + } + + public void setValue( String value ) { + this.value = value; + } + + public String getValue() { + return this.value; + } +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagTypeId.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagTypeId.java new file mode 100644 index 00000000000..25ead94224b --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagTypeId.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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 EC2TagTypeId { + + private String resourceType; + private List resourceIdSet = new ArrayList(); + + public EC2TagTypeId() { + resourceType = null; + } + + public void setResourceType( String resourceType ) { + this.resourceType = resourceType; + } + + public String getResourceType() { + return this.resourceType; + } + + public void addResourceId( String param ) { + resourceIdSet.add( param ); + } + + public String[] getResourceIds() { + return resourceIdSet.toArray(new String[0]); + } +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Tags.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Tags.java new file mode 100644 index 00000000000..dcc5915ab6f --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Tags.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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 EC2Tags { + + private List resourceTypeSet = new ArrayList(); + private List resourceTagSet = new ArrayList(); + + public void addResourceType( EC2TagTypeId param ) { + resourceTypeSet.add( param ); + } + + public EC2TagTypeId[] getResourceTypeSet() { + return resourceTypeSet.toArray(new EC2TagTypeId[0]); + } + + public void addResourceTag( EC2TagKeyValue param ) { + resourceTagSet.add( param ); + } + + public EC2TagKeyValue[] getResourceTags() { + return resourceTagSet.toArray(new EC2TagKeyValue[0]); + } +} + diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java new file mode 100644 index 00000000000..cccaf198254 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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.text.ParseException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.cloud.bridge.service.exception.EC2ServiceException; + +public class EC2TagsFilterSet { + protected final static Logger logger = Logger.getLogger(EC2TagsFilterSet.class); + + protected List filterSet = new ArrayList(); + + private Map filterTypes = new HashMap(); + + public EC2TagsFilterSet() { + filterTypes.put( "resource-id", "String" ); + filterTypes.put( "resource-type", "String" ); + filterTypes.put( "key", "String" ); + filterTypes.put( "value", "String" ); + } + + public void addFilter( EC2Filter param ) { + String filterName = param.getName(); + String value = (String) filterTypes.get( filterName ); + + if (null == value) + throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); + + if (null != value && value.equalsIgnoreCase( "null" )) + throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + + filterSet.add( param ); + } + + public EC2Filter[] getFilterSet() { + return filterSet.toArray(new EC2Filter[0]); + } + + public EC2DescribeTagsResponse evaluate( EC2DescribeTagsResponse sampleList) throws ParseException { + EC2DescribeTagsResponse resultList = new EC2DescribeTagsResponse(); + + boolean matched; + + EC2ResourceTag[] tagSet = sampleList.getTagsSet(); + EC2Filter[] filterSet = getFilterSet(); + for (EC2ResourceTag tag : tagSet) { + matched = true; + for (EC2Filter filter : filterSet) { + if (!filterMatched(tag, filter)) { + matched = false; + break; + } + } + if (matched == true) + resultList.addTags(tag); + } + return resultList; + } + + private boolean filterMatched( EC2ResourceTag tag, EC2Filter filter ) throws ParseException { + String filterName = filter.getName(); + String[] valueSet = filter.getValueSet(); + + if ( filterName.equalsIgnoreCase("resource-id")) { + return containsString(tag.getResourceId(), valueSet); + } else if ( filterName.equalsIgnoreCase("resource-type")) { + return containsString(tag.getResourceType(), valueSet); + } else if ( filterName.equalsIgnoreCase("key")) { + return containsString(tag.getKey(), valueSet); + } else if ( filterName.equalsIgnoreCase("value")) { + return containsString(tag.getValue(), valueSet); + } else + return false; + } + + private boolean containsString( String lookingFor, String[] set ){ + if (lookingFor == null) + return false; + + for (String filter: set) { + if (lookingFor.matches( filter )) return true; + } + return false; + } +} diff --git a/awsapi/src/com/cloud/stack/CloudStackApi.java b/awsapi/src/com/cloud/stack/CloudStackApi.java index e1ad5824070..14dfe747392 100644 --- a/awsapi/src/com/cloud/stack/CloudStackApi.java +++ b/awsapi/src/com/cloud/stack/CloudStackApi.java @@ -41,6 +41,7 @@ import com.cloud.stack.models.CloudStackOsType; import com.cloud.stack.models.CloudStackPasswordData; import com.cloud.stack.models.CloudStackPortForwardingRule; import com.cloud.stack.models.CloudStackResourceLimit; +import com.cloud.stack.models.CloudStackResourceTag; import com.cloud.stack.models.CloudStackSecurityGroup; import com.cloud.stack.models.CloudStackSecurityGroupIngress; import com.cloud.stack.models.CloudStackServiceOffering; @@ -972,7 +973,81 @@ public class CloudStackApi { } return _client.call(cmd, apiKey, secretKey, true, ApiConstants.EXTRACT_VOLUME_RESPONSE, ApiConstants.VOLUME, CloudStackExtractTemplate.class); } - + + //Tags + /** + * Create tags + * + * @param resource type + * @param resource id's + * @param tags + * @return + * @throws Exception + * + */ + public CloudStackInfoResponse createTags(String resourceType, ListresourceIds, + List resourceTags) throws Exception { + CloudStackCommand cmd = new CloudStackCommand(ApiConstants.CREATE_TAGS); + cmd = setParams(cmd, resourceType, resourceIds, resourceTags); + return _client.call(cmd, apiKey, secretKey, true, ApiConstants.CREATE_TAGS_RESPONSE, + null, CloudStackInfoResponse.class); + } + + /** + * Delete tags + * + * @param resource type + * @param resource id's + * @param tags + * @return + * @throws Exception + * + */ + public CloudStackInfoResponse deleteTags(String resourceType, ListresourceIds, + List resourceTags) throws Exception { + CloudStackCommand cmd = new CloudStackCommand(ApiConstants.DELETE_TAGS); + cmd = setParams(cmd, resourceType, resourceIds, resourceTags); + return _client.call(cmd, apiKey, secretKey, true, ApiConstants.DELETE_TAGS_RESPONSE, + null, CloudStackInfoResponse.class); + } + + public List listTags(String account, String domainId, + Boolean isRecursive, Boolean listAll, String keyWord) throws Exception { + CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_TAGS); + if (cmd != null) { + if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account); + if (domainId != null) cmd.setParam(ApiConstants.DOMAIN_ID, domainId); + if (isRecursive != null) cmd.setParam(ApiConstants.IS_RECURSIVE, isRecursive.toString()); + if (listAll != null) cmd.setParam(ApiConstants.LIST_ALL, listAll.toString()); + if (keyWord != null) cmd.setParam(ApiConstants.KEYWORD, keyWord); + } + return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_TAGS_RESPONSE, + ApiConstants.TAG , new TypeToken>() {}.getType()); + } + + private CloudStackCommand setParams(CloudStackCommand cmd, String resourceType, ListresourceIds, + List resourceTags) { + if (cmd != null) { + cmd.setParam(ApiConstants.RESOURCE_TYPE, resourceType); + if (resourceIds != null && resourceIds.size() > 0) { + String resourceIdList = resourceIds.get(0); + for (int i=1 ; i 0) { + int i=0; + for (CloudStackKeyValue resourceTag : resourceTags) { + cmd.setParam(ApiConstants.TAGS+"["+i+"].key", resourceTag.getKey()); + if (resourceTag.getValue() != null) + cmd.setParam(ApiConstants.TAGS+"["+i+"].value", resourceTag.getValue()); + i++; + } + } + } + return cmd; + } + // Security Groups /** * Creates a security group diff --git a/awsapi/src/com/cloud/stack/models/ApiConstants.java b/awsapi/src/com/cloud/stack/models/ApiConstants.java index 4868160a575..059165224d7 100644 --- a/awsapi/src/com/cloud/stack/models/ApiConstants.java +++ b/awsapi/src/com/cloud/stack/models/ApiConstants.java @@ -84,6 +84,8 @@ public class ApiConstants { public static final String CREATE_SNAPSHOT_RESPONSE = "createsnapshotresponse"; public static final String CREATE_SSH_KEY_PAIR = "createSSHKeyPair"; public static final String CREATE_SSH_KEY_PAIR_RESPONSE = "createsshkeypairresponse"; + public static final String CREATE_TAGS = "createTags"; + public static final String CREATE_TAGS_RESPONSE = "createtagsresponse"; public static final String CREATE_TEMPLATE = "createTemplate"; public static final String CREATE_TEMPLATE_RESPONSE = "createtemplateresponse"; public static final String CREATE_VOLUME = "createVolume"; @@ -112,7 +114,9 @@ public class ApiConstants { public static final String DELETE_SNAPSHOT_POLICIES_RESPONSE = "deletesnapshotpoliciesresponse"; public static final String DELETE_SNAPSHOT_RESPONSE = "deletesnapshotresponse"; public static final String DELETE_SSH_KEY_PAIR = "deleteSSHKeyPair"; - public static final String DELETE_SSH_KEY_PAIR_RESPONSE = "deletesshkeypairresponse"; + public static final String DELETE_SSH_KEY_PAIR_RESPONSE = "deletesshkeypairresponse"; + public static final String DELETE_TAGS = "deleteTags"; + public static final String DELETE_TAGS_RESPONSE = "deleteTagsresponse"; public static final String DELETE_TEMPLATE = "deleteTemplate"; public static final String DELETE_TEMPLATE_RESPONSE = "deletetemplateresponse"; public static final String DELETE_VOLUME = "deleteVolume"; @@ -227,6 +231,7 @@ public class ApiConstants { public static final String ISOLATION_URI = "isolationuri"; public static final String JOB_ID = "jobid"; public static final String JOB_STATUS = "jobstatus"; + public static final String KEY = "key"; public static final String KEY_PAIR = "keypair"; public static final String KEYWORD = "keyword"; public static final String LASTNAME = "lastname"; @@ -239,6 +244,7 @@ public class ApiConstants { public static final String LINMIN_APID = "linminapid"; public static final String LINMIN_PASSWORD = "linminpassword"; public static final String LINMIN_USERNAME = "linminusername"; + public static final String LIST_ALL = "listAll"; public static final String LIST_ACCOUNTS = "listAccounts"; public static final String LIST_ACCOUNTS_RESPONSE = "listaccountsresponse"; public static final String LIST_CAPABILITIES = "listCapabilities"; @@ -287,6 +293,8 @@ public class ApiConstants { public static final String LIST_SNAPSHOTS_RESPONSE = "listsnapshotsresponse"; public static final String LIST_SSH_KEY_PAIRS = "listSSHKeyPairs"; public static final String LIST_SSH_KEY_PAIRS_RESPONSE = "listsshkeypairsresponse"; + public static final String LIST_TAGS = "listTags"; + public static final String LIST_TAGS_RESPONSE = "listtagsresponse"; public static final String LIST_TEMPLATE_PERMISSIONS = "listTemplatePermissions"; public static final String LIST_TEMPLATE_PERMISSIONS_RESPONSE = "listtemplatepermissionsresponse"; public static final String LIST_TEMPLATES = "listTemplates"; @@ -378,6 +386,8 @@ public class ApiConstants { public static final String REQUIRES_HVM = "requireshvm"; public static final String RESET_PASSWORD_FOR_VIRTUAL_MACHINE = "resetPasswordForVirtualMachine"; public static final String RESET_PASSWORD_FOR_VIRTUAL_MACHINE_RESPONSE = "resetpasswordforvirtualmachineresponse"; + public static final String RESOURCE_ID = "resourceid"; + public static final String RESOURCE_IDS = "resourceIds"; public static final String RESOURCE_LIMIT = "resourcelimit"; public static final String RESOURCE_TYPE = "resourcetype"; public static final String RESTART_NETWORK = "restartNetwork"; @@ -431,6 +441,7 @@ public class ApiConstants { public static final String STORAGE_TYPE = "storagetype"; public static final String SUCCESS = "success"; public static final String SYSTEM_VM_TYPE = "systemvmtype"; + public static final String TAG = "tag"; public static final String TAGS = "tags"; public static final String TARGET_IQN = "targetiqn"; public static final String TEMPLATE = "template"; @@ -501,6 +512,5 @@ public class ApiConstants { public static final String ZONE = "zone"; public static final String ZONE_ID = "zoneid"; public static final String ZONE_NAME = "zonename"; - public static final String ZONE_TOKEN = "zonetoken"; - -} + public static final String ZONE_TOKEN = "zonetoken"; +} \ No newline at end of file diff --git a/awsapi/src/com/cloud/stack/models/CloudStackResourceTag.java b/awsapi/src/com/cloud/stack/models/CloudStackResourceTag.java new file mode 100644 index 00000000000..d33bb7d790b --- /dev/null +++ b/awsapi/src/com/cloud/stack/models/CloudStackResourceTag.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed 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.stack.models; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackResourceTag { + @SerializedName(ApiConstants.RESOURCE_ID) + private String resourceId; + @SerializedName(ApiConstants.RESOURCE_TYPE) + private String resourceType; + @SerializedName(ApiConstants.KEY) + private String key; + @SerializedName(ApiConstants.VALUE) + private String value; + + public CloudStackResourceTag() { + } + + public String getResourceId() { + return resourceId; + } + + public String getResourceType() { + return resourceType; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } +}