/*
* 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 com.cloud.bridge.service.EC2SoapServiceImpl;
import com.cloud.bridge.service.exception.EC2ServiceException;
public class EC2InstanceFilterSet {
protected List<EC2Filter> filterSet = new ArrayList<EC2Filter>();
private Map<String,String> filterTypes = new HashMap<String,String>();
public EC2InstanceFilterSet()
{
// -> use these values to check that the proper filter is passed to this type of filter set
filterTypes.put( "availability-zone", "string" );
filterTypes.put( "hypervisor", "string" );
filterTypes.put( "image-id", "string" );
filterTypes.put( "instance-id", "string" );
filterTypes.put( "instance-type", "string" );
filterTypes.put( "instance-state-code", "integer" );
filterTypes.put( "instance-state-name", "string" );
filterTypes.put( "ip-address", "string" );
filterTypes.put( "owner-id", "string" );
filterTypes.put( "root-device-name", "string" );
filterTypes.put( "private-ip-address", "string" );
filterTypes.put( "group-id", "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 + "]", 501 );
if (null != value && value.equalsIgnoreCase( "null" ))
throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 );
// ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
filterSet.add( param );
}
public EC2Filter[] getFilterSet() {
return filterSet.toArray(new EC2Filter[0]);
}
/**
* For a filter to match an instance just one of its values has to match the volume.
* For an instance to be included in the instance response it must pass all the defined filters.
*
* @param sampleList - list of instances to test against the defined filters
* @return EC2DescribeInstancesResponse
* @throws ParseException
*/
public EC2DescribeInstancesResponse evaluate( EC2DescribeInstancesResponse sampleList ) throws ParseException
{
EC2DescribeInstancesResponse resultList = new EC2DescribeInstancesResponse();
boolean matched;
EC2Instance[] instanceSet = sampleList.getInstanceSet();
EC2Filter[] filterSet = getFilterSet();
for( int i=0; i < instanceSet.length; i++ )
{
matched = true;
for( int j=0; j < filterSet.length; j++ )
{
if (!filterMatched( instanceSet[i], filterSet[j] )) {
matched = false;
break;
}
}
if (matched) resultList.addInstance( instanceSet[i] );
}
return resultList;
}
private boolean filterMatched( EC2Instance vm, EC2Filter filter ) throws ParseException
{
String filterName = filter.getName();
String[] valueSet = filter.getValueSet();
// TODO: add test of security group the instance is in
if ( filterName.equalsIgnoreCase( "availability-zone" ))
{
return containsString( vm.getZoneName(), valueSet );
}
else if (filterName.equalsIgnoreCase( "hypervisor" ))
{
return containsString( vm.getHypervisor(), valueSet );
}
else if (filterName.equalsIgnoreCase( "image-id" ))
{
return containsString( vm.getTemplateId(), valueSet );
}
else if (filterName.equalsIgnoreCase( "instance-id" ))
{
return containsString( vm.getId(), valueSet );
}
else if (filterName.equalsIgnoreCase( "instance-type" ))
{
return containsString( vm.getServiceOffering(), valueSet );
}
else if (filterName.equalsIgnoreCase( "instance-state-code" ))
{
return containsInteger( EC2SoapServiceImpl.toAmazonCode( vm.getState()), valueSet );
}
else if (filterName.equalsIgnoreCase( "instance-state-name" ))
{
return containsString( EC2SoapServiceImpl.toAmazonStateName( vm.getState()), valueSet );
}
else if (filterName.equalsIgnoreCase( "ip-address" ))
{
return containsString( vm.getIpAddress(), valueSet );
}
else if (filterName.equalsIgnoreCase( "private-ip-address" ))
{
return containsString( vm.getPrivateIpAddress(), valueSet );
}
else if (filterName.equalsIgnoreCase( "owner-id" ))
{
String owner = new String( vm.getDomainId() + ":" + vm.getAccountName());
return containsString( owner, valueSet );
}
else if (filterName.equalsIgnoreCase( "root-device-name" ))
{
return containsDevice( vm.getRootDeviceId(), valueSet );
}
else if (filterName.equalsIgnoreCase( "group-id"))
{
String[] groupSet = vm.getGroupSet();
for (String group : groupSet)
if (containsString(group, valueSet)) return true;
return false;
}
else return false;
}
private boolean containsString( String lookingFor, String[] set )
{
if (null == lookingFor) return false;
for( int i=0; i < set.length; i++ )
{
//System.out.println( "contsinsString: " + lookingFor + " " + set[i] );
if (lookingFor.matches( set[i] )) return true;
}
return false;
}
private boolean containsInteger( int lookingFor, String[] set )
{
for( int i=0; i < set.length; i++ )
{
//System.out.println( "contsinsInteger: " + lookingFor + " " + set[i] );
int temp = Integer.parseInt( set[i] );
if (lookingFor == temp) return true;
}
return false;
}
private boolean containsDevice( String deviceId, String[] set )
{
Integer devId = new Integer(deviceId);
for( int i=0; i < set.length; i++ )
{
//System.out.println( "contsinsDevice: " + deviceId + " " + set[i] );
switch( devId ) {
case 1:
if (( "/dev/sdb" ).matches( set[i] )) return true;
if (( "/dev/xvdb").matches( set[i] )) return true;
break;
case 2:
if (( "/dev/sdc" ).matches( set[i] )) return true;
if (( "/dev/xvdc" ).matches( set[i] )) return true;
break;
case 4:
if (( "/dev/sde" ).matches( set[i] )) return true;
if (( "/dev/xvde" ).matches( set[i] )) return true;
break;
case 5:
if (( "/dev/sdf" ).matches( set[i] )) return true;
if (( "/dev/xvdf" ).matches( set[i] )) return true;
break;
case 6:
if (( "/dev/sdg" ).matches( set[i] )) return true;
if (( "/dev/xvdg" ).matches( set[i] )) return true;
break;
case 7:
if (( "/dev/sdh" ).matches( set[i] )) return true;
if (( "/dev/xvdh" ).matches( set[i] )) return true;
break;
case 8:
if (( "/dev/sdi" ).matches( set[i] )) return true;
if (( "/dev/xvdi" ).matches( set[i] )) return true;
break;
case 9:
if (( "/dev/sdj" ).matches( set[i] )) return true;
if (( "/dev/xvdj" ).matches( set[i] )) return true;
break;
}
}
return false;
}
}