http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java
new file mode 100644
index 0000000..0e77d84
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java
@@ -0,0 +1,127 @@
+/*
+ * 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 org.jclouds.cloudstack;
+
+import org.jclouds.cloudstack.features.GlobalAccountApi;
+import org.jclouds.cloudstack.features.GlobalAlertApi;
+import org.jclouds.cloudstack.features.GlobalCapacityApi;
+import org.jclouds.cloudstack.features.GlobalConfigurationApi;
+import org.jclouds.cloudstack.features.GlobalDomainApi;
+import org.jclouds.cloudstack.features.GlobalHostApi;
+import org.jclouds.cloudstack.features.GlobalOfferingApi;
+import org.jclouds.cloudstack.features.GlobalPodApi;
+import org.jclouds.cloudstack.features.GlobalStoragePoolApi;
+import org.jclouds.cloudstack.features.GlobalUsageApi;
+import org.jclouds.cloudstack.features.GlobalUserApi;
+import org.jclouds.cloudstack.features.GlobalVlanApi;
+import org.jclouds.cloudstack.features.GlobalZoneApi;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * Provides synchronous access to CloudStack.
+ * <p/>
+ * 
+ * @see <a href=
+ *      
"http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html";
+ *      />
+ */
+public interface CloudStackGlobalApi extends CloudStackDomainApi {
+
+   /**
+    * Provides synchronous access to Accounts
+    */
+   @Delegate
+   @Override
+   GlobalAccountApi getAccountApi();
+
+   /**
+    * Provides synchronous access to Users
+    */
+   @Delegate
+   @Override
+   GlobalUserApi getUserClient();
+
+   /**
+    * Provides synchronous access to Alerts
+    */
+   @Delegate
+   GlobalAlertApi getAlertClient();
+
+   /**
+    * Provides synchronous access to Capacities
+    */
+   @Delegate
+   GlobalCapacityApi getCapacityClient();
+
+   /**
+    * Provides synchronous access to Offerings
+    */
+   @Delegate
+   @Override
+   GlobalOfferingApi getOfferingApi();
+
+   /**
+    * Provides synchronous access to Hosts
+    */
+   @Delegate
+   GlobalHostApi getHostClient();
+
+   /**
+    * Provides synchronous access to Storage Pools
+    */
+   @Delegate
+   GlobalStoragePoolApi getStoragePoolClient();
+
+   /**
+    * Provides synchronous access to Usage
+    */
+   @Delegate
+   GlobalUsageApi getUsageClient();
+
+   /**
+    * Provides synchronous access to Configuration
+    */
+   @Delegate
+   @Override
+   GlobalConfigurationApi getConfigurationApi();
+
+   /**
+    * Provides synchronous access to Domain
+    */
+   @Delegate
+   @Override
+   GlobalDomainApi getDomainClient();
+
+   /**
+    * Provides synchronous access to Zone
+    */
+   @Delegate
+   @Override
+   GlobalZoneApi getZoneApi();
+
+   /**
+    * Provides synchronous access to Pod
+    */
+   @Delegate
+   GlobalPodApi getPodClient();
+
+   /**
+    * Provides synchronous access to Vlan
+    */
+   @Delegate
+   GlobalVlanApi getVlanClient();
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java
new file mode 100644
index 0000000..b99e644
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java
@@ -0,0 +1,55 @@
+/*
+ * 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 org.jclouds.cloudstack.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.http.Uris.uriBuilder;
+import static org.jclouds.http.utils.Queries.queryParser;
+
+import java.net.URI;
+import java.util.Map.Entry;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+import com.google.common.collect.Multimap;
+
+@Singleton
+public class BindAccountSecurityGroupPairsToIndexedQueryParams implements 
Binder {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(input instanceof Multimap<?, ?>, "this binder is only 
valid for Multimaps!");
+      Multimap<String, String> pairs = (Multimap<String, String>) 
checkNotNull(input, "account group pairs");
+      checkArgument(!pairs.isEmpty(), "you must specify at least one account, 
group pair");
+
+      Multimap<String, String> existingParams = 
queryParser().apply(request.getEndpoint().getQuery());
+      Builder<String, String> map = ImmutableMultimap.<String, String> 
builder().putAll(existingParams);
+      int i = 0;
+      for (Entry<String, String> entry : pairs.entries())
+         map.put(String.format("usersecuritygrouplist[%d].account", i), 
entry.getKey()).put(
+               String.format("usersecuritygrouplist[%d].group", i++), 
entry.getValue());
+      URI endpoint = 
uriBuilder(request.getEndpoint()).query(map.build()).build();
+      return (R) request.toBuilder().endpoint(endpoint).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java
new file mode 100644
index 0000000..28adf91
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.jclouds.cloudstack.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+
+@Singleton
+public class BindCIDRsToCommaDelimitedQueryParam implements Binder {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(input instanceof Iterable<?>, "this binder is only valid 
for Iterables!");
+      Iterable<String> cidrs = (Iterable<String>) checkNotNull(input, "cidr 
list");
+      checkArgument(!Iterables.isEmpty(cidrs), "you must specify at least one 
cidr range");
+      return (R) request.toBuilder().replaceQueryParam("cidrlist", 
Joiner.on(',').join(cidrs)).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java
new file mode 100644
index 0000000..f4b3813
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.jclouds.cloudstack.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+
+@Singleton
+public class BindIdListToCommaDelimitedQueryParam implements Binder {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(input instanceof Iterable<?>, "this binder is only valid 
for Iterables!");
+      Iterable<Long> numbers = (Iterable<Long>) checkNotNull(input, "list of 
Longs");
+      checkArgument(!Iterables.isEmpty(numbers), "you must specify at least 
one element");
+      return (R) request.toBuilder().replaceQueryParam("ids", 
Joiner.on(',').join(numbers)).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java
new file mode 100644
index 0000000..d80f4ba
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java
@@ -0,0 +1,43 @@
+/*
+ * 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 org.jclouds.cloudstack.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.SnapshotPolicySchedule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+
+@Singleton
+public class BindSnapshotPolicyScheduleToQueryParam implements Binder {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(input instanceof SnapshotPolicySchedule, "this binder is 
only valid for SnapshotPolicySchedule");
+      SnapshotPolicySchedule schedule = 
SnapshotPolicySchedule.class.cast(input);
+      Builder<String, String> builder = ImmutableMultimap.<String, String> 
builder();
+      builder.put("intervaltype", schedule.getInterval().toString());
+      builder.put("schedule", schedule.getTime().toString());
+      return (R) 
request.toBuilder().replaceQueryParams(builder.build()).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java
new file mode 100644
index 0000000..e61990c
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.cloudstack.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import org.jclouds.cloudstack.domain.TemplateMetadata;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+
+public class BindTemplateMetadataToQueryParams implements Binder {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(input instanceof TemplateMetadata, "this binder is only 
valid for TemplateMetadata");
+      TemplateMetadata metadata = (TemplateMetadata) input;
+      Builder<String, String> builder = ImmutableMultimap.<String, 
String>builder();
+      builder.put("name", metadata.getName());
+      builder.put("ostypeid", metadata.getOsTypeId());
+      builder.put("displaytext", metadata.getDisplayText());
+      if (metadata.getSnapshotId() != null) {
+             builder.put("snapshotid", metadata.getSnapshotId());
+      }
+      if (metadata.getVolumeId() != null) {
+             builder.put("volumeid", metadata.getVolumeId());
+      }
+      if (metadata.getVirtualMachineId() != null) {
+             builder.put("virtualmachineid", metadata.getVirtualMachineId());
+      }
+      if (metadata.isPasswordEnabled() != null) {
+             builder.put("passwordenabled", 
metadata.isPasswordEnabled().toString());
+      }
+      return (R) 
request.toBuilder().replaceQueryParams(builder.build()).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java
new file mode 100644
index 0000000..847fea5
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.jclouds.cloudstack.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import org.jclouds.cloudstack.domain.ResourceLimit;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+
+/**
+ * 
+ * @see <a href=
+ *      
"http://download.cloud.com/releases/2.2.0/api_2.2.12/domain_admin/updateResourceLimit.html";
+ *      />
+ */
+public class ResourceLimitToQueryParams implements Binder {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(input instanceof ResourceLimit, "this binder is only valid 
for ResourceLimit");
+      ResourceLimit limit = (ResourceLimit) input;
+      Builder<String, String> builder = ImmutableMultimap.<String, String> 
builder();
+      builder.put("resourcetype", limit.getResourceType().getCode() + "");
+      builder.put("account", limit.getAccount());
+      builder.put("domainid", limit.getDomainId());
+      builder.put("max", limit.getMax() + "");
+      return (R) 
request.toBuilder().replaceQueryParams(builder.build()).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java
new file mode 100644
index 0000000..1109cbb
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java
@@ -0,0 +1,180 @@
+/*
+ * 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 org.jclouds.cloudstack.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static 
org.jclouds.cloudstack.predicates.SshKeyPairPredicates.nameMatches;
+import static 
org.jclouds.cloudstack.predicates.ZonePredicates.supportsSecurityGroups;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.callables.RunScriptOnNode;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.internal.BaseComputeService;
+import org.jclouds.compute.internal.PersistNodeCredentials;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
+import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
+import org.jclouds.compute.strategy.DestroyNodeStrategy;
+import org.jclouds.compute.strategy.GetImageStrategy;
+import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
+import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.RebootNodeStrategy;
+import org.jclouds.compute.strategy.ResumeNodeStrategy;
+import org.jclouds.compute.strategy.SuspendNodeStrategy;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
+import org.jclouds.cloudstack.domain.SecurityGroup;
+import org.jclouds.cloudstack.domain.SshKeyPair;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.domain.ZoneAndName;
+import org.jclouds.cloudstack.predicates.SecurityGroupPredicates;
+import org.jclouds.scriptbuilder.functions.InitAdminAccess;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+@Singleton
+public class CloudStackComputeService extends BaseComputeService {
+   protected final CloudStackApi client;
+   protected final LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap;
+   protected final LoadingCache<String, SshKeyPair> keyPairCache;
+   protected final Function<Set<? extends NodeMetadata>, Multimap<String, 
String>> orphanedGroupsByZoneId;
+   protected final GroupNamingConvention.Factory namingConvention;
+   protected final Supplier<LoadingCache<String, Zone>> zoneIdToZone;
+
+   @Inject
+   protected CloudStackComputeService(ComputeServiceContext context, 
Map<String, Credentials> credentialStore,
+            @Memoized Supplier<Set<? extends Image>> images, @Memoized 
Supplier<Set<? extends Hardware>> sizes,
+            @Memoized Supplier<Set<? extends Location>> locations, 
ListNodesStrategy listNodesStrategy,
+            GetImageStrategy getImageStrategy, GetNodeMetadataStrategy 
getNodeMetadataStrategy,
+            CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, 
RebootNodeStrategy rebootNodeStrategy,
+            DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy 
startNodeStrategy,
+            SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> 
templateBuilderProvider,
+            @Named("DEFAULT") Provider<TemplateOptions> 
templateOptionsProvider,
+            @Named(TIMEOUT_NODE_RUNNING) 
Predicate<AtomicReference<NodeMetadata>> nodeRunning,
+            @Named(TIMEOUT_NODE_TERMINATED) 
Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
+            @Named(TIMEOUT_NODE_SUSPENDED) 
Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
+            InitializeRunScriptOnNodeOrPlaceInBadMap.Factory 
initScriptRunnerFactory,
+            RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess 
initAdminAccess,
+            PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
+            @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService 
userExecutor, CloudStackApi client,
+            LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap,
+            LoadingCache<String, SshKeyPair> keyPairCache,
+            Function<Set<? extends NodeMetadata>, Multimap<String, String>> 
orphanedGroupsByZoneId,
+            GroupNamingConvention.Factory namingConvention,
+            Supplier<LoadingCache<String, Zone>> zoneIdToZone,
+            Optional<ImageExtension> imageExtension,
+            Optional<SecurityGroupExtension> securityGroupExtension) {
+      super(context, credentialStore, images, sizes, locations, 
listNodesStrategy, getImageStrategy,
+               getNodeMetadataStrategy, runNodesAndAddToSetStrategy, 
rebootNodeStrategy, destroyNodeStrategy,
+               startNodeStrategy, stopNodeStrategy, templateBuilderProvider, 
templateOptionsProvider, nodeRunning,
+               nodeTerminated, nodeSuspended, initScriptRunnerFactory, 
initAdminAccess, runScriptOnNodeFactory,
+               persistNodeCredentials, timeouts, userExecutor, imageExtension, 
securityGroupExtension);
+      this.zoneIdToZone = checkNotNull(zoneIdToZone, "zoneIdToZone");
+      this.client = checkNotNull(client, "client");
+      this.securityGroupMap = checkNotNull(securityGroupMap, 
"securityGroupMap");
+      this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
+      this.orphanedGroupsByZoneId = checkNotNull(orphanedGroupsByZoneId, 
"orphanedGroupsByZoneId");
+      this.namingConvention = checkNotNull(namingConvention, 
"namingConvention");
+   }
+
+   @Override
+   protected void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends 
NodeMetadata> deadNodes) {
+      Multimap<String, String> zoneToZoneAndGroupNames = 
orphanedGroupsByZoneId.apply(deadNodes);
+      for (String zoneId : zoneToZoneAndGroupNames.keySet()) {
+         
cleanOrphanedGroupsInZone(ImmutableSet.copyOf(zoneToZoneAndGroupNames.get(zoneId)),
 zoneId);
+      }
+   }
+
+   protected void cleanOrphanedGroupsInZone(Set<String> groups, String zoneId) 
{
+      cleanupOrphanedSecurityGroupsInZone(groups, zoneId);
+      cleanupOrphanedKeyPairsInZone(groups, zoneId);
+   }
+
+   private void cleanupOrphanedSecurityGroupsInZone(Set<String> groups, String 
zoneId) {
+      Zone zone = zoneIdToZone.get().getUnchecked(zoneId);
+
+      if (supportsSecurityGroups().apply(zone)) {
+         for (String group : groups) {
+            for (SecurityGroup securityGroup : 
Iterables.filter(client.getSecurityGroupApi().listSecurityGroups(),
+                     
SecurityGroupPredicates.nameMatches(namingConvention.create().containsGroup(group))))
 {
+               ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, 
securityGroup.getName());
+               logger.debug(">> deleting securityGroup(%s)", zoneAndName);
+               
client.getSecurityGroupApi().deleteSecurityGroup(securityGroup.getId());
+               // TODO: test this clear happens
+               securityGroupMap.invalidate(zoneAndName);
+               logger.debug("<< deleted securityGroup(%s)", zoneAndName);
+            }
+         }
+      }
+   }
+
+   private void cleanupOrphanedKeyPairsInZone(Set<String> groups, String 
zoneId) {
+      for (String group : groups) {
+         for (SshKeyPair pair : 
Iterables.filter(client.getSSHKeyPairApi().listSSHKeyPairs(),
+                                                 
nameMatches(namingConvention.create().containsGroup(group)))) {
+            logger.debug(">> deleting keypair(%s)", pair.getName());
+            client.getSSHKeyPairApi().deleteSSHKeyPair(pair.getName());
+            // TODO: test this clear happens
+            keyPairCache.invalidate(pair.getName());
+            logger.debug("<< deleted keypair(%s)", pair.getName());
+         }
+         
keyPairCache.invalidate(namingConvention.create().sharedNameForGroup(group));
+      }
+   }
+
+   /**
+    * returns template options, as {@link CloudStackTemplateOptions}.
+    */
+   @Override
+   public CloudStackTemplateOptions templateOptions() {
+      return CloudStackTemplateOptions.class.cast(super.templateOptions());
+   }
+   
+   
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java
new file mode 100644
index 0000000..b2c02ad
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java
@@ -0,0 +1,291 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.config;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static 
org.jclouds.cloudstack.config.CloudStackProperties.AUTO_GENERATE_KEYPAIRS;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.compute.extensions.CloudStackImageExtension;
+import 
org.jclouds.cloudstack.compute.extensions.CloudStackSecurityGroupExtension;
+import 
org.jclouds.cloudstack.compute.functions.CloudStackSecurityGroupToSecurityGroup;
+import org.jclouds.cloudstack.compute.functions.IngressRuleToIpPermission;
+import org.jclouds.cloudstack.compute.functions.OrphanedGroupsByZoneId;
+import org.jclouds.cloudstack.compute.functions.ServiceOfferingToHardware;
+import org.jclouds.cloudstack.compute.functions.TemplateToImage;
+import org.jclouds.cloudstack.compute.functions.TemplateToOperatingSystem;
+import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata;
+import org.jclouds.cloudstack.compute.functions.ZoneToLocation;
+import org.jclouds.cloudstack.compute.loaders.CreateUniqueKeyPair;
+import org.jclouds.cloudstack.compute.loaders.FindSecurityGroupOrCreate;
+import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
+import org.jclouds.cloudstack.compute.strategy.AdvancedNetworkOptionsConverter;
+import org.jclouds.cloudstack.compute.strategy.BasicNetworkOptionsConverter;
+import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
+import org.jclouds.cloudstack.compute.strategy.OptionsConverter;
+import org.jclouds.cloudstack.domain.FirewallRule;
+import org.jclouds.cloudstack.domain.IPForwardingRule;
+import org.jclouds.cloudstack.domain.IngressRule;
+import org.jclouds.cloudstack.domain.Network;
+import org.jclouds.cloudstack.domain.NetworkType;
+import org.jclouds.cloudstack.domain.OSType;
+import org.jclouds.cloudstack.domain.Project;
+import org.jclouds.cloudstack.domain.SecurityGroup;
+import org.jclouds.cloudstack.domain.ServiceOffering;
+import org.jclouds.cloudstack.domain.SshKeyPair;
+import org.jclouds.cloudstack.domain.Template;
+import org.jclouds.cloudstack.domain.User;
+import org.jclouds.cloudstack.domain.VirtualMachine;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.domain.ZoneAndName;
+import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs;
+import org.jclouds.cloudstack.features.GuestOSApi;
+import org.jclouds.cloudstack.functions.CreateSecurityGroupIfNeeded;
+import org.jclouds.cloudstack.functions.GetFirewallRulesByVirtualMachine;
+import org.jclouds.cloudstack.functions.GetIPForwardingRulesByVirtualMachine;
+import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
+import org.jclouds.cloudstack.functions.ZoneIdToZone;
+import org.jclouds.cloudstack.predicates.JobComplete;
+import org.jclouds.cloudstack.suppliers.GetCurrentUser;
+import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser;
+import org.jclouds.cloudstack.suppliers.ProjectsForCurrentUser;
+import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.Location;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.rest.AuthorizationException;
+import 
org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
+
+import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+import com.google.inject.name.Names;
+
+public class CloudStackComputeServiceContextModule extends
+         ComputeServiceAdapterContextModule<VirtualMachine, ServiceOffering, 
Template, Zone> {
+
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, 
ServiceOffering, Template, Zone>>() {
+      }).to(CloudStackComputeServiceAdapter.class);
+      bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() {
+      }).to(VirtualMachineToNodeMetadata.class);
+      bind(new TypeLiteral<Function<SecurityGroup, 
org.jclouds.compute.domain.SecurityGroup>>() {
+      }).to(CloudStackSecurityGroupToSecurityGroup.class);
+      bind(new TypeLiteral<Function<IngressRule, IpPermission>>() {
+      }).to(IngressRuleToIpPermission.class);
+      bind(new TypeLiteral<Function<Template, 
org.jclouds.compute.domain.Image>>() {
+      }).to(TemplateToImage.class);
+      bind(new TypeLiteral<Function<ServiceOffering, 
org.jclouds.compute.domain.Hardware>>() {
+      }).to(ServiceOfferingToHardware.class);
+      bind(new TypeLiteral<Function<Zone, Location>>() {
+      }).to(ZoneToLocation.class);
+      bind(TemplateOptions.class).to(CloudStackTemplateOptions.class);
+      bind(new TypeLiteral<Function<Template, OperatingSystem>>() {
+      }).to(TemplateToOperatingSystem.class);
+      install(new 
FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class));
+      bind(new TypeLiteral<CacheLoader<String, Set<IPForwardingRule>>>() {
+      }).to(GetIPForwardingRulesByVirtualMachine.class);
+      bind(new TypeLiteral<CacheLoader<String, Set<FirewallRule>>>() {
+      }).to(GetFirewallRulesByVirtualMachine.class);
+      bind(new TypeLiteral<CacheLoader<String, Zone>>() {
+      }).to(ZoneIdToZone.class);
+      bind(new TypeLiteral<CacheLoader<String, SshKeyPair>>() {
+      }).to(CreateUniqueKeyPair.class);
+      bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {
+      }).to(ZoneIdToZoneSupplier.class);
+      bind(new TypeLiteral<Function<ZoneSecurityGroupNamePortsCidrs, 
SecurityGroup>>() {
+      }).to(CreateSecurityGroupIfNeeded.class);
+      bind(new TypeLiteral<CacheLoader<ZoneAndName, SecurityGroup>>() {
+      }).to(FindSecurityGroupOrCreate.class);
+      bind(new TypeLiteral<Function<Set<? extends NodeMetadata>,  
Multimap<String, String>>>() {
+      }).to(OrphanedGroupsByZoneId.class);
+
+      bind(new TypeLiteral<ImageExtension>() {
+      }).to(CloudStackImageExtension.class);
+
+      bind(new TypeLiteral<SecurityGroupExtension>() {
+      }).to(CloudStackSecurityGroupExtension.class);
+
+      // to have the compute service adapter override default locations
+      install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, 
ServiceOffering, Template, Zone>() {
+      });
+   }
+   
+
+   @Override
+   protected TemplateOptions provideTemplateOptions(Injector injector, 
TemplateOptions options) {
+      return options.as(CloudStackTemplateOptions.class)
+         .generateKeyPair(injector.getInstance(
+                  Key.get(boolean.class, 
Names.named(AUTO_GENERATE_KEYPAIRS))));
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<String, String>> 
listOSCategories(AtomicReference<AuthorizationException> authException, 
@Named(PROPERTY_SESSION_INTERVAL) long seconds,
+         final CloudStackApi client) {
+      return 
MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+            new Supplier<Map<String, String>>() {
+               @Override
+               public Map<String, String> get() {
+                  GuestOSApi guestOSClient = client.getGuestOSApi();
+                  return guestOSClient.listOSCategories();
+               }
+               @Override
+               public String toString() {
+                  return 
MoreObjects.toStringHelper(client.getGuestOSApi()).add("method", 
"listOSCategories").toString();
+               }
+            }, seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<String, OSType>> 
listOSTypes(AtomicReference<AuthorizationException> authException, 
@Named(PROPERTY_SESSION_INTERVAL) long seconds,
+         final CloudStackApi client) {
+      return 
MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+            new Supplier<Map<String, OSType>>() {
+               @Override
+               public Map<String, OSType> get() {
+                  GuestOSApi guestOSClient = client.getGuestOSApi();
+                  return Maps.uniqueIndex(guestOSClient.listOSTypes(), new 
Function<OSType, String>() {
+
+                     @Override
+                     public String apply(OSType arg0) {
+                        return arg0.getId();
+                     }
+                  });
+               }
+               @Override
+               public String toString() {
+                  return 
MoreObjects.toStringHelper(client.getGuestOSApi()).add("method", 
"listOSTypes").toString();
+               }
+            }, seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<String, Network>> 
listNetworks(AtomicReference<AuthorizationException> authException, 
@Named(PROPERTY_SESSION_INTERVAL) long seconds,
+         final NetworksForCurrentUser networksForCurrentUser) {
+      return 
MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
 networksForCurrentUser,
+               seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<String, Project>> 
listProjects(AtomicReference<AuthorizationException> authException, 
@Named(PROPERTY_SESSION_INTERVAL) long seconds,
+                                                      final 
ProjectsForCurrentUser projectsForCurrentUser) {
+      return 
MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
 projectsForCurrentUser,
+              seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<User> 
getCurrentUser(AtomicReference<AuthorizationException> authException, 
@Named(PROPERTY_SESSION_INTERVAL) long seconds,
+         final GetCurrentUser getCurrentUser) {
+      return 
MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
 getCurrentUser,
+               seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   protected Predicate<String> jobComplete(JobComplete jobComplete) {
+      return retry(jobComplete, 1200, 1, 5, SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   protected LoadingCache<String, SshKeyPair> keyPairMap(
+         CacheLoader<String, SshKeyPair> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+
+   @Provides
+   @Singleton
+   protected LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap(
+            CacheLoader<ZoneAndName, SecurityGroup> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+
+   @Provides
+   @Singleton
+   protected LoadingCache<String, Set<IPForwardingRule>> 
getIPForwardingRulesByVirtualMachine(
+      CacheLoader<String, Set<IPForwardingRule>> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+
+
+   @Provides
+   @Singleton
+   protected LoadingCache<String, Set<FirewallRule>> 
getFirewallRulesByVirtualMachine(
+      CacheLoader<String, Set<FirewallRule>> getFirewallRules) {
+      return CacheBuilder.newBuilder().build(getFirewallRules);
+   }
+
+   @Provides
+   @Singleton
+   public Map<NetworkType, ? extends OptionsConverter> optionsConverters() {
+      return ImmutableMap.of(
+         NetworkType.ADVANCED, new AdvancedNetworkOptionsConverter(),
+         NetworkType.BASIC, new BasicNetworkOptionsConverter());
+   }
+
+   @Override
+   protected Optional<ImageExtension> provideImageExtension(Injector i) {
+      return Optional.of(i.getInstance(ImageExtension.class));
+   }
+
+   @Override
+   protected Optional<SecurityGroupExtension> 
provideSecurityGroupExtension(Injector i) {
+      return Optional.of(i.getInstance(SecurityGroupExtension.class));
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java
new file mode 100644
index 0000000..2009e6d
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java
@@ -0,0 +1,160 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.extensions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.find;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
+
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.Template;
+import org.jclouds.cloudstack.domain.TemplateMetadata;
+import org.jclouds.cloudstack.domain.VirtualMachine;
+import org.jclouds.cloudstack.domain.Volume;
+import org.jclouds.cloudstack.options.CreateTemplateOptions;
+import org.jclouds.cloudstack.options.ListVolumesOptions;
+import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.CloneImageTemplate;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.ImageTemplate;
+import org.jclouds.compute.domain.ImageTemplateBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Atomics;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+
+/**
+ * CloudStack implementation of {@link ImageExtension}
+ */
+@Singleton
+public class CloudStackImageExtension implements ImageExtension {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final CloudStackApi client;
+   private final ListeningExecutorService userExecutor;
+   private final Supplier<Set<? extends Location>> locations;
+   private final Predicate<AtomicReference<Image>> imageAvailablePredicate;
+   private final BlockUntilJobCompletesAndReturnResult 
blockUntilJobCompletesAndReturnResult;
+   private final Predicate<String> jobComplete;
+
+   @Inject
+   public CloudStackImageExtension(CloudStackApi client,
+                                   @Named(Constants.PROPERTY_USER_THREADS) 
ListeningExecutorService userExecutor,
+                                   @Memoized Supplier<Set<? extends Location>> 
locations,
+                                   @Named(TIMEOUT_IMAGE_AVAILABLE) 
Predicate<AtomicReference<Image>> imageAvailablePredicate,
+                                   BlockUntilJobCompletesAndReturnResult 
blockUntilJobCompletesAndReturnResult,
+                                   Predicate<String> jobComplete) {
+      this.client = checkNotNull(client, "client");
+      this.userExecutor = checkNotNull(userExecutor, "userExecutor");
+      this.locations = checkNotNull(locations, "locations");
+      this.imageAvailablePredicate = checkNotNull(imageAvailablePredicate, 
"imageAvailablePredicate");
+      this.blockUntilJobCompletesAndReturnResult = 
checkNotNull(blockUntilJobCompletesAndReturnResult,
+                                                                
"blockUntilJobCompletesAndReturnResult");
+      this.jobComplete = checkNotNull(jobComplete, "jobComplete");
+   }
+
+   @Override
+   public ImageTemplate buildImageTemplateFromNode(String name, String id) {
+      VirtualMachine vm = client.getVirtualMachineApi().getVirtualMachine(id);
+      if (vm == null)
+         throw new NoSuchElementException("Cannot find vm with id: " + id);
+      CloneImageTemplate template = new 
ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name).build();
+      return template;
+   }
+
+   @Override
+   public ListenableFuture<Image> createImage(ImageTemplate template) {
+      checkState(template instanceof CloneImageTemplate,
+               " cloudstack only currently supports creating images through 
cloning.");
+      CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
+
+      VirtualMachine vm = 
client.getVirtualMachineApi().getVirtualMachine(cloneTemplate.getSourceNodeId());
+      String stopJob = 
client.getVirtualMachineApi().stopVirtualMachine(vm.getId());
+      jobComplete.apply(stopJob);
+
+      Set<Volume> volumes = 
client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.virtualMachineId(vm.getId()));
+      Volume volume = Iterables.getOnlyElement(volumes);
+      
+      CreateTemplateOptions options = 
CreateTemplateOptions.Builder.volumeId(volume.getId());
+      AsyncCreateResponse templateJob = 
client.getTemplateApi().createTemplate(TemplateMetadata.builder()
+                                                                               
   .name(cloneTemplate.getName())
+                                                                               
   .osTypeId(vm.getGuestOSId())
+                                                                               
   .displayText(cloneTemplate.getName())
+                                                                               
   .build(), options);
+      Template newTemplate = 
blockUntilJobCompletesAndReturnResult.<Template>apply(templateJob);
+
+      logger.info(">> Registered new template %s, waiting for it to become 
available.", newTemplate.getId());
+
+      final AtomicReference<Image> image = Atomics.newReference(new 
ImageBuilder()
+                                                                
.location(find(locations.get(), idEquals(vm.getZoneId())))
+                                                                
.id(newTemplate.getId())
+                                                                
.providerId(newTemplate.getId())
+                                                                
.description(cloneTemplate.getName())
+                                                                
.operatingSystem(OperatingSystem.builder().description(cloneTemplate.getName()).build())
+                                                                
.status(Image.Status.PENDING).build());
+
+      return userExecutor.submit(new Callable<Image>() {
+         @Override
+         public Image call() throws Exception {
+            if (imageAvailablePredicate.apply(image))
+               return image.get();
+            // TODO: get rid of the expectation that the image will be 
available, as it is very brittle
+            throw new UncheckedTimeoutException("Image was not created within 
the time limit: " + image.get());
+         }
+      });
+   }
+
+   @Override
+   public boolean deleteImage(String id) {
+      try {
+         AsyncCreateResponse deleteJob = 
client.getTemplateApi().deleteTemplate(id);
+         jobComplete.apply(deleteJob.getJobId());
+         return true;
+      } catch (Exception e) {
+         return false;
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java
new file mode 100644
index 0000000..70f7728
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java
@@ -0,0 +1,282 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.extensions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.notNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static 
org.jclouds.cloudstack.predicates.SecurityGroupPredicates.ruleCidrMatches;
+import static 
org.jclouds.cloudstack.predicates.SecurityGroupPredicates.ruleGroupMatches;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.IngressRule;
+import org.jclouds.cloudstack.domain.ZoneAndName;
+import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs;
+import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
+import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.domain.Location;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+
+/**
+ * An extension to compute service to allow for the manipulation of {@link 
org.jclouds.compute.domain.SecurityGroup}s. Implementation
+ * is optional by providers.
+ */
+public class CloudStackSecurityGroupExtension implements 
SecurityGroupExtension {
+   protected final CloudStackApi api;
+   protected final Function<org.jclouds.cloudstack.domain.SecurityGroup, 
SecurityGroup> groupConverter;
+   protected final LoadingCache<ZoneAndName, 
org.jclouds.cloudstack.domain.SecurityGroup> groupCreator;
+   protected final GroupNamingConvention.Factory namingConvention;
+   protected final Supplier<Set<? extends Location>> locations;
+   protected final BlockUntilJobCompletesAndReturnResult 
blockUntilJobCompletesAndReturnResult;
+   protected final Predicate<String> jobComplete;
+
+   @Inject
+   public CloudStackSecurityGroupExtension(CloudStackApi api,
+                                           
Function<org.jclouds.cloudstack.domain.SecurityGroup, SecurityGroup> 
groupConverter,
+                                           LoadingCache<ZoneAndName, 
org.jclouds.cloudstack.domain.SecurityGroup> groupCreator,
+                                           GroupNamingConvention.Factory 
namingConvention,
+                                           @Memoized Supplier<Set<? extends 
Location>> locations,
+                                           
BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
+                                           Predicate<String> jobComplete) {
+      this.api = checkNotNull(api, "api");
+      this.groupConverter = checkNotNull(groupConverter, "groupConverter");
+      this.groupCreator = checkNotNull(groupCreator, "groupCreator");
+      this.namingConvention = checkNotNull(namingConvention, 
"namingConvention");
+      this.locations = checkNotNull(locations, "locations");
+      this.blockUntilJobCompletesAndReturnResult = 
checkNotNull(blockUntilJobCompletesAndReturnResult,
+              "blockUntilJobCompletesAndReturnResult");
+      this.jobComplete = checkNotNull(jobComplete, "jobComplete");
+   }
+
+   @Override
+   public Set<SecurityGroup> listSecurityGroups() {
+      Iterable<? extends org.jclouds.cloudstack.domain.SecurityGroup> 
rawGroups =
+              api.getSecurityGroupApi().listSecurityGroups();
+      Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
+              groupConverter);
+      return ImmutableSet.copyOf(groups);
+   }
+
+   /**
+    * Note that for the time being, security groups are not scoped by location 
in
+    * CloudStack, so this will simply return listSecurityGroups().
+    *
+    * @param location
+    * @return security groups
+    */
+   @Override
+   public Set<SecurityGroup> listSecurityGroupsInLocation(final Location 
location) {
+      return listSecurityGroups();
+   }
+
+   @Override
+   public Set<SecurityGroup> listSecurityGroupsForNode(String id) {
+      checkNotNull(id, "id");
+
+      Iterable<? extends org.jclouds.cloudstack.domain.SecurityGroup> 
rawGroups =
+              
api.getSecurityGroupApi().listSecurityGroups(ListSecurityGroupsOptions.Builder
+                      .virtualMachineId(id));
+
+      Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
+              groupConverter);
+      return ImmutableSet.copyOf(groups);
+   }
+
+   @Override
+   public SecurityGroup getSecurityGroupById(String id) {
+      checkNotNull(id, "id");
+
+      org.jclouds.cloudstack.domain.SecurityGroup rawGroup
+              = api.getSecurityGroupApi().getSecurityGroup(id);
+
+      if (rawGroup == null) {
+         return null;
+      }
+
+      return groupConverter.apply(rawGroup);
+   }
+
+   @Override
+   public SecurityGroup createSecurityGroup(String name, Location location) {
+      checkNotNull(name, "name");
+      checkNotNull(location, "location");
+
+      String markerGroup = namingConvention.create().sharedNameForGroup(name);
+
+      ZoneSecurityGroupNamePortsCidrs zoneAndName = 
ZoneSecurityGroupNamePortsCidrs.builder()
+              .zone(location.getId())
+              .name(markerGroup)
+              .build();
+
+      return groupConverter.apply(groupCreator.getUnchecked(zoneAndName));
+   }
+
+   @Override
+   public boolean removeSecurityGroup(String id) {
+      checkNotNull(id, "id");
+
+      org.jclouds.cloudstack.domain.SecurityGroup group =
+              api.getSecurityGroupApi().getSecurityGroup(id);
+
+      if (group == null) {
+         return false;
+      }
+
+      for (IngressRule rule : group.getIngressRules()) {
+         
jobComplete.apply(api.getSecurityGroupApi().revokeIngressRule(rule.getId()));
+      }
+
+      api.getSecurityGroupApi().deleteSecurityGroup(id);
+
+      // TODO find something better here maybe - hard to map zones to groups
+      for (Location location : locations.get()) {
+         groupCreator.invalidate(ZoneSecurityGroupNamePortsCidrs.builder()
+                 .zone(location.getId())
+                 .name(group.getName())
+                 .build());
+      }
+
+      return true;
+   }
+
+   @Override
+   public SecurityGroup addIpPermission(IpPermission ipPermission, 
SecurityGroup group) {
+      checkNotNull(group, "group");
+      checkNotNull(ipPermission, "ipPermission");
+      String id = checkNotNull(group.getId(), "group.getId()");
+
+      if (!ipPermission.getCidrBlocks().isEmpty()) {
+         
jobComplete.apply(api.getSecurityGroupApi().authorizeIngressPortsToCIDRs(id,
+                 ipPermission.getIpProtocol().toString().toUpperCase(),
+                 ipPermission.getFromPort(),
+                 ipPermission.getToPort(),
+                 ipPermission.getCidrBlocks()));
+      }
+
+      if (!ipPermission.getTenantIdGroupNamePairs().isEmpty()) {
+         
jobComplete.apply(api.getSecurityGroupApi().authorizeIngressPortsToSecurityGroups(id,
+                 ipPermission.getIpProtocol().toString().toUpperCase(),
+                 ipPermission.getFromPort(),
+                 ipPermission.getToPort(),
+                 ipPermission.getTenantIdGroupNamePairs()));
+      }
+
+      return getSecurityGroupById(id);
+   }
+
+   @Override
+   public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, 
int endPort,
+                                        Multimap<String, String> 
tenantIdGroupNamePairs,
+                                        Iterable<String> ipRanges,
+                                        Iterable<String> groupIds, 
SecurityGroup group) {
+      IpPermission.Builder permBuilder = IpPermission.builder();
+      permBuilder.ipProtocol(protocol);
+      permBuilder.fromPort(startPort);
+      permBuilder.toPort(endPort);
+      permBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs);
+      permBuilder.cidrBlocks(ipRanges);
+      permBuilder.groupIds(groupIds);
+
+      return addIpPermission(permBuilder.build(), group);
+   }
+
+   @Override
+   public SecurityGroup removeIpPermission(IpPermission ipPermission, 
SecurityGroup group) {
+      checkNotNull(group, "group");
+      checkNotNull(ipPermission, "ipPermission");
+      String id = checkNotNull(group.getId(), "group.getId()");
+
+      org.jclouds.cloudstack.domain.SecurityGroup rawGroup = 
api.getSecurityGroupApi()
+              .getSecurityGroup(id);
+
+      if (!ipPermission.getCidrBlocks().isEmpty()) {
+         for (IngressRule rule : filter(rawGroup.getIngressRules(),
+                 ruleCidrMatches(ipPermission.getIpProtocol().toString(),
+                         ipPermission.getFromPort(),
+                         ipPermission.getToPort(),
+                         ipPermission.getCidrBlocks()))) {
+             
jobComplete.apply(api.getSecurityGroupApi().revokeIngressRule(rule.getId()));
+         }
+      }
+
+      if (!ipPermission.getTenantIdGroupNamePairs().isEmpty()) {
+         for (IngressRule rule : filter(rawGroup.getIngressRules(),
+                 ruleGroupMatches(ipPermission.getIpProtocol().toString(),
+                         ipPermission.getFromPort(),
+                         ipPermission.getToPort(),
+                         ipPermission.getTenantIdGroupNamePairs()))) {
+             
jobComplete.apply(api.getSecurityGroupApi().revokeIngressRule(rule.getId()));
+         }
+      }
+
+      return getSecurityGroupById(id);
+   }
+
+   @Override
+   public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, 
int endPort,
+                                           Multimap<String, String> 
tenantIdGroupNamePairs,
+                                           Iterable<String> ipRanges,
+                                           Iterable<String> groupIds, 
SecurityGroup group) {
+      IpPermission.Builder permBuilder = IpPermission.builder();
+      permBuilder.ipProtocol(protocol);
+      permBuilder.fromPort(startPort);
+      permBuilder.toPort(endPort);
+      permBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs);
+      permBuilder.cidrBlocks(ipRanges);
+      permBuilder.groupIds(groupIds);
+
+      return removeIpPermission(permBuilder.build(), group);
+   }
+
+   @Override
+   public boolean supportsTenantIdGroupNamePairs() {
+      return true;
+   }
+
+   @Override
+   public boolean supportsTenantIdGroupIdPairs() {
+      return false;
+   }
+
+   @Override
+   public boolean supportsGroupIds() {
+      return false;
+   }
+
+   @Override
+   public boolean supportsPortRangesForGroups() {
+      return false;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java
new file mode 100644
index 0000000..0d17317
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.functions;
+
+import static com.google.common.collect.Iterables.transform;
+
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.domain.SecurityGroupBuilder;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.cloudstack.domain.IngressRule;
+
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+
+
+/**
+ * A function for transforming a CloudStack-specific SecurityGroup into a 
generic
+ * SecurityGroup object.
+ */
+@Singleton
+public class CloudStackSecurityGroupToSecurityGroup implements 
Function<org.jclouds.cloudstack.domain.SecurityGroup, SecurityGroup> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   protected final Function<IngressRule, IpPermission> ruleToPermission;
+   
+   @Inject
+   public CloudStackSecurityGroupToSecurityGroup(Function<IngressRule, 
IpPermission> ruleToPermission) {
+      this.ruleToPermission = ruleToPermission;
+   }
+
+   @Override
+   public SecurityGroup apply(org.jclouds.cloudstack.domain.SecurityGroup 
group) {
+      SecurityGroupBuilder builder = new SecurityGroupBuilder();
+      
+      builder.id(group.getId());
+      builder.providerId(group.getId());
+      builder.name(group.getName());
+      builder.ownerId(group.getAccount());
+      builder.ipPermissions(transform(group.getIngressRules(), 
ruleToPermission));
+      
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java
new file mode 100644
index 0000000..fbcdc18
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.functions;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.cloudstack.domain.IngressRule;
+import org.jclouds.logging.Logger;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+
+import com.google.common.base.Function;
+
+
+/**
+ * A function for transforming a CloudStack-specific IngressRule into a generic
+ * IpPermission object.
+ */
+public class IngressRuleToIpPermission implements Function<IngressRule, 
IpPermission> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+   
+   public IngressRuleToIpPermission() {
+   }
+
+   @Override
+   public IpPermission apply(IngressRule rule) {
+      IpPermission.Builder builder = IpPermission.builder();
+      builder.ipProtocol(IpProtocol.fromValue(rule.getProtocol()));
+      builder.fromPort(rule.getStartPort());
+      builder.toPort(rule.getEndPort());
+      if (rule.getCIDR() != null) {
+         builder.cidrBlock(rule.getCIDR());
+      }
+      if (rule.getSecurityGroupName() != null
+              && rule.getAccount() != null) {
+         builder.tenantIdGroupNamePair(rule.getAccount(), 
rule.getSecurityGroupName());
+      }
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java
new file mode 100644
index 0000000..d7a187d
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java
@@ -0,0 +1,73 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Sets.filter;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.predicates.NodePredicates;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.cloudstack.compute.predicates.AllNodesInGroupTerminated;
+import org.jclouds.cloudstack.domain.ZoneAndName;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+public class OrphanedGroupsByZoneId implements Function<Set<? extends 
NodeMetadata>, Multimap<String, String>> {
+   private final Predicate<ZoneAndName> allNodesInGroupTerminated;
+
+   @Inject
+   protected OrphanedGroupsByZoneId(ComputeService computeService) {
+      this(new AllNodesInGroupTerminated(checkNotNull(computeService, 
"computeService")));
+   }
+
+   @VisibleForTesting
+   OrphanedGroupsByZoneId(Predicate<ZoneAndName> allNodesInGroupTerminated) {
+      this.allNodesInGroupTerminated = checkNotNull(allNodesInGroupTerminated, 
"allNodesInGroupTerminated");
+   }
+
+   public Multimap<String, String> apply(Set<? extends NodeMetadata> 
deadNodes) {
+      Iterable<? extends NodeMetadata> nodesWithGroup = filter(deadNodes, 
NodePredicates.hasGroup());
+      Set<ZoneAndName> zoneAndGroupNames = 
ImmutableSet.copyOf(filter(transform(nodesWithGroup,
+               new Function<NodeMetadata, ZoneAndName>() {
+
+                  @Override
+                  public ZoneAndName apply(NodeMetadata input) {
+                     String zoneId = input.getLocation().getScope() == 
LocationScope.HOST ? input.getLocation()
+                              .getParent().getId() : 
input.getLocation().getId();
+                     return ZoneAndName.fromZoneAndName(zoneId, 
input.getGroup());
+                  }
+
+               }), allNodesInGroupTerminated));
+      Multimap<String, String> zoneToZoneAndGroupNames = 
Multimaps.transformValues(Multimaps.index(zoneAndGroupNames,
+               ZoneAndName.ZONE_FUNCTION), ZoneAndName.NAME_FUNCTION);
+      return zoneToZoneAndGroupNames;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java
new file mode 100644
index 0000000..ab85c3a
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java
@@ -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 org.jclouds.cloudstack.compute.functions;
+
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.ServiceOffering;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Processor;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+
+@Singleton
+public class ServiceOfferingToHardware implements Function<ServiceOffering, 
Hardware> {
+
+   @Override
+   public Hardware apply(ServiceOffering offering) {
+      return new HardwareBuilder()
+            .ids(offering.getId() + "")
+            .name(offering.getName())
+            .tags(offering.getTags())
+            .processors(ImmutableList.of(new 
Processor(offering.getCpuNumber(), offering.getCpuSpeed())))
+            .ram(offering.getMemory())//
+            // TODO: hypervisor probably from zone?
+            // TODO .volumes()
+            // displayText
+            // created
+            // haSupport
+            // storageType
+            // TODO where's the location of this?
+            .build();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java
new file mode 100644
index 0000000..86ab66e
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.Template;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Image.Status;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.domain.Location;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
+
+@Singleton
+public class TemplateToImage implements Function<Template, Image> {
+   private final Supplier<Set<? extends Location>> locations;
+   private final Function<Template, OperatingSystem> templateToOperatingSystem;
+
+   @Inject
+   public TemplateToImage(@Memoized Supplier<Set<? extends Location>> 
locations,
+         Function<Template, OperatingSystem> templateToOperatingSystem) {
+      this.locations = checkNotNull(locations, "locations");
+      this.templateToOperatingSystem = checkNotNull(templateToOperatingSystem, 
"templateToOperatingSystem");
+   }
+
+   @Override
+   public Image apply(Template template) {
+      checkNotNull(template, "template");
+
+      OperatingSystem os = templateToOperatingSystem.apply(template);
+
+      ImageBuilder builder = new ImageBuilder().ids(template.getId() + 
"").name(template.getName())
+            .description(template.getDisplayText()).operatingSystem(os);
+
+      if (!template.isCrossZones())
+         
builder.location(FluentIterable.from(locations.get()).firstMatch(idEquals(template.getZoneId())).orNull());
+
+      //TODO: implement status mapping!!!
+      builder.status(Status.AVAILABLE);
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java
----------------------------------------------------------------------
diff --git 
a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java
 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java
new file mode 100644
index 0000000..9abb7da
--- /dev/null
+++ 
b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.jclouds.cloudstack.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.OSType;
+import org.jclouds.cloudstack.domain.Template;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.OperatingSystem.Builder;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+
+@Singleton
+public class TemplateToOperatingSystem implements Function<Template, 
OperatingSystem> {
+   // CentOS 5.2 (32-bit)
+   public static final Pattern DEFAULT_PATTERN = Pattern.compile(".* ([0-9.]+) 
?\\(.*");
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final Supplier<Map<String, OSType>> osTypes;
+   private final Supplier<Map<String, String>> osCategories;
+   private final Map<OsFamily, Map<String, String>> osVersionMap;
+
+   @Inject
+   public TemplateToOperatingSystem(@Memoized Supplier<Map<String, OSType>> 
osTypes,
+         @Memoized Supplier<Map<String, String>> osCategories, Map<OsFamily, 
Map<String, String>> osVersionMap) {
+      this.osTypes = checkNotNull(osTypes, "osTypes");
+      this.osCategories = checkNotNull(osCategories, "osCategories");
+      this.osVersionMap = checkNotNull(osVersionMap, "osVersionMap");
+   }
+
+   public OperatingSystem apply(Template from) {
+      Builder builder = 
OperatingSystem.builder().description(from.getOSType());
+
+      OSType type = osTypes.get().get(from.getOSTypeId());
+      if (type == null) {
+         logger.warn("Template refers to OS type ID %s but this does not 
exist. Template=%s Known OS types=%s", from.getOSTypeId(), from, osTypes.get());
+         return builder.build();
+      }
+      builder.description(type.getDescription());
+      builder.is64Bit(type.getDescription().indexOf("64-bit") != -1);
+      String osCategory = osCategories.get().get(type.getOSCategoryId());
+      if (osCategory == null) {
+         logger.warn("OS type refers to OS category ID %s but this does not 
exist. OS type=%s Known OS categories=%s", type.getOSCategoryId(), type, 
osCategories.get());
+         return builder.build();
+      }
+      builder.name(osCategory);
+      OsFamily family = OsFamily.fromValue(osCategory.toLowerCase());
+      builder.family(family);
+      Matcher matcher = DEFAULT_PATTERN.matcher(type.getDescription());
+      if (matcher.find()) {
+         
builder.version(ComputeServiceUtils.parseVersionOrReturnEmptyString(family, 
matcher.group(1), osVersionMap));
+      }
+      return builder.build();
+   }
+}

Reply via email to