This commit is contained in:
Pranav Saxena 2012-07-25 00:06:39 +05:30
commit 5ba20b328d
56 changed files with 2054 additions and 820 deletions

View File

@ -18,3 +18,4 @@
# management server compile-time environment parameters
paths.pid=@PIDDIR@
paths.scripts=@AGENTLIBDIR@

View File

@ -36,15 +36,33 @@ whatami=cloud-agent
# set environment variables
SHORTNAME="$whatami"
PIDFILE=@PIDDIR@/"$whatami".pid
LOCKFILE=@LOCKDIR@/"$SHORTNAME"
LOGFILE=@AGENTLOG@
PIDFILE=/var/run/"$whatami".pid
LOCKFILE=/var/lock/subsys/"$SHORTNAME"
LOGFILE=/var/log/cloud/agent/agent.log
PROGNAME="Cloud Agent"
CLASS="com.cloud.agent.AgentShell"
unset OPTIONS
[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME"
DAEMONIZE=@BINDIR@/@PACKAGE@-daemonize
PROG=@LIBEXECDIR@/agent-runner
[ -r /etc/default/"$SHORTNAME" ] && source /etc/default/"$SHORTNAME"
# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm"
for jdir in $JDK_DIRS; do
if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
JAVA_HOME="$jdir"
fi
done
export JAVA_HOME
SCP="@SYSTEMCLASSPATH@"
DCP="@DEPSCLASSPATH@"
ACP="@AGENTCLASSPATH@"
JCP="/usr/share/java/commons-daemon.jar"
# We need to append the JSVC daemon JAR to the classpath
# AgentShell implements the JSVC daemon methods
export CLASSPATH="$SCP:$DCP:$ACP:$JCP:@AGENTSYSCONFDIR@"
wait_for_network() {
i=1
@ -79,9 +97,7 @@ start() {
wait_for_network
if start-stop-daemon --start --quiet \
--pidfile "$PIDFILE" \
--exec "$DAEMONIZE" -- -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS
if jsvc -cp "$CLASSPATH" -pidfile "$PIDFILE" $CLASS
RETVAL=$?
then
rc=0
@ -107,11 +123,11 @@ stop() {
count="0"
echo -n $"Stopping $PROGNAME" "$SHORTNAME"
start-stop-daemon --stop --quiet --oknodo --pidfile "$PIDFILE"
jsvc -pidfile "$PIDFILE" -stop $CLASS
until [ "$count" -gt "$SHUTDOWN_WAIT" ]
do
agentPid=`ps aux|grep [j]ava|grep cloud-agent`
agentPid=`ps aux|grep [j]svc|grep cloud-agent`
if [ "$?" -gt "0" ];then
break
fi
@ -119,16 +135,16 @@ stop() {
let count="${count}+1"
done
agentPid=`ps aux|grep [j]ava|grep cloud-agent`
agentPid=`ps aux|grep [j]svc|grep cloud-agent`
if [ "$?" -eq "0" ]; then
agentPid=`ps aux|grep [j]ava|awk '{print $2}'`
agentPid=`ps aux|grep [j]svc|awk '{print $2}'`
if [ "$agentPid" != "" ]; then
kill -9 $agentPid
fi
fi
log_end_msg $?
rm -f "$PIDFILE"
log_end_msg $?
rm -f "$PIDFILE"
}

View File

@ -1,88 +0,0 @@
#!/usr/bin/env bash
# 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.
#run.sh runs the agent client.
cd `dirname "$0"`
SYSTEMJARS="@SYSTEMJARS@"
SCP=$(build-classpath $SYSTEMJARS) ; if [ $? != 0 ] ; then SCP="@SYSTEMCLASSPATH@" ; fi
DCP="@DEPSCLASSPATH@"
ACP="@AGENTCLASSPATH@"
export CLASSPATH=$SCP:$DCP:$ACP:@AGENTSYSCONFDIR@
for jarfile in "@PREMIUMJAVADIR@"/* ; do
if [ ! -e "$jarfile" ] ; then continue ; fi
CLASSPATH=$jarfile:$CLASSPATH
done
for plugin in "@PLUGINJAVADIR@"/* ; do
if [ ! -e "$plugin" ] ; then continue ; fi
CLASSPATH=$plugin:$CLASSPATH
done
export CLASSPATH
set -e
cd "@AGENTLIBDIR@"
echo Current directory is "$PWD"
echo CLASSPATH to run the agent: "$CLASSPATH"
export PATH=/sbin:/usr/sbin:"$PATH"
SERVICEARGS=
for x in private public ; do
configuration=`grep "^$x.network.device" "@AGENTSYSCONFDIR@"/agent.properties||true`
if [ -n "$configuration" ] ; then
echo "Using manually-configured network device $CONFIGURATION"
else
defaultroute=`ip route | grep ^default | cut -d ' ' -f 5`
test -n "$defaultroute"
echo "Using auto-discovered network device $defaultroute which is the default route"
SERVICEARGS="$SERVICEARGS $x.network.device="$defaultroute
fi
done
function termagent() {
if [ "$agentpid" != "" ] ; then
echo Killing VMOps Agent "(PID $agentpid)" with SIGTERM >&2
kill -TERM $agentpid
echo Waiting for agent to exit >&2
wait $agentpid
ex=$?
echo Agent exited with return code $ex >&2
else
echo Agent PID is unknown >&2
fi
}
trap termagent TERM
while true ; do
java -Xms128M -Xmx384M -cp "$CLASSPATH" "$@" com.cloud.agent.AgentShell $SERVICEARGS &
agentpid=$!
echo "Agent started. PID: $!" >&2
wait $agentpid
ex=$?
if [ $ex -gt 128 ]; then
echo "wait on agent process interrupted by SIGTERM" >&2
exit $ex
fi
echo "Agent exited with return code $ex" >&2
if [ $ex -eq 0 ] || [ $ex -eq 1 ] || [ $ex -eq 66 ] || [ $ex -gt 128 ]; then
echo "Exiting..." > /dev/stderr
exit $ex
fi
echo "Restarting agent..." > /dev/stderr
sleep 1
done

View File

@ -27,6 +27,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@ -371,7 +372,7 @@ public class AgentShell implements IAgentShell {
return true;
}
private void init(String[] args) throws ConfigurationException {
public void init(String[] args) throws ConfigurationException {
final ComponentLocator locator = ComponentLocator.getLocator("agent");
@ -383,8 +384,14 @@ public class AgentShell implements IAgentShell {
}
s_logger.info("Implementation Version is " + _version);
loadProperties();
parseCommand(args);
List<String> properties = Collections.list((Enumeration<String>)_properties.propertyNames());
for (String property:properties){
s_logger.debug("Found property: " + property);
}
_storage = locator.getManager(StorageComponent.class);
if (_storage == null) {
s_logger.info("Defaulting to using properties file for storage");
@ -558,13 +565,10 @@ public class AgentShell implements IAgentShell {
return _nextAgentId++;
}
private void run(String[] args) {
public void start() {
try {
System.setProperty("java.net.preferIPv4Stack", "true");
loadProperties();
init(args);
String instance = getProperty(null, "instance");
if (instance == null) {
if (Boolean.parseBoolean(getProperty(null, "developer"))) {
@ -579,7 +583,7 @@ public class AgentShell implements IAgentShell {
String pidDir = getProperty(null, "piddir");
final String run = "agent." + instance + "pid";
s_logger.debug("Checking to see if " + run + "exists.");
s_logger.debug("Checking to see if " + run + " exists.");
ProcessUtil.pidCheck(pidDir, run);
launchAgent();
@ -616,22 +620,17 @@ public class AgentShell implements IAgentShell {
}
}
public static void main(String[] args) {
AgentShell shell = new AgentShell();
Runtime.getRuntime().addShutdownHook(new ShutdownThread(shell));
shell.run(args);
public void destroy() {
}
private static class ShutdownThread extends Thread {
AgentShell _shell;
public ShutdownThread(AgentShell shell) {
this._shell = shell;
}
@Override
public void run() {
_shell.stop();
public static void main(String[] args) {
try {
AgentShell shell = new AgentShell();
shell.init(args);
shell.start();
} catch (ConfigurationException e) {
System.out.println(e.getMessage());
}
}
}

View File

@ -33,6 +33,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;
@ -46,10 +47,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;
@ -69,6 +73,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;
@ -79,6 +85,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;
@ -199,6 +206,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<String> resourceTypeList = new ArrayList<String>();
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()));
@ -323,11 +413,10 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
if (null != items) { // -> can be empty
for( int i=0; i < items.length; i++ ) request.addInstanceId( items[i].getInstanceId());
}
if (null != fst) {
request.setFilterSet( toInstanceFilterSet( fst ));
}
if (null != fst)
request = toInstanceFilterSet( request, fst );
return toDescribeInstancesResponse( engine.describeInstances( request ), engine );
}
@ -428,13 +517,24 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
{
String[] timeFilters = new String[1];
timeFilters[0] = new String( "start-time" );
request.setFilterSet( toSnapshotFilterSet( fst, timeFilters ));
request = toSnapshotFilterSet( request, fst, timeFilters );
}
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();
@ -456,7 +556,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
String[] timeFilters = new String[2];
timeFilters[0] = new String( "attachment.attach-time" );
timeFilters[1] = new String( "create-time" );
request.setFilterSet( toVolumeFilterSet( fst, timeFilters ));
request = toVolumeFilterSet( request, fst, timeFilters );
}
return toDescribeVolumesResponse( engine.handleRequest( request ));
@ -855,7 +955,11 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
param7.addItem( param8 );
param3.setBlockDeviceMapping( param7 );
param2.addItem( param3 );
EC2TagKeyValue[] tags = images[i].getResourceTags();
param3.setTagSet(setResourceTags(tags));
param2.addItem( param3 );
}
param1.setImagesSet( param2 );
@ -940,8 +1044,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
return vfs;
}
private EC2VolumeFilterSet toVolumeFilterSet( FilterSetType fst, String[] timeStrs )
private EC2DescribeVolumes toVolumeFilterSet( EC2DescribeVolumes request, FilterSetType fst, String[] timeStrs )
{
EC2VolumeFilterSet vfs = new EC2VolumeFilterSet();
boolean timeFilter = false;
@ -952,73 +1055,94 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
// -> each filter can have one or more values associated with it
for( int j=0; j < items.length; j++ )
{
EC2Filter oneFilter = new EC2Filter();
String filterName = items[j].getName();
oneFilter.setName( filterName );
// -> is the filter one of the xsd:dateTime filters?
timeFilter = false;
for( int m=0; m < timeStrs.length; m++ )
{
timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
if (timeFilter) break;
}
ValueSetType vst = items[j].getValueSet();
ValueType[] valueItems = vst.getItem();
for( int k=0; k < valueItems.length; k++ )
{
// -> time values are not encoded as regexes
if ( timeFilter )
oneFilter.addValue( valueItems[k].getValue());
else oneFilter.addValueEncoded( valueItems[k].getValue());
}
vfs.addFilter( oneFilter );
}
}
return vfs;
}
String filterName = items[j].getName();
ValueSetType vst = items[j].getValueSet();
ValueType[] valueItems = vst.getItem();
private EC2SnapshotFilterSet toSnapshotFilterSet( FilterSetType fst, String[] timeStrs )
{
EC2SnapshotFilterSet vfs = new EC2SnapshotFilterSet();
if (filterName.startsWith("tag:")) {
String key= filterName.split(":")[1];
for (ValueType valueItem : valueItems) {
EC2TagKeyValue tag = new EC2TagKeyValue();
tag.setKey(key);
tag.setValue(valueItem.getValue());
request.addResourceTag(tag);
}
} else {
EC2Filter oneFilter = new EC2Filter();
oneFilter.setName( filterName );
// -> is the filter one of the xsd:dateTime filters?
timeFilter = false;
for( int m=0; m < timeStrs.length; m++ ) {
timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
if (timeFilter) break;
}
for( int k=0; k < valueItems.length; k++ ) {
// -> time values are not encoded as regexes
if ( timeFilter )
oneFilter.addValue( valueItems[k].getValue());
else
oneFilter.addValueEncoded( valueItems[k].getValue());
}
vfs.addFilter( oneFilter );
}
}
request.setFilterSet(vfs);
}
return request;
}
private EC2DescribeSnapshots toSnapshotFilterSet( EC2DescribeSnapshots request, FilterSetType fst, String[] timeStrs )
{
EC2SnapshotFilterSet sfs = new EC2SnapshotFilterSet();
boolean timeFilter = false;
FilterType[] items = fst.getItem();
if (null != items)
{
// -> each filter can have one or more values associated with it
for( int j=0; j < items.length; j++ )
{
EC2Filter oneFilter = new EC2Filter();
String filterName = items[j].getName();
oneFilter.setName( filterName );
// -> is the filter one of the xsd:dateTime filters?
timeFilter = false;
for( int m=0; m < timeStrs.length; m++ )
{
timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
if (timeFilter) break;
}
ValueSetType vst = items[j].getValueSet();
ValueType[] valueItems = vst.getItem();
for( int k=0; k < valueItems.length; k++ )
{
// -> time values are not encoded as regexes
if ( timeFilter )
oneFilter.addValue( valueItems[k].getValue());
else oneFilter.addValueEncoded( valueItems[k].getValue());
}
vfs.addFilter( oneFilter );
}
}
return vfs;
}
String filterName = items[j].getName();
ValueSetType vst = items[j].getValueSet();
ValueType[] valueItems = vst.getItem();
if (filterName.startsWith("tag:")) {
String key= filterName.split(":")[1];
for (ValueType valueItem : valueItems) {
EC2TagKeyValue tag = new EC2TagKeyValue();
tag.setKey(key);
tag.setValue(valueItem.getValue());
request.addResourceTag(tag);
}
}
else {
EC2Filter oneFilter = new EC2Filter();
oneFilter.setName( filterName );
// -> is the filter one of the xsd:dateTime filters?
timeFilter = false;
for( int m=0; m < timeStrs.length; m++ ) {
timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
if (timeFilter) break;
}
for( int k=0; k < valueItems.length; k++ ) {
// -> time values are not encoded as regexes
if ( timeFilter )
oneFilter.addValue( valueItems[k].getValue());
else
oneFilter.addValueEncoded( valueItems[k].getValue());
}
sfs.addFilter( oneFilter );
}
}
request.setFilterSet(sfs);
}
return request;
}
// TODO make these filter set functions use generics
private EC2GroupFilterSet toGroupFilterSet( FilterSetType fst )
{
@ -1046,8 +1170,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
return gfs;
}
private EC2InstanceFilterSet toInstanceFilterSet( FilterSetType fst )
private EC2DescribeInstances toInstanceFilterSet( EC2DescribeInstances request, FilterSetType fst )
{
EC2InstanceFilterSet ifs = new EC2InstanceFilterSet();
@ -1057,22 +1180,30 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
// -> each filter can have one or more values associated with it
for( int j=0; j < items.length; j++ )
{
EC2Filter oneFilter = new EC2Filter();
String filterName = items[j].getName();
oneFilter.setName( filterName );
ValueSetType vst = items[j].getValueSet();
ValueType[] valueItems = vst.getItem();
for( int k=0; k < valueItems.length; k++ )
{
oneFilter.addValueEncoded( valueItems[k].getValue());
}
ifs.addFilter( oneFilter );
}
}
return ifs;
}
String filterName = items[j].getName();
ValueSetType vst = items[j].getValueSet();
ValueType[] valueItems = vst.getItem();
if (filterName.startsWith("tag:")) {
String key= filterName.split(":")[1];
for (ValueType valueItem : valueItems) {
EC2TagKeyValue tag = new EC2TagKeyValue();
tag.setKey(key);
tag.setValue(valueItem.getValue());
request.addResourceTag(tag);
}
} else {
EC2Filter oneFilter = new EC2Filter();
oneFilter.setName( filterName );
for( int k=0; k < valueItems.length; k++ )
oneFilter.addValueEncoded( valueItems[k].getValue());
ifs.addFilter( oneFilter );
}
}
request.setFilterSet(ifs);
}
return request;
}
private EC2AvailabilityZonesFilterSet toAvailabiltyZonesFilterSet( FilterSetType fst ) {
EC2AvailabilityZonesFilterSet azfs = new EC2AvailabilityZonesFilterSet();
@ -1094,8 +1225,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 )
{
@ -1142,14 +1293,9 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
}
param3.setAttachmentSet( param4 );
// -> try to generate an empty tag does not seem to work
ResourceTagSetType param6 = new ResourceTagSetType();
ResourceTagSetItemType param7 = new ResourceTagSetItemType();
param7.setKey("");
param7.setValue("");
param6.addItem( param7 );
param3.setTagSet( param6 );
EC2TagKeyValue[] tags = vol.getResourceTags();
param3.setTagSet( setResourceTags(tags) );
param2.addItem( param3 );
}
param1.setVolumeSet( param2 );
@ -1277,6 +1423,9 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
param7.setSpotInstanceRequestId( "" );
param7.setHypervisor(inst.getHypervisor());
EC2TagKeyValue[] tags = inst.getResourceTags();
param7.setTagSet(setResourceTags(tags));
param6.addItem( param7 );
param3.setInstancesSet( param6 );
param2.addItem( param3 );
@ -1759,12 +1908,9 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
param3.setDescription( snap.getName());
param3.setOwnerAlias( snap.getAccountName() );
ResourceTagSetType param18 = new ResourceTagSetType();
ResourceTagSetItemType param19 = new ResourceTagSetItemType();
param19.setKey("");
param19.setValue("");
param18.addItem( param19 );
param3.setTagSet( param18 );
EC2TagKeyValue[] tags = snap.getResourceTags();
param3.setTagSet(setResourceTags(tags));
param2.addItem( param3 );
}
@ -1931,7 +2077,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();
@ -2047,7 +2234,29 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {
public GetPasswordDataResponse getPasswordData(GetPasswordData getPasswordData) {
return toGetPasswordData(engine.getPasswordData(getPasswordData.getGetPasswordData().getInstanceId()));
}
public static ResourceTagSetType setResourceTags(EC2TagKeyValue[] tags){
ResourceTagSetType param1 = new ResourceTagSetType();
if (null == tags || 0 == tags.length) {
ResourceTagSetItemType param2 = new ResourceTagSetItemType();
param2.setKey("");
param2.setValue("");
param1.addItem( param2 );
}
else {
for(EC2TagKeyValue tag : tags) {
ResourceTagSetItemType param2 = new ResourceTagSetItemType();
param2.setKey(tag.getKey());
if (tag.getValue() != null)
param2.setValue(tag.getValue());
else
param2.setValue("");
param1.addItem(param2);
}
}
return param1;
}
@SuppressWarnings("serial")
public static GetPasswordDataResponse toGetPasswordData(final EC2PasswordData passwdData) {
return new GetPasswordDataResponse() {{
@ -2116,10 +2325,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");
@ -2156,10 +2361,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");
@ -2229,10 +2430,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");
}

View File

@ -23,6 +23,7 @@ public class EC2DescribeInstances {
private List<String> instancesSet = new ArrayList<String>(); // a list of strings identifying instances
private EC2InstanceFilterSet ifs = null;
private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
public EC2DescribeInstances() {
}
@ -42,4 +43,12 @@ public class EC2DescribeInstances {
public void setFilterSet( EC2InstanceFilterSet param ) {
ifs = param;
}
public void addResourceTag( EC2TagKeyValue param ) {
resourceTagSet.add( param );
}
public EC2TagKeyValue[] getResourceTagSet() {
return resourceTagSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -23,6 +23,7 @@ public class EC2DescribeSnapshots {
private List<String> snapshotSet = new ArrayList<String>(); // a list of strings identifying snapshots
private EC2SnapshotFilterSet sfs = null;
private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
public EC2DescribeSnapshots() {
}
@ -42,4 +43,12 @@ public class EC2DescribeSnapshots {
public void setFilterSet( EC2SnapshotFilterSet param ) {
sfs = param;
}
public void addResourceTag( EC2TagKeyValue param ) {
resourceTagSet.add( param );
}
public EC2TagKeyValue[] getResourceTagSet() {
return resourceTagSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -0,0 +1,34 @@
// 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;
public class EC2DescribeTags {
private EC2TagsFilterSet tfs = null;
public EC2DescribeTags() {
}
public EC2TagsFilterSet getFilterSet() {
return tfs;
}
public void setFilterSet( EC2TagsFilterSet param ) {
tfs = param;
}
}

View File

@ -0,0 +1,37 @@
// 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 EC2DescribeTagsResponse {
private List<EC2ResourceTag> tagsSet = new ArrayList<EC2ResourceTag>();
public EC2DescribeTagsResponse() {
}
public void addTags( EC2ResourceTag param ) {
tagsSet.add( param );
}
public EC2ResourceTag[] getTagsSet() {
return tagsSet.toArray(new EC2ResourceTag[0]);
}
}

View File

@ -23,6 +23,7 @@ public class EC2DescribeVolumes {
private List<String> volumeSet = new ArrayList<String>(); // a list of strings identifying volume ids
private EC2VolumeFilterSet vfs = null;
private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
public EC2DescribeVolumes() {
}
@ -42,4 +43,12 @@ public class EC2DescribeVolumes {
public void setFilterSet( EC2VolumeFilterSet param ) {
vfs = param;
}
public void addResourceTag( EC2TagKeyValue param ) {
resourceTagSet.add( param );
}
public EC2TagKeyValue[] getResourceTagSet() {
return resourceTagSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -59,6 +59,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;
@ -417,20 +418,22 @@ public class EC2Engine {
* @param request
* @return
*/
public EC2DescribeSnapshotsResponse handleRequest( EC2DescribeSnapshots request )
public EC2DescribeSnapshotsResponse handleRequest( EC2DescribeSnapshots request )
{
EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse();
EC2SnapshotFilterSet sfs = request.getFilterSet();
EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet();
try {
// -> query to get the volume size for each snapshot
EC2DescribeSnapshotsResponse response = listSnapshots( request.getSnapshotSet());
EC2DescribeSnapshotsResponse response = listSnapshots( request.getSnapshotSet(),
getResourceTags(tagKeyValueSet));
if (response == null) {
return new EC2DescribeSnapshotsResponse();
}
EC2Snapshot[] snapshots = response.getSnapshotSet();
for (EC2Snapshot snap : snapshots) {
volumes = listVolumes(snap.getVolumeId(), null, volumes);
volumes = listVolumes(snap.getVolumeId(), null, volumes, null);
EC2Volume[] volSet = volumes.getVolumeSet();
if (0 < volSet.length) snap.setVolumeSize(volSet[0].getSize());
volumes.reset();
@ -472,7 +475,7 @@ public class EC2Engine {
ec2Snapshot.setCreated(snap.getCreated());
ec2Snapshot.setVolumeId(snap.getVolumeId());
List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, snap.getVolumeId(), null, null, null, null, null, null, null);
List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, snap.getVolumeId(), null, null, null, null, null, null, null, null);
if(vols.size() > 0) {
assert(vols.get(0).getSize() != null);
@ -629,17 +632,18 @@ public class EC2Engine {
*
* @param interestedShots - can be null, should be a subset of all snapshots
*/
private EC2DescribeSnapshotsResponse listSnapshots( String[] interestedShots ) throws Exception {
private EC2DescribeSnapshotsResponse listSnapshots( String[] interestedShots, List<CloudStackKeyValue> resourceTagSet ) throws Exception {
EC2DescribeSnapshotsResponse snapshots = new EC2DescribeSnapshotsResponse();
List<CloudStackSnapshot> cloudSnaps;
if (interestedShots == null || interestedShots.length == 0) {
cloudSnaps = getApi().listSnapshots(null, null, null, null, null, null, null, null, null);
cloudSnaps = getApi().listSnapshots(null, null, null, null, null, null, null, null, null, resourceTagSet);
} else {
cloudSnaps = new ArrayList<CloudStackSnapshot>();
for(String id : interestedShots) {
List<CloudStackSnapshot> tmpList = getApi().listSnapshots(null, null, id, null, null, null, null, null, null);
List<CloudStackSnapshot> tmpList = getApi().listSnapshots(null, null, id, null, null, null, null,
null, null, resourceTagSet);
cloudSnaps.addAll(tmpList);
}
}
@ -659,6 +663,15 @@ public class EC2Engine {
shot.setAccountName(cloudSnapshot.getAccountName());
shot.setDomainId(cloudSnapshot.getDomainId());
List<CloudStackKeyValue> resourceTags = cloudSnapshot.getTags();
for(CloudStackKeyValue resourceTag : resourceTags) {
EC2TagKeyValue param = new EC2TagKeyValue();
param.setKey(resourceTag.getKey());
if (resourceTag.getValue() != null)
param.setValue(resourceTag.getValue());
shot.addResourceTag(param);
}
snapshots.addSnapshot(shot);
}
return snapshots;
@ -870,7 +883,7 @@ public class EC2Engine {
public boolean associateAddress( EC2AssociateAddress request ) {
try {
CloudStackIpAddress cloudIp = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null).get(0);
CloudStackUserVm cloudVm = getApi().listVirtualMachines(null, null, true, null, null, null, null, request.getInstanceId(), null, null, null, null, null, null, null, null).get(0);
CloudStackUserVm cloudVm = getApi().listVirtualMachines(null, null, true, null, null, null, null, request.getInstanceId(), null, null, null, null, null, null, null, null, null).get(0);
CloudStackInfoResponse resp = getApi().enableStaticNat(cloudIp.getId(), cloudVm.getId());
if (resp != null) {
@ -995,7 +1008,7 @@ public class EC2Engine {
// [A] Creating a template from a VM volume should be from the ROOT volume
// Also for this to work the VM must be in a Stopped state so we 'reboot' it if its not
EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse();
volumes = listVolumes( null, request.getInstanceId(), volumes );
volumes = listVolumes( null, request.getInstanceId(), volumes, null );
EC2Volume[] volSet = volumes.getVolumeSet();
for (EC2Volume vol : volSet) {
if (vol.getType().equalsIgnoreCase( "ROOT" )) {
@ -1012,7 +1025,7 @@ public class EC2Engine {
// [B] The parameters must be in sorted order for proper signature generation
EC2DescribeInstancesResponse instances = new EC2DescribeInstancesResponse();
instances = lookupInstances( request.getInstanceId(), instances );
instances = lookupInstances( request.getInstanceId(), instances, null );
EC2Instance[] instanceSet = instances.getInstanceSet();
String templateId = instanceSet[0].getTemplateId();
@ -1055,9 +1068,8 @@ public class EC2Engine {
{
try {
CloudStackAccount caller = getCurrentAccount();
if (null == request.getFormat() || null == request.getName() || null == request.getOsTypeName() ||
null == request.getLocation() || null == request.getZoneName())
throw new EC2ServiceException(ServerError.InternalError, "Missing parameter - location/architecture/name");
if (null == request.getName())
throw new EC2ServiceException(ClientError.Unsupported, "Missing parameter - name");
List<CloudStackTemplate> templates = getApi().registerTemplate((request.getDescription() == null ? request.getName() : request.getDescription()),
request.getFormat(), request.getHypervisor(), request.getName(), toOSTypeId(request.getOsTypeName()), request.getLocation(),
@ -1106,7 +1118,9 @@ public class EC2Engine {
*/
public EC2DescribeInstancesResponse describeInstances(EC2DescribeInstances request ) {
try {
return listVirtualMachines( request.getInstancesSet(), request.getFilterSet());
EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet();
return listVirtualMachines( request.getInstancesSet(), request.getFilterSet(),
getResourceTags(tagKeyValueSet));
} catch( Exception e ) {
logger.error( "EC2 DescribeInstances - " ,e);
throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred.");
@ -1150,14 +1164,14 @@ public class EC2Engine {
public EC2DescribeVolumesResponse handleRequest( EC2DescribeVolumes request ) {
EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse();
EC2VolumeFilterSet vfs = request.getFilterSet();
EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet();
try {
String[] volumeIds = request.getVolumeSet();
if ( 0 == volumeIds.length ){
volumes = listVolumes( null, null, volumes );
volumes = listVolumes( null, null, volumes, getResourceTags(tagKeyValueSet) );
} else {
for (String s : volumeIds)
volumes = listVolumes(s, null, volumes );
volumes = listVolumes(s, null, volumes, getResourceTags(tagKeyValueSet) );
}
if ( null == vfs )
@ -1311,6 +1325,80 @@ public class EC2Engine {
}
}
/**
* Create/Delete tags
*
* @param request
* @param operation
* @return
*/
public boolean modifyTags( EC2Tags request, String operation) {
try {
List<CloudStackKeyValue> resourceTagList = new ArrayList<CloudStackKeyValue>();
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<String> resourceIdList = new ArrayList<String>();
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<CloudStackResourceTag> resourceTagList = getApi().listTags(null, null, null, true, null);
List<EC2ResourceTag> tagList = new ArrayList<EC2ResourceTag>();
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
*
@ -1324,7 +1412,7 @@ public class EC2Engine {
// -> reboot is not allowed on destroyed (i.e., terminated) instances
try {
String[] instanceSet = request.getInstancesSet();
EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null );
EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null, null );
vms = previousState.getInstanceSet();
// -> send reboot requests for each found VM
@ -1461,7 +1549,7 @@ public class EC2Engine {
// -> first determine the current state of each VM (becomes it previous state)
try {
EC2DescribeInstancesResponse previousState = listVirtualMachines( request.getInstancesSet(), null );
EC2DescribeInstancesResponse previousState = listVirtualMachines( request.getInstancesSet(), null, null );
vms = previousState.getInstanceSet();
// -> send start requests for each item
@ -1503,7 +1591,7 @@ public class EC2Engine {
try {
String[] instanceSet = request.getInstancesSet();
EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null );
EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null, null );
virtualMachines = previousState.getInstanceSet();
// -> send stop requests for each item
@ -1570,7 +1658,7 @@ public class EC2Engine {
if (maxAllowed == -1)
return -1; // no limit
EC2DescribeInstancesResponse existingVMS = listVirtualMachines( null, null );
EC2DescribeInstancesResponse existingVMS = listVirtualMachines( null, null, null );
EC2Instance[] vmsList = existingVMS.getInstanceSet();
return (maxAllowed - vmsList.length);
} else {
@ -1584,15 +1672,16 @@ public class EC2Engine {
* @param virtualMachineIds - an array of instances we are interested in getting information on
* @param ifs - filter out unwanted instances
*/
private EC2DescribeInstancesResponse listVirtualMachines( String[] virtualMachineIds, EC2InstanceFilterSet ifs ) throws Exception
private EC2DescribeInstancesResponse listVirtualMachines( String[] virtualMachineIds, EC2InstanceFilterSet ifs,
List<CloudStackKeyValue> resourceTags ) throws Exception
{
EC2DescribeInstancesResponse instances = new EC2DescribeInstancesResponse();
if (null == virtualMachineIds || 0 == virtualMachineIds.length) {
instances = lookupInstances( null, instances );
instances = lookupInstances( null, instances, resourceTags );
} else {
for( int i=0; i < virtualMachineIds.length; i++ ) {
instances = lookupInstances( virtualMachineIds[i], instances );
instances = lookupInstances( virtualMachineIds[i], instances, resourceTags );
}
}
@ -1607,9 +1696,11 @@ public class EC2Engine {
* @param volumeId - if interested in one specific volume, null if want to list all volumes
* @param instanceId - if interested in volumes for a specific instance, null if instance is not important
*/
private EC2DescribeVolumesResponse listVolumes(String volumeId, String instanceId, EC2DescribeVolumesResponse volumes)throws Exception {
private EC2DescribeVolumesResponse listVolumes(String volumeId, String instanceId, EC2DescribeVolumesResponse volumes,
List<CloudStackKeyValue> resourceTagSet)throws Exception {
List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, volumeId, null, null, null, null, null, instanceId, null);
List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, volumeId, null, null, null, null, null,
instanceId, null, resourceTagSet);
if(vols != null && vols.size() > 0) {
for(CloudStackVolume vol : vols) {
EC2Volume ec2Vol = new EC2Volume();
@ -1635,6 +1726,15 @@ public class EC2Engine {
ec2Vol.setVMState(vol.getVirtualMachineState());
ec2Vol.setZoneName(vol.getZoneName());
List<CloudStackKeyValue> resourceTags = vol.getTags();
for(CloudStackKeyValue resourceTag : resourceTags) {
EC2TagKeyValue param = new EC2TagKeyValue();
param.setKey(resourceTag.getKey());
if (resourceTag.getValue() != null)
param.setValue(resourceTag.getValue());
ec2Vol.addResourceTag(param);
}
volumes.addVolume(ec2Vol);
}
}
@ -1779,12 +1879,13 @@ public class EC2Engine {
* @return the same object passed in as the "instances" parameter modified with one or more
* EC2Instance objects loaded.
*/
private EC2DescribeInstancesResponse lookupInstances( String instanceId, EC2DescribeInstancesResponse instances )
private EC2DescribeInstancesResponse lookupInstances( String instanceId, EC2DescribeInstancesResponse instances,
List<CloudStackKeyValue> resourceTagSet )
throws Exception {
String instId = instanceId != null ? instanceId : null;
List<CloudStackUserVm> vms = getApi().listVirtualMachines(null, null, true, null, null, null, null,
instId, null, null, null, null, null, null, null, null);
instId, null, null, null, null, null, null, null, null, resourceTagSet);
if(vms != null && vms.size() > 0) {
for(CloudStackUserVm cloudVm : vms) {
@ -1812,7 +1913,16 @@ public class EC2Engine {
break;
}
}
List<CloudStackKeyValue> resourceTags = cloudVm.getTags();
for(CloudStackKeyValue resourceTag : resourceTags) {
EC2TagKeyValue param = new EC2TagKeyValue();
param.setKey(resourceTag.getKey());
if (resourceTag.getValue() != null)
param.setValue(resourceTag.getValue());
ec2Vm.addResourceTag(param);
}
if (cloudVm.getSecurityGroupList() != null && cloudVm.getSecurityGroupList().size() > 0) {
// TODO, we have a list of security groups, just return the first one?
List<CloudStackSecurityGroup> securityGroupList = cloudVm.getSecurityGroupList();
@ -1885,6 +1995,14 @@ public class EC2Engine {
ec2Image.setIsPublic(temp.getIsPublic());
ec2Image.setIsReady(temp.getIsReady());
ec2Image.setDomainId(temp.getDomainId());
List<CloudStackKeyValue> resourceTags = temp.getTags();
for(CloudStackKeyValue resourceTag : resourceTags) {
EC2TagKeyValue param = new EC2TagKeyValue();
param.setKey(resourceTag.getKey());
if (resourceTag.getValue() != null)
param.setValue(resourceTag.getValue());
ec2Image.addResourceTag(param);
}
images.addImage(ec2Image);
}
}
@ -2245,6 +2363,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
@ -2299,4 +2447,15 @@ public class EC2Engine {
}
return elementList.toString();
}
private List<CloudStackKeyValue> getResourceTags(EC2TagKeyValue[] tagKeyValueSet) {
List<CloudStackKeyValue> resourceTags = new ArrayList<CloudStackKeyValue>();
for (EC2TagKeyValue tagKeyValue : tagKeyValueSet) {
CloudStackKeyValue resourceTag = new CloudStackKeyValue();
resourceTag.setKeyValue(tagKeyValue.getKey(), tagKeyValue.getValue());
resourceTags.add(resourceTag);
}
return resourceTags;
}
}

View File

@ -16,6 +16,9 @@
// under the License.
package com.cloud.bridge.service.core.ec2;
import java.util.ArrayList;
import java.util.List;
/**
* An EC2 Image is a Cloud template.
*/
@ -29,6 +32,7 @@ public class EC2Image {
private boolean isReady;
private String accountName;
private String domainId;
private List<EC2TagKeyValue> tagsSet;
public EC2Image() {
id = null;
@ -39,6 +43,7 @@ public class EC2Image {
isReady = false;
accountName = null;
domainId = null;
tagsSet = new ArrayList<EC2TagKeyValue>();
}
public void setId( String id ) {
@ -104,5 +109,13 @@ public class EC2Image {
public void setDomainId(String domainId) {
this.domainId = domainId;
}
public void addResourceTag( EC2TagKeyValue param ) {
tagsSet.add( param );
}
public EC2TagKeyValue[] getResourceTags() {
return tagsSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -41,6 +41,7 @@ public class EC2Instance {
private String rootDeviceType;
private String rootDeviceId;
private List<String> groupSet;
private List<EC2TagKeyValue> tagsSet;
public EC2Instance() {
id = null;
@ -60,6 +61,7 @@ public class EC2Instance {
rootDeviceType = null;
rootDeviceId = null;
groupSet = new ArrayList<String>();
tagsSet = new ArrayList<EC2TagKeyValue>();
}
public void setId( String id ) {
@ -197,5 +199,13 @@ public class EC2Instance {
public String[] getGroupSet() {
return groupSet.toArray(new String[0]);
}
public void addResourceTag( EC2TagKeyValue param ) {
tagsSet.add( param );
}
public EC2TagKeyValue[] getResourceTags() {
return tagsSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -48,20 +48,21 @@ public class EC2InstanceFilterSet {
filterTypes.put( "root-device-name", "string" );
filterTypes.put( "private-ip-address", "string" );
filterTypes.put( "group-id", "string" );
filterTypes.put( "tag-key", "string" );
filterTypes.put( "tag-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 + "]", 501 );
if (null != value && value.equalsIgnoreCase( "null" ))
throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 );
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 );
}
@ -162,6 +163,26 @@ public class EC2InstanceFilterSet {
for (String group : groupSet)
if (containsString(group, valueSet)) return true;
return false;
}
else if (filterName.equalsIgnoreCase("tag-key"))
{
EC2TagKeyValue[] tagSet = vm.getResourceTags();
for (EC2TagKeyValue tag : tagSet)
if (containsString(tag.getKey(), valueSet)) return true;
return false;
}
else if (filterName.equalsIgnoreCase("tag-value"))
{
EC2TagKeyValue[] tagSet = vm.getResourceTags();
for (EC2TagKeyValue tag : tagSet) {
if (tag.getValue() == null) {
if (containsEmptyValue(valueSet)) return true;
}
else {
if (containsString(tag.getValue(), valueSet)) return true;
}
}
return false;
}
else return false;
}
@ -178,8 +199,14 @@ public class EC2InstanceFilterSet {
}
return false;
}
private boolean containsEmptyValue( String[] set )
{
for( int i=0; i < set.length; i++ )
if (set[i].isEmpty()) return true;
return false;
}
private boolean containsInteger( int lookingFor, String[] set )
{
for( int i=0; i < set.length; i++ )

View File

@ -16,6 +16,9 @@
// under the License.
package com.cloud.bridge.service.core.ec2;
import com.cloud.bridge.service.exception.EC2ServiceException;
import com.cloud.bridge.service.exception.EC2ServiceException.ClientError;
public class EC2RegisterImage {
private String location;
@ -67,14 +70,19 @@ public class EC2RegisterImage {
*/
public void setArchitecture( String param ) {
if (null != param) {
String parts[] = param.split( ":" );
if (3 <= parts.length) {
format = parts[0];
zoneName = parts[1];
osTypeName = parts[2];
hypervisor = parts[3];
}
}
if (!param.contains(":") || param.split(":").length < 4) {
throw new EC2ServiceException( ClientError.InvalidParameterValue, "Supported format for " +
"'architecture' is format:zonename:ostypename:hypervisor" );
}
String parts[] = param.split( ":" );
format = parts[0];
zoneName = parts[1];
osTypeName = parts[2];
hypervisor = parts[3];
}
else {
throw new EC2ServiceException(ClientError.Unsupported, "Missing Parameter -" + " architecture");
}
}
public String getFormat() {

View File

@ -0,0 +1,64 @@
// 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;
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;
}
}

View File

@ -16,7 +16,9 @@
// under the License.
package com.cloud.bridge.service.core.ec2;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import com.cloud.bridge.util.EC2RestAuth;
@ -31,6 +33,7 @@ public class EC2Snapshot {
private Calendar created;
private String accountName;
private String domainId;
private List<EC2TagKeyValue> tagsSet;
public EC2Snapshot() {
id = null;
@ -42,6 +45,7 @@ public class EC2Snapshot {
created = null;
accountName = null;
domainId = null;
tagsSet = new ArrayList<EC2TagKeyValue>();
}
public void setId(String id ) {
@ -116,4 +120,12 @@ public class EC2Snapshot {
public void setState(String state) {
this.state = state;
}
public void addResourceTag( EC2TagKeyValue param ) {
tagsSet.add( param );
}
public EC2TagKeyValue[] getResourceTags() {
return tagsSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -46,20 +46,23 @@ public class EC2SnapshotFilterSet {
filterTypes.put( "status", "string" );
filterTypes.put( "volume-id", "string" );
filterTypes.put( "volume-size", "string" );
filterTypes.put( "tag-key", "string" );
filterTypes.put( "tag-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 );
if (!filterName.startsWith("tag:")) {
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 );
}
// ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
filterSet.add( param );
}
@ -140,6 +143,26 @@ public class EC2SnapshotFilterSet {
{
return containsLong( snap.getVolumeSize(), valueSet );
}
else if (filterName.equalsIgnoreCase("tag-key"))
{
EC2TagKeyValue[] tagSet = snap.getResourceTags();
for (EC2TagKeyValue tag : tagSet)
if (containsString(tag.getKey(), valueSet)) return true;
return false;
}
else if (filterName.equalsIgnoreCase("tag-value"))
{
EC2TagKeyValue[] tagSet = snap.getResourceTags();
for (EC2TagKeyValue tag : tagSet){
if (tag.getValue() == null) {
if (containsEmptyValue(valueSet)) return true;
}
else {
if (containsString(tag.getValue(), valueSet)) return true;
}
}
return false;
}
else return false;
}
@ -155,7 +178,13 @@ public class EC2SnapshotFilterSet {
return false;
}
private boolean containsEmptyValue( String[] set )
{
for( int i=0; i < set.length; i++ )
if (set[i].isEmpty()) return true;
return false;
}
private boolean containsLong( long lookingFor, String[] set )
{
for (String s : set) {

View File

@ -0,0 +1,44 @@
// 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;
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;
}
}

View File

@ -0,0 +1,47 @@
// 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 EC2TagTypeId {
private String resourceType;
private List<String> resourceIdSet = new ArrayList<String>();
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]);
}
}

View File

@ -0,0 +1,44 @@
// 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 EC2Tags {
private List<EC2TagTypeId> resourceTypeSet = new ArrayList<EC2TagTypeId>();
private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
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]);
}
}

View File

@ -0,0 +1,107 @@
// 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.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<EC2Filter> filterSet = new ArrayList<EC2Filter>();
private Map<String,String> filterTypes = new HashMap<String,String>();
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;
}
}

View File

@ -16,6 +16,9 @@
// under the License.
package com.cloud.bridge.service.core.ec2;
import java.util.ArrayList;
import java.util.List;
public class EC2Volume {
@ -32,6 +35,7 @@ public class EC2Volume {
private String hypervisor;
private String created;
private String attached;
private List<EC2TagKeyValue> tagsSet;
public EC2Volume() {
id = null;
@ -46,6 +50,7 @@ public class EC2Volume {
hypervisor = null;
created = null;
attached = null;
tagsSet = new ArrayList<EC2TagKeyValue>();
}
public void setSize(Long size) {
@ -230,5 +235,13 @@ public class EC2Volume {
public void setAttached(String attached) {
this.attached = attached;
}
public void addResourceTag( EC2TagKeyValue param ) {
tagsSet.add( param );
}
public EC2TagKeyValue[] getResourceTags() {
return tagsSet.toArray(new EC2TagKeyValue[0]);
}
}

View File

@ -49,8 +49,8 @@ public class EC2VolumeFilterSet {
filterTypes.put( "size", "integer" );
filterTypes.put( "snapshot-id", "string" );
filterTypes.put( "status", "set:creating|available|in-use|deleting|deleted|error" );
filterTypes.put( "tag-key", "null" );
filterTypes.put( "tag-value", "null" );
filterTypes.put( "tag-key", "string" );
filterTypes.put( "tag-value", "string" );
filterTypes.put( "volume-id", "string" );
// filterTypes.put( "tag:*", "null" );
}
@ -59,14 +59,13 @@ public class EC2VolumeFilterSet {
public void addFilter( EC2Filter param )
{
String filterName = param.getName();
String value = (String) filterTypes.get( filterName );
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 );
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 );
// ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
filterSet.add( param );
}
@ -136,7 +135,27 @@ public class EC2VolumeFilterSet {
else if (filterName.equalsIgnoreCase( "attachment.device" ))
return containsDevice(vol.getDeviceId(), valueSet );
else if (filterName.equalsIgnoreCase( "attachment.instance-id" ))
return containsString(String.valueOf(vol.getInstanceId()), valueSet );
return containsString(String.valueOf(vol.getInstanceId()), valueSet );
else if (filterName.equalsIgnoreCase("tag-key"))
{
EC2TagKeyValue[] tagSet = vol.getResourceTags();
for (EC2TagKeyValue tag : tagSet)
if (containsString(tag.getKey(), valueSet)) return true;
return false;
}
else if (filterName.equalsIgnoreCase("tag-value"))
{
EC2TagKeyValue[] tagSet = vol.getResourceTags();
for (EC2TagKeyValue tag : tagSet){
if (tag.getValue() == null) {
if (containsEmptyValue(valueSet)) return true;
}
else {
if (containsString(tag.getValue(), valueSet)) return true;
}
}
return false;
}
else return false;
}
@ -150,6 +169,12 @@ public class EC2VolumeFilterSet {
return false;
}
private boolean containsEmptyValue( String[] set )
{
for( int i=0; i < set.length; i++ )
if (set[i].isEmpty()) return true;
return false;
}
private boolean containsLong( long lookingFor, String[] set )
{

View File

@ -42,6 +42,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;
@ -313,7 +314,7 @@ public class CloudStackApi {
*/
public List<CloudStackUserVm> listVirtualMachines(String account, String accountId, Boolean listAll, Boolean forVirtualNetwork, String groupId, String hostId,
String hypervisor, String id, Boolean isRecursive, String keyWord, String name, String networkId, String podId, String state, String storageId,
String zoneId) throws Exception {
String zoneId, List<CloudStackKeyValue> resourceTags) throws Exception {
CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_VIRTUAL_MACHINES);
if (cmd != null) {
if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account);
@ -332,6 +333,8 @@ public class CloudStackApi {
if (state != null) cmd.setParam(ApiConstants.STATE, state);
if (storageId != null) cmd.setParam(ApiConstants.STORAGE_ID, storageId);
if (zoneId != null) cmd.setParam(ApiConstants.ZONE_ID, zoneId);
if (resourceTags != null && resourceTags.size() > 0)
cmd = setParams(cmd, null, null, resourceTags);
}
return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_VIRTUAL_MACHINES_RESPONSE, ApiConstants.VIRTUAL_MACHINE,
new TypeToken<List<CloudStackUserVm>>() {}.getType());
@ -934,7 +937,7 @@ public class CloudStackApi {
* @throws Exception
*/
public List<CloudStackVolume> listVolumes(String account, String domainId, String hostId, String id, Boolean isRecursive, String keyWord, String name,
String podId, String type, String virtualMachineId, String zoneId) throws Exception {
String podId, String type, String virtualMachineId, String zoneId, List<CloudStackKeyValue> resourceTags) throws Exception {
CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_VOLUMES);
if (cmd != null) {
if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account);
@ -948,6 +951,8 @@ public class CloudStackApi {
if (type != null) cmd.setParam(ApiConstants.TYPE, type);
if (virtualMachineId != null) cmd.setParam(ApiConstants.VIRTUAL_MACHINE_ID, virtualMachineId);
if (zoneId != null) cmd.setParam(ApiConstants.ZONE_ID, zoneId);
if (resourceTags != null && resourceTags.size() > 0)
cmd = setParams(cmd, null, null, resourceTags);
}
return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_VOLUMES_RESPONSE, ApiConstants.VOLUME,
new TypeToken<List<CloudStackVolume>>() {}.getType());
@ -973,7 +978,82 @@ 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, List<String>resourceIds,
List<CloudStackKeyValue> 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, List<String>resourceIds,
List<CloudStackKeyValue> 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<CloudStackResourceTag> 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<List<CloudStackResourceTag>>() {}.getType());
}
private CloudStackCommand setParams(CloudStackCommand cmd, String resourceType, List<String>resourceIds,
List<CloudStackKeyValue> resourceTags) {
if (cmd != null) {
if (resourceType != null)
cmd.setParam(ApiConstants.RESOURCE_TYPE, resourceType);
if (resourceIds != null && resourceIds.size() > 0) {
String resourceIdList = resourceIds.get(0);
for (int i=1 ; i<resourceIds.size(); i++)
resourceIdList = resourceIdList.concat(","+resourceIds.get(i));
cmd.setParam(ApiConstants.RESOURCE_IDS, resourceIdList);
}
if (resourceTags != null && resourceTags.size() > 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
@ -1168,7 +1248,7 @@ public class CloudStackApi {
* @throws Exception
*/
public List<CloudStackSnapshot> listSnapshots(String account, String domainId, String id, String intervalType, Boolean isRecursive,
String keyWord, String name, String snapshotType, String volumeId) throws Exception {
String keyWord, String name, String snapshotType, String volumeId, List<CloudStackKeyValue> resourceTags) throws Exception {
CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_SNAPSHOTS);
if (cmd != null) {
if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account);
@ -1180,6 +1260,8 @@ public class CloudStackApi {
if (name != null) cmd.setParam(ApiConstants.NAME, name);
if (snapshotType != null) cmd.setParam(ApiConstants.SNAPSHOT_TYPE, snapshotType);
if (volumeId != null) cmd.setParam(ApiConstants.VOLUME_ID, volumeId);
if (resourceTags != null && resourceTags.size() > 0)
cmd = setParams(cmd, null, null, resourceTags);
}
return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_SNAPSHOTS_RESPONSE, ApiConstants.SNAPSHOT,
new TypeToken<List<CloudStackSnapshot>>() {}.getType());

View File

@ -85,6 +85,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";
@ -114,6 +116,8 @@ public class ApiConstants {
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_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";
@ -228,6 +232,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";
@ -290,6 +295,8 @@ public class ApiConstants {
public static final String LIST_SSH_KEY_PAIRS = "listSSHKeyPairs";
public static final String LIST_SSH_KEY_PAIRS_RESPONSE = "listsshkeypairsresponse";
public static final String LIST_TEMPLATE_PERMISSIONS = "listTemplatePermissions";
public static final String LIST_TAGS = "listTags";
public static final String LIST_TAGS_RESPONSE = "listtagsresponse";
public static final String LIST_TEMPLATE_PERMISSIONS_RESPONSE = "listtemplatepermissionsresponse";
public static final String LIST_TEMPLATES = "listTemplates";
public static final String LIST_TEMPLATES_RESPONSE = "listtemplatesresponse";
@ -380,6 +387,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";
@ -433,6 +442,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";

View File

@ -0,0 +1,50 @@
// 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.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;
}
}

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.stack.models;
import java.util.List;
import com.google.gson.annotations.SerializedName;
public class CloudStackSnapshot {
@ -47,6 +49,8 @@ public class CloudStackSnapshot {
private String volumeName;
@SerializedName(ApiConstants.VOLUME_TYPE)
private String volumeType;
@SerializedName(ApiConstants.TAGS)
private List<CloudStackKeyValue> tags;
public CloudStackSnapshot() {
}
@ -106,4 +110,9 @@ public class CloudStackSnapshot {
public String getState() {
return state;
}
public List<CloudStackKeyValue> getTags() {
return tags;
}
}

View File

@ -17,6 +17,8 @@
package com.cloud.stack.models;
import java.util.List;
import com.google.gson.annotations.SerializedName;
public class CloudStackTemplate {
@ -82,6 +84,8 @@ public class CloudStackTemplate {
private String zoneId;
@SerializedName(ApiConstants.ZONE_NAME)
private String zoneName;
@SerializedName(ApiConstants.TAGS)
private List<CloudStackKeyValue> tags;
/**
*
@ -306,4 +310,10 @@ public class CloudStackTemplate {
return zoneName;
}
/**
* @return all tags
*/
public List<CloudStackKeyValue> getTags() {
return tags;
}
}

View File

@ -103,6 +103,8 @@ public class CloudStackUserVm {
private List<CloudStackNic> nics;
@SerializedName(ApiConstants.SECURITY_GROUP)
private List<CloudStackSecurityGroup> securityGroupList;
@SerializedName(ApiConstants.TAGS)
private List<CloudStackKeyValue> tags;
public CloudStackUserVm() {
}
@ -394,5 +396,12 @@ public class CloudStackUserVm {
return securityGroupList;
}
/**
* @return all tags
*/
public List<CloudStackKeyValue> getTags() {
return tags;
}
}

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.stack.models;
import java.util.List;
import com.google.gson.annotations.SerializedName;
public class CloudStackVolume {
@ -81,6 +83,8 @@ public class CloudStackVolume {
private String zoneId;
@SerializedName(ApiConstants.ZONE_NAME)
private String zoneName;
@SerializedName(ApiConstants.TAGS)
private List<CloudStackKeyValue> tags;
public CloudStackVolume() {
@ -334,4 +338,10 @@ public class CloudStackVolume {
return zoneName;
}
/**
* @return all tags
*/
public List<CloudStackKeyValue> getTags() {
return tags;
}
}

View File

@ -82,7 +82,7 @@
<include name="cloud-commons-collections-3.2.1.jar" />
<include name="cloud-commons-codec-1.4.jar" />
<include name="cloud-commons-pool-1.4.jar" />
<include name="cloud-libvirt-0.4.5.jar" />
<include name="libvirt-0.4.8.jar" />
<include name="cloud-jna.jar" />
<include name="cloud-cglib.jar" />
<include name="jetty-6.1.26.jar" />

View File

@ -1,351 +0,0 @@
/*
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.
*/
/*
UNIX daemonizer. Daemonizes any non-interactive console program and watches over it.
Whenever a signal is sent to this process, it halts the daemonized process as well.
To compile: cc -o daemonize daemonize.c
Usage: ./daemonize -?
Users of this: catalina initscript
*/
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <pwd.h>
#define RUNNING_DIR "/"
#define PIDFILE "/var/run/daemonize.pid"
#define VARLOGFILE "/var/log/daemon.log"
#define PROGNAME "daemonized"
#define DEFAULTUSER "root"
char * pidfile = PIDFILE;
char * varlogfile = VARLOGFILE;
char * progname = PROGNAME;
char * user = PROGNAME;
void initialize_syslog(const char*pn) {
openlog(pn,LOG_PID,LOG_DAEMON);
syslog(LOG_INFO, "syslog connection opened");
}
void cleanup_syslog() {
syslog(LOG_INFO, "syslog connection closed");
closelog();
}
int killed = 0;
int killsignal = 0;
int pidfile_fd;
int varlogfile_fd;
int uid = 0; int gid = 0;
struct passwd *creds;
void signal_handler(sig)
int sig;
{
killsignal = sig;
switch(sig) {
case SIGCHLD:
syslog(LOG_INFO,"sigchild signal caught");
break;
case SIGHUP:
syslog(LOG_INFO,"hangup signal caught");
killed = 1;
break;
case SIGTERM:
syslog(LOG_INFO,"terminate signal caught");
killed = 1;
break;
case SIGINT:
syslog(LOG_INFO,"keyboard interrupt signal caught");
killed = 1;
break;
}
}
int daemonize(const char*prog_name)
{
char str[10];
int i;
int bufsize=1024; char *buf = malloc(1024);
umask( S_IWGRP | S_IROTH | S_IWOTH ); /* set newly created file permissions */
/* test logfile */
varlogfile_fd=open(varlogfile,O_RDWR|O_CREAT|O_APPEND,0666);
if (varlogfile_fd == -1) {
snprintf(buf,bufsize,"Could not open output file %s -- exiting",varlogfile); perror(buf);
return 1; /* exitvalue */
}
if (uid != 0) {
chown(varlogfile,uid,gid);
}
close(varlogfile_fd);
pidfile_fd=open(pidfile,O_RDWR|O_CREAT,0666);
if (pidfile_fd<0) {
snprintf(buf,bufsize,"The PID file %s cannot be opened -- exiting",pidfile); perror(buf);
return 2; /* exitvalue */
}
if (lockf(pidfile_fd,F_TEST,0)==1) {
snprintf(buf,bufsize,"A daemon is already running (cannot lock PID file %s) -- exiting",pidfile); perror(buf);
return 3; /* exitvalue */
}
close(pidfile_fd);
if(getppid()==1) return 0; /* already a daemon */
i=fork();
if (i < 0) return 4; /* exitvalue */ /* fork error */
if (i > 0) exit(0); /* parent exits */
/* child (daemon) continues */
setsid(); /* obtain a new process group */
chdir(RUNNING_DIR); /* change running directory */
/* close FDs and reopen to logfile */
for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */
varlogfile_fd=open(varlogfile,O_RDWR|O_APPEND,0666); dup(varlogfile_fd); dup(varlogfile_fd); /* handle standart I/O */
initialize_syslog(prog_name); /* set up syslog */
/* PID file */
pidfile_fd=open(pidfile,O_RDWR|O_CREAT,0666);
if (pidfile_fd<0) {
syslog(LOG_ERR,"The PID file %s cannot be opened (%m) -- exiting",pidfile);
return 2; /* exitvalue */
}
if (lockf(pidfile_fd,F_TLOCK,0)<0) {
syslog(LOG_ERR,"A daemon is already running -- cannot lock PID file %s (%m) -- exiting",pidfile);
return 3; /* exitvalue */
}
/* first instance continues */
/* record pid to pidfile */
sprintf(str,"%d\n",getpid());
if (write(pidfile_fd,str,strlen(str)) < strlen(str)) {
syslog(LOG_ERR,"Could not write PID into PID file %s (%m) -- exiting",pidfile);
return 5; /* exitvalue */
}
signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGHUP,signal_handler); /* catch hangup signal */
signal(SIGTERM,signal_handler); /* catch kill signal */
signal(SIGINT,signal_handler); /* catch keyboard interrupt signal */
return 0;
}
void cleanup() {
cleanup_syslog();
unlink(pidfile);
close(pidfile_fd);
close(varlogfile_fd);
}
void usage(char * cmdname) {
fprintf (stderr,
"Usage: %s [options...] -- <command> [command-specific arguments...]\n"
"Daemonize any program.\n"
"\n"
"Options:\n"
"\n"
" -l <logfile>: log stdout/stderr to this *absolute* path (default "VARLOGFILE")\n"
" -u <username>: setuid() to this user name before starting the program (default "DEFAULTUSER")\n"
" -p <pidfile>: lock and write the PID to this *absolute* path (default "PIDFILE")\n"
" -n <progname>: name the daemon assumes (default "PROGNAME")\n"
" -h: show this usage guide\n"
"\n"
"Exit status:\n"
" 0 if daemonized correctly\n"
" other if an error took place\n"
"", cmdname);
exit(0);
}
int parse_args(int argc,char ** argv) {
int index;
int c;
// pidfile = PIDFILE;
// varlogfile = VARLOGFILE;
// progname = PROGNAME;
opterr = 0;
while ((c = getopt (argc, argv, "l:p:n:u:")) != -1)
switch (c)
{
case 'l':
varlogfile = optarg;
break;
case 'p':
pidfile = optarg;
break;
case 'n':
progname = optarg;
break;
case 'u':
if (getuid() != 0) {
fprintf (stderr, "-u can only be used by root.\nSee help with -h\n", user);
exit(64);
}
user = optarg;
creds = getpwnam(user);
if (creds == NULL) {
fprintf (stderr, "User %s was not found in the user database.\nSee help with -h\n", user);
exit(63);
}
uid = creds->pw_uid; gid = creds->pw_gid;
break;
// case 'h':
// break;
// usage(argv[0]); /* halts after this */
case '?':
if (optopt == '?' || optopt == 'h')
usage(argv[0]); /* halts after this */
if (optopt == 'l' || optopt == 'p' || optopt == 'n')
fprintf (stderr, "Option -%c requires an argument.\nSee help with -h\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\nSee help with -h\n", optopt);
else
fprintf (stderr, "Unknown option character `\\x%x'.\nSee help with -h\n", optopt);
exit(64); /* exitvalue */
default:
abort ();
}
for (index = optind; index < argc; index++);
if (index == optind) {
fprintf (stderr, "You need to specify a command to run.\nSee help with -h\n", optopt);
exit(64); /* exitvalue */
}
return optind;
}
int main(int argc, char** argv)
{
/* parse command line arguments, we will use the first non-option one as the starting point */
int i;
char ** newargv = calloc(argc+1, sizeof(char**));
int startat = parse_args(argc,argv);
int newargc = argc - startat;
for (i = startat; i < argc; i++) { newargv[i-startat] = argv[i]; }
/* try and daemonize */
int daemonret = daemonize(progname);
if (daemonret) exit(daemonret);
syslog(LOG_INFO,"successfully daemonized");
/* fork */
int pid, wpid, status, execret;
syslog(LOG_INFO,"starting %s in subprocess",newargv[0]);
pid = fork();
if (pid < 0) {
/* failed to fork, damnit! */
syslog(LOG_ERR,"could not fork to run %s as a child process (%m)",newargv[0]);
exit(4); /* exitvalue */
}
else if (pid == 0) {
/* child */
if (uid != 0) {
execret = setgid(gid);
if (execret == -1) {
syslog(LOG_ERR,"could not setgid() to gid %d",gid);
exit(8); /* exitvalue */
}
execret = setuid(uid);
if (execret == -1) {
syslog(LOG_ERR,"could not setuid() to uid %d",uid);
exit(8); /* exitvalue */
}
}
execret = execvp(newargv[0],newargv);
if (errno == 2) {
syslog(LOG_ERR,"could not run program: no such file or directory");
exit(127);
}
if (errno == 13) {
syslog(LOG_ERR,"could not run program: permission denied");
exit(126);
}
syslog(LOG_ERR,"could not run program: unknown reason");
exit(255);
}
/* parent continues here */
syslog(LOG_INFO,"successfully started subprocess -- PID %d",pid);
int finalexit = 0;
int waitret = 0;
while (1) {
if (killed) {
kill(pid,killsignal);
killed = 0;
}
waitret = waitpid(pid,&status,WNOHANG);
if (waitret == pid) break;
usleep(250000);
}
if WIFEXITED(status) {
switch (WEXITSTATUS(status)) {
case 0:
syslog(LOG_INFO,"%s exited normally",newargv[0]);
break;
case 126:
syslog(LOG_ERR,"%s: permission denied",newargv[0]);
finalexit = 126; /* exitvalue */
break;
case 127:
syslog(LOG_ERR,"%s: command not found",newargv[0]);
finalexit = 127; /* exitvalue */
break;
default:
syslog(LOG_INFO,"%s exited abnormally with status %d",newargv[0],WEXITSTATUS(status));
finalexit = 6; /* exitvalue */
}
}
if WIFSIGNALED(status) {
syslog(LOG_INFO,"%s was killed with signal %d",newargv[0],WTERMSIG(status));
finalexit = 7; /* exitvalue */
}
syslog(LOG_INFO,"shutting down");
cleanup();
exit(finalexit);
}
/* EOF */

View File

@ -1,3 +1,3 @@
/usr/share/java/cloud-google-gson-1.7.1.jar
/usr/share/java/cloud-libvirt-0.4.5.jar
/usr/share/java/libvirt-0.4.8.jar
/usr/share/java/cloud-log4j-extras.jar

4
debian/control vendored
View File

@ -123,7 +123,7 @@ Provides: vmops-agent
Conflicts: vmops-agent
Replaces: vmops-agent
Architecture: any
Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-agent-deps (= ${source:Version}), python, cloud-python (= ${source:Version}), cloud-agent-libs (= ${source:Version}), cloud-agent-scripts (= ${source:Version}), libcommons-httpclient-java, libcommons-collections-java, libcommons-dbcp-java, libcommons-pool-java, libcommons-logging-java, libvirt0, sysvinit-utils, chkconfig, qemu-kvm, libvirt-bin, uuid-runtime, rsync, grep, iproute, ebtables, vlan, libcglib-java, libcommons-httpclient-java, libservlet2.5-java, liblog4j1.2-java, libjna-java, wget
Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-agent-deps (= ${source:Version}), python, cloud-python (= ${source:Version}), cloud-agent-libs (= ${source:Version}), cloud-agent-scripts (= ${source:Version}), libcommons-httpclient-java, libcommons-collections-java, libcommons-dbcp-java, libcommons-pool-java, libcommons-logging-java, libvirt0, sysvinit-utils, chkconfig, qemu-kvm, libvirt-bin, uuid-runtime, rsync, grep, iproute, ebtables, vlan, libcglib-java, libcommons-httpclient-java, libservlet2.5-java, liblog4j1.2-java, libjna-java, wget, jsvc
Description: CloudStack agent
The CloudStack agent is in charge of managing shared computing resources in
a CloudStack Cloud Stack-powered cloud. Install this package if this computer
@ -141,7 +141,7 @@ Provides: vmops-usage
Conflicts: vmops-usage
Replaces: vmops-usage
Architecture: any
Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-deps (= ${source:Version}), cloud-server (= ${source:Version}), cloud-setup (= ${source:Version}), cloud-client (= ${source:Version})
Depends: openjdk-6-jre, cloud-utils (= ${source:Version}), cloud-core (= ${source:Version}), cloud-deps (= ${source:Version}), cloud-server (= ${source:Version}), cloud-setup (= ${source:Version}), cloud-client (= ${source:Version}), jsvc
Description: CloudStack usage monitor
The CloudStack usage monitor provides usage accounting across the entire cloud for
cloud operators to charge based on usage parameters.

2
deps/.classpath vendored
View File

@ -15,7 +15,7 @@
<classpathentry exported="true" kind="lib" path="cloud-jasypt-1.8.jar"/>
<classpathentry exported="true" kind="lib" path="cloud-jsch-0.1.42.jar"/>
<classpathentry exported="true" kind="lib" path="cloud-jstl-1.2.jar"/>
<classpathentry exported="true" kind="lib" path="cloud-libvirt-0.4.5.jar"/>
<classpathentry exported="true" kind="lib" path="libvirt-0.4.8.jar"/>
<classpathentry exported="true" kind="lib" path="cloud-log4j.jar" sourcepath="/home/dev/thirdparty/apache-log4j-1.2.16/src/main/java"/>
<classpathentry exported="true" kind="lib" path="cloud-mysql-connector-java-5.1.7-bin.jar"/>
<classpathentry exported="true" kind="lib" path="cloud-servlet-api.jar"/>

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import org.apache.log4j.Logger;
@ -102,4 +107,4 @@ public class AddExternalLoadBalancerCmd extends BaseCmd {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, cre.getMessage());
}
}
}
}

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import org.apache.log4j.Logger;
@ -127,4 +132,4 @@ public class AddF5LoadBalancerCmd extends BaseAsyncCmd {
public long getEntityOwnerId() {
return UserContext.current().getCaller().getId();
}
}
}

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import org.apache.log4j.Logger;

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import org.apache.log4j.Logger;

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import org.apache.log4j.Logger;

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import java.util.ArrayList;

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import java.util.ArrayList;

View File

@ -1,15 +1,20 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
// 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.api.commands;
import java.util.ArrayList;

View File

@ -3210,10 +3210,25 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
} else {
if (assignedPool.getId() != vol.getPoolId()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Volume " + vol + " is not recreatable! Cannot recreate on storagepool: " + assignedPool);
s_logger.debug("Mismatch in storage pool " + assignedPool + " assigned by deploymentPlanner and the one associated with volume " + vol);
}
if (vm.getServiceOffering().getUseLocalStorage())
{
if (s_logger.isDebugEnabled()) {
s_logger.debug("Local volume " + vol + " will be recreated on storage pool " + assignedPool + " assigned by deploymentPlanner");
}
recreateVols.add(vol);
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Shared volume " + vol + " will be migrated on storage pool " + assignedPool + " assigned by deploymentPlanner");
}
try {
Volume migratedVol = migrateVolume(vol.getId(), assignedPool.getId());
vm.addDisk(new VolumeTO(migratedVol, assignedPool));
} catch (ConcurrentOperationException e) {
throw new StorageUnavailableException("Volume migration failed for " + vol, Volume.class, vol.getId());
}
}
throw new StorageUnavailableException("Volume is not recreatable, Unable to create " + vol, Volume.class, vol.getId());
// copy volume usecase - not yet developed.
} else {
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
vm.addDisk(new VolumeTO(vol, pool));

View File

@ -336,4 +336,13 @@ public class MockAccountManagerImpl implements Manager, AccountManager {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.cloud.user.AccountService#getUserByApiKey(java.lang.String)
*/
@Override
public UserAccount getUserByApiKey(String apiKey) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -8952,6 +8952,204 @@ div.panel.ui-dialog div.list-view div.fixed-header {
background: #DFE1E3;
}
/*Tagger*/
.tagger {
width: 94%;
margin: auto;
padding-bottom: 12px;
background: #F2F0F0;
border: 1px solid #CFC9C9;
/*+placement:shift -4px 0px;*/
position: relative;
left: -4px;
top: 0px;
}
.tagger .field {
width: 179px;
float: left;
position: relative;
}
.tagger .tag-info {
font-size: 11px;
color: #757575;
margin-top: 12px;
margin-left: 8px;
}
.tagger .tag-info.title {
font-size: 11px;
color: #6F9BF0;
margin-bottom: 5px;
}
.tagger form {
margin: 12px 9px 0px;
}
.tagger.readonly form {
display: none;
}
.tagger form label {
display: block;
float: left;
width: 28px;
text-align: right;
font-size: 10px;
color: #394552;
margin-right: 9px;
/*+placement:shift 5px 8px;*/
position: relative;
left: 5px;
top: 8px;
}
.tagger form label.error {
position: absolute;
color: #FF0000;
left: 42px;
top: 29px;
/*[empty]background-color:;*/
}
.tagger form input {
padding: 4px;
background: #FFFFFF;
border: 1px solid #808080;
/*+border-radius:4px;*/
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-khtml-border-radius: 4px;
border-radius: 4px;
}
.tagger form input[type=submit] {
background: url(../images/bg-gradients.png) repeat-x 0px -220px;
cursor: pointer;
color: #FFFFFF;
/*+text-shadow:0px -1px 2px #000000;*/
-moz-text-shadow: 0px -1px 2px #000000;
-webkit-text-shadow: 0px -1px 2px #000000;
-o-text-shadow: 0px -1px 2px #000000;
text-shadow: 0px -1px 2px #000000;
border: none;
/*+border-radius:4px;*/
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-khtml-border-radius: 4px;
border-radius: 4px;
padding: 7px 25px 7px 26px;
margin-left: 16px;
}
.tagger form input[type=submit]:hover {
background-position: 0px -946px;
}
.tagger ul {
display: block;
width: 96%;
margin: 16px auto auto;
/*+border-radius:2px;*/
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
-khtml-border-radius: 2px;
border-radius: 2px;
overflow: auto;
padding-bottom: 10px;
border: 1px solid #D2D2D2;
background: #FFFFFF;
/*+box-shadow:inset 0px 0px 10px #DCDCDC;*/
-moz-box-shadow: inset 0px 0px 10px #DCDCDC;
-webkit-box-shadow: inset 0px 0px 10px #DCDCDC;
-o-box-shadow: inset 0px 0px 10px #DCDCDC;
box-shadow: inset 0px 0px 10px #DCDCDC;
}
.tagger.readonly ul {
}
.tagger ul li {
background: #DFDFDF 0px 4px;
height: 15px;
padding: 0px 18px 0 7px;
display: inline-block;
float: left;
margin-left: 7px;
margin-right: 2px;
margin-top: 5px;
/*+border-radius:4px;*/
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-khtml-border-radius: 4px;
border-radius: 4px;
/*+placement:shift 0px 2px;*/
position: relative;
left: 0px;
top: 2px;
}
.tagger ul li span {
color: #000000;
}
.tagger ul li span.label {
font-size: 10px;
position: relative;
left: 15px;
top: -2px;
}
.tagger.readonly ul li span.label {
left: 6px;
}
.tagger ul li span.remove {
width: 15px !important;
overflow: hidden !important;
height: 11px !important;
background: #DFDFDF url(../images/sprites.png) no-repeat -596px -1183px;
display: block;
top: 0px !important;
left: -3px !important;
text-indent: 4px;
padding: 4px 0px 0px 8px;
font-size: 8px;
font-weight: bold;
cursor: pointer;
position: absolute !important;
color: #5B5B5B;
}
.tagger.readonly ul li span.remove {
display: none;
}
.tagger ul li span.remove:hover {
color: #000000;
}
/** Dialog tagger*/
.ui-dialog .tagger {
}
.ui-dialog .tagger .field {
width: 119px !important;
}
.ui-dialog .tagger input.key,
.ui-dialog .tagger input.value {
width: 66px !important;
height: 15px;
font-size: 11px !important;
}
.ui-dialog .tagger input[type=submit] {
padding: 6px 15px;
}
/*VPC / vApps*/
.vpc-chart {
width: 100%;

View File

@ -1614,7 +1614,8 @@
<script type="text/javascript" src="scripts/ui/widgets/listView.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui/widgets/detailView.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui/widgets/treeView.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui/widgets/notifications.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui/widgets/notifications.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui/widgets/tagger.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/cloud.core.callbacks.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/sharedFunctions.js?t=<%=now%>"></script>

View File

@ -617,5 +617,83 @@ cloudStack.api = {
}
}
}
},
tags: function(args) {
var resourceType = args.resourceType;
var contextId = args.contextId;
return {
actions: {
add: function(args) {
var data = args.data;
var resourceId = args.context[contextId][0].id;
$.ajax({
url: createURL(
'createTags&tags[0].key=' + data.key + '&tags[0].value=' + data.value
),
data: {
resourceIds: resourceId,
resourceType: resourceType
},
success: function(json) {
args.response.success({
_custom: { jobId: json.createtagsresponse.jobid },
notification: {
desc: 'Add tag for instance',
poll: pollAsyncJobResult
}
});
}
});
},
remove: function(args) {
var data = args.context.tagItems[0];
var resourceId = args.context[contextId][0].id;
$.ajax({
url: createURL(
'deleteTags&tags[0].key=' + data.key + '&tags[0].value=' + data.value
),
data: {
resourceIds: resourceId,
resourceType: resourceType
},
success: function(json) {
args.response.success({
_custom: { jobId: json.deletetagsresponse.jobid },
notification: {
desc: 'Remove tag for instance',
poll: pollAsyncJobResult
}
});
}
});
}
},
dataProvider: function(args) {
var resourceId = args.context[contextId][0].id;
$.ajax({
url: createURL('listTags'),
data: {
listAll: true,
resourceId: resourceId,
resourceType: resourceType
},
success: function(json) {
args.response.success({
data: json.listtagsresponse ?
json.listtagsresponse.tag : []
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
}
};
}
};

View File

@ -287,10 +287,14 @@
* @param callback
*/
edit: function($detailView, args) {
$detailView.addClass('edit-mode');
if ($detailView.find('.button.done').size()) return false;
// Convert value TDs
var $inputs = $detailView.find('input, select');
var $inputs = $detailView.find('input, select').filter(function() {
return !$(this).closest('.tagger').size() && !$(this).attr('type') == 'submit';
});
var action = args.actions[args.actionName];
var id = $detailView.data('view-args').id;
var $editButton = $('<div>').addClass('button done').html(_l('label.apply')).hide();
@ -302,9 +306,14 @@
$detailView.find('.ui-tabs-panel .detail-group.actions')
).fadeIn();
$detailView.find('.tagger').removeClass('readonly');
$detailView.find('.tagger').find('input[type=text]').val('');
var convertInputs = function($inputs) {
// Save and turn back into labels
$inputs.each(function() {
if ($(this).closest('.tagger').size()) return true;
var $input = $(this);
var $value = $input.closest('td.value span');
@ -328,8 +337,12 @@
};
var removeEditForm = function() {
$detailView.removeClass('edit-mode');
// Remove Edit form
var $form = $detailView.find('form');
var $form = $detailView.find('form').filter(function() {
return !$(this).closest('.tagger').size();
});
if ($form.size()) {
var $mainGroups = $form.find('div.main-groups').detach();
$form.parent('div').append($mainGroups);
@ -337,11 +350,15 @@
}
//Remove required labels
$detailView.find('span.field-required').remove();
}
$detailView.find('.tagger').addClass('readonly');
};
// Put in original values
var cancelEdits = function($inputs, $editButton) {
$inputs.each(function() {
if ($(this).closest('.tagger').size()) return true;
var $input = $(this);
var $value = $input.closest('td.value span');
var originalValue = $input.data('original-value');
@ -424,8 +441,12 @@
};
$editButton.click(function() {
var $inputs = $detailView.find('input, select'),
$form = $detailView.find('form');
var $inputs = $detailView.find('input, select').filter(function() {
return !$(this).closest('.tagger').size();
});
var $form = $detailView.find('form').filter(function() {
return !$(this).closest('.tagger').size();
});
if ($(this).hasClass('done')) {
if (!$form.valid()) {
@ -438,6 +459,8 @@
} else { // Cancel
cancelEdits($inputs, $editButton);
}
return true;
});
$detailView.find('td.value span').each(function() {
@ -511,8 +534,11 @@
}
// Setup form validation
$detailView.find('form').validate();
$detailView.find('form').find('input, select').each(function() {
var $form = $detailView.find('form').filter(function() {
return !$(this).closest('.tagger').size();
});
$form.validate();
$form.find('input, select').each(function() {
var data = $(this).parent('span').data('validation-rules');
if (data) {
$(this).rules('add', data);
@ -934,6 +960,14 @@
actionFilter: actionFilter
}).appendTo($tabContent);
if (tabs.tags) {
$('<div>').tagger(
$.extend(true, {}, tabs.tags, {
context: $detailView.data('view-args').context
})
).appendTo($detailView.find('.main-groups')).addClass('readonly');
}
return true;
},
error: function() {

View File

@ -332,10 +332,16 @@
after: function(args) {
var $loading = $('<div>').addClass('loading-overlay').prependTo($dataItem);
performAction({ data: args.data, complete: function() {
$multi.multiEdit('refresh');
$multi.trigger('refresh');
} });
}
});
if (options.tags) {
$(':ui-dialog').append(
$('<div>').addClass('multi-edit-tags').tagger(options.tags)
);
}
}
})
);
@ -652,6 +658,7 @@
$.fn.multiEdit = function(args) {
var dataProvider = args.dataProvider;
var multipleAdd = args.multipleAdd;
var tags = args.tags;
var $multi = $('<div>').addClass('multi-edit').appendTo(this);
var $multiForm = $('<form>').appendTo($multi);
var $inputTable = $('<table>').addClass('multi-edit').appendTo($multiForm);
@ -918,7 +925,8 @@
context: $.extend(true, {}, context, this._context),
ignoreEmptyFields: ignoreEmptyFields,
preFilter: actionPreFilter,
listView: listView
listView: listView,
tags: tags
}
).appendTo($dataBody);
});

View File

@ -0,0 +1,201 @@
(function($, cloudStack) {
var elems = {
inputArea: function(args) {
var $form = $('<form>').addClass('tag-input');
var $keyField = $('<div>').addClass('field key');
var $keyLabel = $('<label>').attr('for', 'key').html('Key:');
var $key = $('<input>').addClass('key required').attr('name', 'key');
var $valueField = $('<div>').addClass('field value');
var $valueLabel = $('<label>').attr('for', 'value').html('Value:');
var $value = $('<input>').addClass('value required').attr('name', 'value');
var $submit = $('<input>').attr('type', 'submit').val('Add');
$keyField.append($keyLabel, $key);
$valueField.append($valueLabel, $value);
$form.append(
$keyField, $valueField,
$submit
);
$form.validate({ onfocusout: false });
$form.submit(
args.onSubmit ?
function() {
if (!$form.valid()) return false;
args.onSubmit({
data: cloudStack.serializeForm($form),
response: {
success: function() {
// Restore editing of input
$key.attr('disabled', false);
$value.attr('disabled', false);
// Clear out old data
$key.val(''); $value.val('');
$key.focus();
},
error: function() {
// Restore editing of input
$key.attr('disabled', false);
$value.attr('disabled', false);
$key.focus();
}
}
});
// Prevent input during submission
$key.attr('disabled', 'disabled');
$value.attr('disabled', 'disabled');
return false;
} :
function() { return false; }
);
return $form;
},
tagItem: function(title, onRemove, data) {
var $li = $('<li>');
var $label = $('<span>').addClass('label').html(title);
var $remove = $('<span>').addClass('remove').html('X');
$remove.click(function() {
if (onRemove) onRemove($li, data);
});
$li.append($remove, $label);
return $li;
},
info: function(text) {
var $info = $('<div>').addClass('tag-info');
var $text = $('<span>').html(text);
$text.appendTo($info);
return $info;
}
};
$.widget('cloudStack.tagger', {
_init: function(args) {
var context = this.options.context;
var dataProvider = this.options.dataProvider;
var actions = this.options.actions;
var $container = this.element.addClass('tagger');
var $tagArea = $('<ul>').addClass('tags');
var $title = elems.info('Tags').addClass('title');
var $loading = $('<div>').addClass('loading-overlay');
var onRemoveItem = function($item, data) {
$loading.appendTo($container);
actions.remove({
context: $.extend(true, {}, context, {
tagItems: [data]
}),
response: {
success: function(args) {
var notification = $.extend(true, {} , args.notification, {
interval: 500,
_custom: args._custom
});
cloudStack.ui.notifications.add(
notification,
// Success
function() {
$loading.remove();
$item.remove();
}, {},
// Error
function() {
$loading.remove();
}, {}
);
},
error: function(message) {
$loading.remove();
cloudStack.dialog.notice({ message: message });
}
}
});
};
var $inputArea = elems.inputArea({
onSubmit: function(args) {
var data = args.data;
var success = args.response.success;
var error = args.response.error;
var title = data.key + ' = ' + data.value;
$loading.appendTo($container);
actions.add({
data: data,
context: context,
response: {
success: function(args) {
var notification = $.extend(true, {} , args.notification, {
interval: 500,
_custom: args._custom
});
cloudStack.ui.notifications.add(
notification,
// Success
function() {
$loading.remove();
elems.tagItem(title, onRemoveItem, data).appendTo($tagArea);
success();
}, {},
// Error
function() {
$loading.remove();
error();
}, {}
);
},
error: function(message) {
$loading.remove();
error();
cloudStack.dialog.notice({ message: message });
}
}
});
}
});
$container.append($title, $inputArea, $tagArea);
// Get data
$loading.appendTo($container);
dataProvider({
context: context,
response: {
success: function(args) {
var data = args.data;
$loading.remove();
$(data).map(function(index, item) {
var key = item.key;
var value = item.value;
var data = { key: key, value: value };
elems.tagItem(key + ' = ' + value, onRemoveItem, data).appendTo($tagArea);
});
},
error: function(message) {
$loading.remove();
$container.find('ul').html(message);
}
}
});
}
});
}(jQuery, cloudStack));

View File

@ -18,11 +18,29 @@ LOCKFILE=@LOCKDIR@/"$SHORTNAME"
LOGFILE=@USAGELOG@
PROGNAME="CloudStack Usage Monitor"
USER=@MSUSER@
CLASS="com.cloud.usage.UsageServer"
unset OPTIONS
[ -r @SYSCONFDIR@/default/"$SHORTNAME" ] && source @SYSCONFDIR@/default/"$SHORTNAME"
DAEMONIZE=@BINDIR@/@PACKAGE@-daemonize
PROG=@LIBEXECDIR@/usage-runner
# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm"
for jdir in $JDK_DIRS; do
if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
JAVA_HOME="$jdir"
fi
done
export JAVA_HOME
SCP="@SYSTEMCLASSPATH@"
DCP="@DEPSCLASSPATH@"
UCP="@USAGECLASSPATH@"
JCP="/usr/share/java/commons-daemon.jar"
# We need to append the JSVC daemon JAR to the classpath
# AgentShell implements the JSVC daemon methods
export CLASSPATH="$SCP:$DCP:$UCP:$JCP:@USAGESYSCONFDIR@"
start() {
log_daemon_msg $"Starting $PROGNAME" "$SHORTNAME"
@ -39,9 +57,7 @@ start() {
exit 1
fi
if start-stop-daemon --start --quiet \
--pidfile "$PIDFILE" \
--exec "$DAEMONIZE" -- -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" -u "$USER" "$PROG" $OPTIONS
if jsvc -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" $CLASS
RETVAL=$?
then
rc=0
@ -64,7 +80,7 @@ start() {
stop() {
echo -n $"Stopping $PROGNAME" "$SHORTNAME"
start-stop-daemon --stop --quiet --oknodo --pidfile "$PIDFILE"
jsvc -pidfile "$PIDFILE" -stop $CLASS
log_end_msg $?
rm -f "$PIDFILE"
}

View File

@ -1,37 +0,0 @@
#!/bin/bash
# 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
# 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.
SYSTEMJARS="@SYSTEMJARS@"
SCP=$(build-classpath $SYSTEMJARS) ; if [ $? != 0 ] ; then SCP="@SYSTEMCLASSPATH@" ; fi
DCP="@DEPSCLASSPATH@"
ACP="@USAGECLASSPATH@"
export CLASSPATH=$SCP:$DCP:$ACP:@USAGESYSCONFDIR@
for jarfile in "@PREMIUMJAVADIR@"/* ; do
if [ ! -e "$jarfile" ] ; then continue ; fi
CLASSPATH=$jarfile:$CLASSPATH
done
for plugin in "@PLUGINJAVADIR@"/* ; do
if [ ! -e "$plugin" ] ; then continue ; fi
CLASSPATH=$plugin:$CLASSPATH
done
export CLASSPATH
set -e
echo Current directory is "$PWD"
echo CLASSPATH to run the usage server: "$CLASSPATH"
exec java -cp "$CLASSPATH" -Dpid=$$ -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=@USAGELOGDIR@ "$@" com.cloud.usage.UsageServer

View File

@ -28,7 +28,16 @@ public class UsageServer {
* @param args
*/
public static void main(String[] args) {
// TODO: do we need to communicate with mgmt server?
UsageServer usage = new UsageServer();
usage.init(args);
usage.start();
}
public void init(String[] args) {
}
public void start() {
final ComponentLocator _locator = ComponentLocator.getLocator(UsageServer.Name, "usage-components.xml", "log4j-cloud_usage");
UsageManager mgr = _locator.getManager(UsageManager.class);
if (mgr != null) {
@ -37,4 +46,12 @@ public class UsageServer {
}
}
}
public void stop() {
}
public void destroy() {
}
}