You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by ni...@apache.org on 2014/03/18 03:52:12 UTC

[19/20] fixing https://issues.apache.org/jira/browse/STRATOS-520 - adding Openstack-nova module to dependencies

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
new file mode 100644
index 0000000..311d4ab
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
@@ -0,0 +1,286 @@
+/*
+ * 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.openstack.nova.v2_0.compute.config;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.openstack.nova.v2_0.config.NovaProperties.AUTO_ALLOCATE_FLOATING_IPS;
+import static org.jclouds.openstack.nova.v2_0.config.NovaProperties.AUTO_GENERATE_KEYPAIRS;
+import static org.jclouds.openstack.nova.v2_0.config.NovaProperties.TIMEOUT_SECURITYGROUP_PRESENT;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.functions.IdentityFunction;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.openstack.nova.v2_0.compute.NovaComputeService;
+import org.jclouds.openstack.nova.v2_0.compute.NovaComputeServiceAdapter;
+import org.jclouds.openstack.nova.v2_0.compute.extensions.NovaImageExtension;
+import org.jclouds.openstack.nova.v2_0.compute.extensions.NovaSecurityGroupExtension;
+import org.jclouds.openstack.nova.v2_0.compute.functions.CreateSecurityGroupIfNeeded;
+import org.jclouds.openstack.nova.v2_0.compute.functions.FlavorInZoneToHardware;
+import org.jclouds.openstack.nova.v2_0.compute.functions.ImageInZoneToImage;
+import org.jclouds.openstack.nova.v2_0.compute.functions.ImageToOperatingSystem;
+import org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupInZoneToSecurityGroup;
+import org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupToSecurityGroup;
+import org.jclouds.openstack.nova.v2_0.compute.functions.OrphanedGroupsByZoneId;
+import org.jclouds.openstack.nova.v2_0.compute.functions.SecurityGroupRuleToIpPermission;
+import org.jclouds.openstack.nova.v2_0.compute.functions.ServerInZoneToNodeMetadata;
+import org.jclouds.openstack.nova.v2_0.compute.loaders.CreateUniqueKeyPair;
+import org.jclouds.openstack.nova.v2_0.compute.loaders.FindSecurityGroupOrCreate;
+import org.jclouds.openstack.nova.v2_0.compute.loaders.LoadFloatingIpsForInstance;
+import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
+import org.jclouds.openstack.nova.v2_0.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
+import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
+import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
+import org.jclouds.openstack.nova.v2_0.domain.Server;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.FlavorInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ImageInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ServerInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
+import org.jclouds.openstack.nova.v2_0.predicates.FindSecurityGroupWithNameAndReturnTrue;
+
+import com.google.common.annotations.VisibleForTesting;
+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.base.Suppliers;
+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.name.Names;
+
+/**
+ * Module for building a compute service context for Nova
+ * 
+ * @author Matt Stephenson
+ */
+public class NovaComputeServiceContextModule extends
+         ComputeServiceAdapterContextModule<ServerInZone, FlavorInZone, ImageInZone, Location> {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<ComputeServiceAdapter<ServerInZone, FlavorInZone, ImageInZone, Location>>() {
+      }).to(NovaComputeServiceAdapter.class);
+     
+      bind(ComputeService.class).to(NovaComputeService.class);
+      
+      bind(new TypeLiteral<Function<ServerInZone, NodeMetadata>>() {
+      }).to(ServerInZoneToNodeMetadata.class);
+
+      bind(new TypeLiteral<Function<SecurityGroupRule, IpPermission>>() {
+      }).to(SecurityGroupRuleToIpPermission.class);
+
+      bind(new TypeLiteral<Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup>>() {
+      }).to(NovaSecurityGroupToSecurityGroup.class);
+
+      bind(new TypeLiteral<Function<SecurityGroupInZone, SecurityGroup>>() {
+      }).to(NovaSecurityGroupInZoneToSecurityGroup.class);
+
+      bind(new TypeLiteral<Function<Set<? extends NodeMetadata>,  Multimap<String, String>>>() {
+      }).to(OrphanedGroupsByZoneId.class);
+
+      bind(new TypeLiteral<Function<ImageInZone, Image>>() {
+      }).to(ImageInZoneToImage.class);
+      bind(new TypeLiteral<Function<org.jclouds.openstack.nova.v2_0.domain.Image, OperatingSystem>>() {
+      }).to(ImageToOperatingSystem.class);
+
+      bind(new TypeLiteral<Function<FlavorInZone, Hardware>>() {
+      }).to(FlavorInZoneToHardware.class);
+
+      // we aren't converting location from a provider-specific type
+      bind(new TypeLiteral<Function<Location, Location>>() {
+      }).to(Class.class.cast(IdentityFunction.class));
+
+      bind(TemplateOptions.class).to(NovaTemplateOptions.class);
+
+      bind(new TypeLiteral<CacheLoader<ZoneAndId, Iterable<? extends FloatingIP>>>() {
+      }).annotatedWith(Names.named("FLOATINGIP")).to(LoadFloatingIpsForInstance.class);
+
+      bind(new TypeLiteral<Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>>() {
+      }).to(CreateSecurityGroupIfNeeded.class);
+
+      bind(new TypeLiteral<CacheLoader<ZoneAndName, SecurityGroupInZone>>() {
+      }).to(FindSecurityGroupOrCreate.class);
+
+      bind(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
+               ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
+
+      bind(new TypeLiteral<CacheLoader<ZoneAndName, KeyPair>>() {
+      }).to(CreateUniqueKeyPair.class);
+      
+      bind(new TypeLiteral<ImageExtension>() {
+      }).to(NovaImageExtension.class);
+
+      bind(new TypeLiteral<SecurityGroupExtension>() {
+      }).to(NovaSecurityGroupExtension.class);
+   }
+
+   @Override
+   protected TemplateOptions provideTemplateOptions(Injector injector, TemplateOptions options) {
+      return options.as(NovaTemplateOptions.class)
+            .autoAssignFloatingIp(injector.getInstance(
+                  Key.get(boolean.class, Names.named(AUTO_ALLOCATE_FLOATING_IPS))))
+            .generateKeyPair(injector.getInstance(
+                  Key.get(boolean.class, Names.named(AUTO_GENERATE_KEYPAIRS))));
+   }
+
+   @Provides
+   @Singleton
+   @Named("FLOATINGIP")
+   protected LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> instanceToFloatingIps(
+            @Named("FLOATINGIP") CacheLoader<ZoneAndId, Iterable<? extends FloatingIP>> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+
+   @Provides
+   @Singleton
+   protected LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap(
+            CacheLoader<ZoneAndName, SecurityGroupInZone> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+   
+   @Override
+   protected Map<OsFamily, LoginCredentials> osFamilyToCredentials(Injector injector) {
+      return ImmutableMap.of(OsFamily.WINDOWS, LoginCredentials.builder().user("Administrator").build(),
+               OsFamily.UBUNTU, LoginCredentials.builder().user("ubuntu").build());
+   }
+
+   @Provides
+   @Singleton
+   @Named("SECURITYGROUP_PRESENT")
+   protected Predicate<AtomicReference<ZoneAndName>> securityGroupEventualConsistencyDelay(
+            FindSecurityGroupWithNameAndReturnTrue in,
+            @Named(TIMEOUT_SECURITYGROUP_PRESENT) long msDelay) {
+      return retry(in, msDelay, 100l, MILLISECONDS);
+   }
+
+   @Provides
+   @Singleton
+   protected LoadingCache<ZoneAndName, KeyPair> keyPairMap(
+         CacheLoader<ZoneAndName, KeyPair> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+
+   @Provides
+   @Singleton
+   protected Supplier<Map<String, Location>> createLocationIndexedById(
+            @Memoized Supplier<Set<? extends Location>> locations) {
+      return Suppliers.compose(new Function<Set<? extends Location>, Map<String, Location>>() {
+
+         @SuppressWarnings("unchecked")
+         @Override
+         public Map<String, Location> apply(Set<? extends Location> arg0) {
+            // TODO: find a nice way to get rid of this cast.
+            Iterable<Location> locations = (Iterable<Location>) arg0;
+            return Maps.uniqueIndex(locations, new Function<Location, String>() {
+
+               @Override
+               public String apply(Location arg0) {
+                  return arg0.getId();
+               }
+
+            });
+         }
+      }, locations);
+
+   }
+
+   @VisibleForTesting
+   public static final Map<Server.Status, NodeMetadata.Status> toPortableNodeStatus = ImmutableMap
+            .<Server.Status, NodeMetadata.Status> builder().put(Server.Status.ACTIVE, NodeMetadata.Status.RUNNING)//
+            .put(Server.Status.SUSPENDED, NodeMetadata.Status.SUSPENDED)//
+            .put(Server.Status.DELETED, NodeMetadata.Status.TERMINATED)//
+            .put(Server.Status.PAUSED, NodeMetadata.Status.SUSPENDED)//
+            .put(Server.Status.RESIZE, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.VERIFY_RESIZE, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.REVERT_RESIZE, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.BUILD, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.PASSWORD, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.REBUILD, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.ERROR, NodeMetadata.Status.ERROR)//
+            .put(Server.Status.REBOOT, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.HARD_REBOOT, NodeMetadata.Status.PENDING)//
+            .put(Server.Status.UNKNOWN, NodeMetadata.Status.UNRECOGNIZED)//
+            .put(Server.Status.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build();
+
+   @Singleton
+   @Provides
+   protected Map<Server.Status, NodeMetadata.Status> toPortableNodeStatus() {
+      return toPortableNodeStatus;
+   }
+   
+   @VisibleForTesting
+   public static final Map<org.jclouds.openstack.nova.v2_0.domain.Image.Status, Image.Status> toPortableImageStatus = ImmutableMap
+            .<org.jclouds.openstack.nova.v2_0.domain.Image.Status, Image.Status> builder()
+            .put(org.jclouds.openstack.nova.v2_0.domain.Image.Status.ACTIVE, Image.Status.AVAILABLE)
+            .put(org.jclouds.openstack.nova.v2_0.domain.Image.Status.SAVING, Image.Status.PENDING)
+            .put(org.jclouds.openstack.nova.v2_0.domain.Image.Status.DELETED, Image.Status.DELETED)
+            .put(org.jclouds.openstack.nova.v2_0.domain.Image.Status.ERROR, Image.Status.ERROR)
+            .put(org.jclouds.openstack.nova.v2_0.domain.Image.Status.UNKNOWN, Image.Status.UNRECOGNIZED)
+            .put(org.jclouds.openstack.nova.v2_0.domain.Image.Status.UNRECOGNIZED, Image.Status.UNRECOGNIZED).build();
+
+   @Singleton
+   @Provides
+   protected Map<org.jclouds.openstack.nova.v2_0.domain.Image.Status, Image.Status> toPortableImageStatus() {
+      return toPortableImageStatus;
+   }
+   
+   @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/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaImageExtension.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaImageExtension.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaImageExtension.java
new file mode 100644
index 0000000..f8fd4d9
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaImageExtension.java
@@ -0,0 +1,140 @@
+/*
+ * 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.openstack.nova.v2_0.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.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 org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.domain.Server;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+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;
+
+/**
+ * Nova implementation of {@link ImageExtension}
+ * 
+ * @author David Alves
+ *
+ */
+@Singleton
+public class NovaImageExtension implements ImageExtension {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final NovaApi novaApi;
+   private final ListeningExecutorService userExecutor;
+   private final Supplier<Set<? extends Location>> locations;
+   private final Predicate<AtomicReference<Image>> imageAvailablePredicate;
+
+   @Inject
+   public NovaImageExtension(NovaApi novaApi, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+         @Memoized Supplier<Set<? extends Location>> locations,
+         @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<AtomicReference<Image>> imageAvailablePredicate) {
+      this.novaApi = checkNotNull(novaApi, "novaApi");
+      this.userExecutor = checkNotNull(userExecutor, "userExecutor");
+      this.locations = checkNotNull(locations, "locations");
+      this.imageAvailablePredicate = checkNotNull(imageAvailablePredicate, "imageAvailablePredicate");
+   }
+
+   @Override
+   public ImageTemplate buildImageTemplateFromNode(String name, final String id) {
+      ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(id);
+      Server server = novaApi.getServerApiForZone(zoneAndId.getZone()).get(zoneAndId.getId());
+      if (server == null)
+         throw new NoSuchElementException("Cannot find server with id: " + zoneAndId);
+      CloneImageTemplate template = new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name).build();
+      return template;
+   }
+
+   @Override
+   public ListenableFuture<Image> createImage(ImageTemplate template) {
+      checkState(template instanceof CloneImageTemplate,
+               " openstack-nova only supports creating images through cloning.");
+      CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
+      ZoneAndId sourceImageZoneAndId = ZoneAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId());
+
+      String newImageId = novaApi.getServerApiForZone(sourceImageZoneAndId.getZone()).createImageFromServer(
+               cloneTemplate.getName(), sourceImageZoneAndId.getId());
+
+      final ZoneAndId targetImageZoneAndId = ZoneAndId.fromZoneAndId(sourceImageZoneAndId.getZone(), newImageId);
+
+      logger.info(">> Registered new Image %s, waiting for it to become available.", newImageId);
+      
+      final AtomicReference<Image> image = Atomics.newReference(new ImageBuilder()
+            .location(find(locations.get(), idEquals(targetImageZoneAndId.getZone())))
+            .id(targetImageZoneAndId.slashEncode())
+            .providerId(targetImageZoneAndId.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) {
+      ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(id);
+      try {
+         this.novaApi.getImageApiForZone(zoneAndId.getZone()).delete(zoneAndId.getId());
+      } catch (Exception e) {
+         return false;
+      }
+      return true;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
new file mode 100644
index 0000000..8b36fc9
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
@@ -0,0 +1,373 @@
+/*
+ * 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.openstack.nova.v2_0.compute.extensions;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.notNull;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.nameIn;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleCidr;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleEndPort;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleGroup;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleProtocol;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleStartPort;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.Constants;
+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.location.Zone;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.domain.Ingress;
+import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
+import org.jclouds.openstack.nova.v2_0.domain.ServerWithSecurityGroups;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
+import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupApi;
+import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsApi;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+ * An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s. Implementation
+ * is optional by providers.
+ *
+ * @author Andrew Bayer
+ */
+public class NovaSecurityGroupExtension implements SecurityGroupExtension {
+
+   protected final NovaApi api;
+   protected final ListeningExecutorService userExecutor;
+   protected final Supplier<Set<String>> zoneIds;
+   protected final Function<SecurityGroupInZone, SecurityGroup> groupConverter;
+   protected final LoadingCache<ZoneAndName, SecurityGroupInZone> groupCreator;
+   protected final GroupNamingConvention.Factory namingConvention;
+
+   @Inject
+   public NovaSecurityGroupExtension(NovaApi api,
+                                    @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+                                    @Zone Supplier<Set<String>> zoneIds,
+                                    Function<SecurityGroupInZone, SecurityGroup> groupConverter,
+                                    LoadingCache<ZoneAndName, SecurityGroupInZone> groupCreator,
+                                    GroupNamingConvention.Factory namingConvention) {
+
+      this.api = checkNotNull(api, "api");
+      this.userExecutor = checkNotNull(userExecutor, "userExecutor");
+      this.zoneIds = checkNotNull(zoneIds, "zoneIds");
+      this.groupConverter = checkNotNull(groupConverter, "groupConverter");
+      this.groupCreator = checkNotNull(groupCreator, "groupCreator");
+      this.namingConvention = checkNotNull(namingConvention, "namingConvention");
+   }
+
+   @Override
+   public Set<SecurityGroup> listSecurityGroups() {
+      Iterable<? extends SecurityGroupInZone> rawGroups = pollSecurityGroups();
+      Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
+              groupConverter);
+      return ImmutableSet.copyOf(groups);
+   }
+
+
+   @Override
+   public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) {
+      String zone = location.getId();
+      if (zone == null) {
+         return ImmutableSet.of();
+      }
+      return listSecurityGroupsInLocation(zone);
+   }
+
+   public Set<SecurityGroup> listSecurityGroupsInLocation(String zone) {
+      Iterable<? extends SecurityGroupInZone> rawGroups = pollSecurityGroupsByZone(zone);
+      Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
+              groupConverter);
+      return ImmutableSet.copyOf(groups);
+   }
+
+   @Override
+   public Set<SecurityGroup> listSecurityGroupsForNode(String id) {
+      ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(checkNotNull(id, "id"));
+      String zone = zoneAndId.getZone();
+      String instanceId = zoneAndId.getId();
+
+      Optional<? extends ServerWithSecurityGroupsApi> serverApi = api.getServerWithSecurityGroupsExtensionForZone(zone);
+      Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
+
+      if (!serverApi.isPresent() || !sgApi.isPresent()) {
+         return ImmutableSet.of();
+      }
+
+      ServerWithSecurityGroups instance = serverApi.get().get(instanceId);
+      if (instance == null) {
+         return ImmutableSet.of();
+      }
+
+      Set<String> groupNames = instance.getSecurityGroupNames();
+      Set<? extends SecurityGroupInZone> rawGroups =
+              sgApi.get().list().filter(nameIn(groupNames)).transform(groupToGroupInZone(zone)).toSet();
+
+      return ImmutableSet.copyOf(transform(filter(rawGroups, notNull()), groupConverter));
+   }
+
+   @Override
+   public SecurityGroup getSecurityGroupById(String id) {
+      ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(checkNotNull(id, "id"));
+      String zone = zoneAndId.getZone();
+      String groupId = zoneAndId.getId();
+
+      Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
+
+      if (!sgApi.isPresent()) {
+         return null;
+      }
+
+      SecurityGroupInZone rawGroup = new SecurityGroupInZone(sgApi.get().get(groupId), zone);
+
+      return groupConverter.apply(rawGroup);
+   }
+
+   @Override
+   public SecurityGroup createSecurityGroup(String name, Location location) {
+      String zone = location.getId();
+      if (zone == null) {
+         return null;
+      }
+      return createSecurityGroup(name, zone);
+   }
+
+   public SecurityGroup createSecurityGroup(String name, String zone) {
+      String markerGroup = namingConvention.create().sharedNameForGroup(name);
+      ZoneSecurityGroupNameAndPorts zoneAndName = new ZoneSecurityGroupNameAndPorts(zone, markerGroup, ImmutableSet.<Integer> of());
+
+      SecurityGroupInZone rawGroup = groupCreator.apply(zoneAndName);
+      return groupConverter.apply(rawGroup);
+   }
+
+   @Override
+   public boolean removeSecurityGroup(String id) {
+      checkNotNull(id, "id");
+      ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(id);
+      String zone = zoneAndId.getZone();
+      String groupId = zoneAndId.getId();
+
+      Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
+
+      if (!sgApi.isPresent()) {
+         return false;
+      }
+
+      if (sgApi.get().get(groupId) == null) {
+         return false;
+      }
+
+      sgApi.get().delete(groupId);
+      // TODO: test this clear happens
+      groupCreator.invalidate(new ZoneSecurityGroupNameAndPorts(zone, groupId, ImmutableSet.<Integer> of()));
+      return true;
+   }
+
+   @Override
+   public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
+      String zone = group.getLocation().getId();
+      ZoneAndId groupZoneAndId = ZoneAndId.fromSlashEncoded(group.getId());
+      String id = groupZoneAndId.getId();
+      Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
+
+      if (!sgApi.isPresent()) {
+         return null;
+      }
+
+      if (ipPermission.getCidrBlocks().size() > 0) {
+         for (String cidr : ipPermission.getCidrBlocks()) {
+            sgApi.get().createRuleAllowingCidrBlock(id,
+                    Ingress.builder()
+                            .ipProtocol(ipPermission.getIpProtocol())
+                            .fromPort(ipPermission.getFromPort())
+                            .toPort(ipPermission.getToPort())
+                            .build(),
+                    cidr);
+         }
+      }
+
+      if (ipPermission.getGroupIds().size() > 0) {
+         for (String zoneAndGroupRaw : ipPermission.getGroupIds()) {
+            ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(zoneAndGroupRaw);
+            String groupId = zoneAndId.getId();
+            sgApi.get().createRuleAllowingSecurityGroupId(id,
+                    Ingress.builder()
+                            .ipProtocol(ipPermission.getIpProtocol())
+                            .fromPort(ipPermission.getFromPort())
+                            .toPort(ipPermission.getToPort())
+                            .build(),
+                    groupId);
+         }
+      }
+
+      return getSecurityGroupById(ZoneAndId.fromZoneAndId(zone, id).slashEncode());
+   }
+
+   @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) {
+      String zone = group.getLocation().getId();
+      ZoneAndId groupZoneAndId = ZoneAndId.fromSlashEncoded(group.getId());
+      String id = groupZoneAndId.getId();
+
+      Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
+
+      if (!sgApi.isPresent()) {
+         return null;
+      }
+
+      org.jclouds.openstack.nova.v2_0.domain.SecurityGroup securityGroup = sgApi.get().get(id);
+
+      if (ipPermission.getCidrBlocks().size() > 0) {
+         for (String cidr : ipPermission.getCidrBlocks()) {
+            for (SecurityGroupRule rule : filter(securityGroup.getRules(),
+                    and(ruleCidr(cidr), ruleProtocol(ipPermission.getIpProtocol()),
+                            ruleStartPort(ipPermission.getFromPort()),
+                            ruleEndPort(ipPermission.getToPort())))) {
+               sgApi.get().deleteRule(rule.getId());
+            }
+         }
+      }
+
+      if (ipPermission.getGroupIds().size() > 0) {
+         for (String groupId : ipPermission.getGroupIds()) {
+            for (SecurityGroupRule rule : filter(securityGroup.getRules(),
+                    and(ruleGroup(groupId), ruleProtocol(ipPermission.getIpProtocol()),
+                            ruleStartPort(ipPermission.getFromPort()),
+                            ruleEndPort(ipPermission.getToPort())))) {
+               sgApi.get().deleteRule(rule.getId());
+            }
+
+         }
+      }
+
+      return getSecurityGroupById(ZoneAndId.fromZoneAndId(zone, id).slashEncode());
+   }
+
+   @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 false;
+   }
+
+   @Override
+   public boolean supportsTenantIdGroupIdPairs() {
+      return false;
+   }
+
+   @Override
+   public boolean supportsGroupIds() {
+      return true;
+   }
+
+   @Override
+   public boolean supportsPortRangesForGroups() {
+      return false;
+   }
+
+   protected Iterable<? extends SecurityGroupInZone> pollSecurityGroups() {
+      Iterable<? extends Set<? extends SecurityGroupInZone>> groups
+              = transform(zoneIds.get(), allSecurityGroupsInZone());
+
+      return concat(groups);
+   }
+
+
+   protected Iterable<? extends SecurityGroupInZone> pollSecurityGroupsByZone(String zone) {
+      return allSecurityGroupsInZone().apply(zone);
+   }
+
+   protected Function<String, Set<? extends SecurityGroupInZone>> allSecurityGroupsInZone() {
+      return new Function<String, Set<? extends SecurityGroupInZone>>() {
+
+         @Override
+         public Set<? extends SecurityGroupInZone> apply(final String from) {
+            Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(from);
+
+            if (!sgApi.isPresent()) {
+               return ImmutableSet.of();
+            }
+
+
+            return sgApi.get().list().transform(groupToGroupInZone(from)).toSet();
+         }
+
+      };
+   }
+
+   protected Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroupInZone> groupToGroupInZone(final String zone) {
+      return new Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroupInZone>() {
+         @Override
+         public SecurityGroupInZone apply(org.jclouds.openstack.nova.v2_0.domain.SecurityGroup group) {
+            return new SecurityGroupInZone(group, zone);
+         }
+      };
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
new file mode 100644
index 0000000..f7c18ee
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
@@ -0,0 +1,112 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
+import org.jclouds.rest.InsufficientResourcesException;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * A function for adding and allocating an ip to a node
+ * 
+ * @author Adrian Cole
+ */
+public class AllocateAndAddFloatingIpToNode implements
+         Function<AtomicReference<NodeMetadata>, AtomicReference<NodeMetadata>> {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final Predicate<AtomicReference<NodeMetadata>> nodeRunning;
+   private final NovaApi novaApi;
+   private final LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache;
+
+   @Inject
+   public AllocateAndAddFloatingIpToNode(@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
+            NovaApi novaApi, @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache) {
+      this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
+      this.novaApi = checkNotNull(novaApi, "novaApi");
+      this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
+   }
+
+   @Override
+   public AtomicReference<NodeMetadata> apply(AtomicReference<NodeMetadata> input) {
+      checkState(nodeRunning.apply(input), "node never achieved state running %s", input.get());
+      NodeMetadata node = input.get();
+      // node's location is a host
+      String zoneId = node.getLocation().getParent().getId();
+      FloatingIPApi floatingIpApi = novaApi.getFloatingIPExtensionForZone(zoneId).get();
+
+      FloatingIP ip = null;
+      try {
+         logger.debug(">> allocating or reassigning floating ip for node(%s)", node.getId());
+         ip = floatingIpApi.create();
+      } catch (InsufficientResourcesException e) {
+         logger.trace("<< [%s] allocating a new floating ip for node(%s)", e.getMessage(), node.getId());
+         logger.trace(">> searching for existing, unassigned floating ip for node(%s)", node.getId());
+         ArrayList<FloatingIP> unassignedIps = Lists.newArrayList(Iterables.filter(floatingIpApi.list(),
+                  new Predicate<FloatingIP>() {
+
+                     @Override
+                     public boolean apply(FloatingIP arg0) {
+                        return arg0.getFixedIp() == null;
+                     }
+
+                  }));
+         // try to prevent multiple parallel launches from choosing the same ip.
+         Collections.shuffle(unassignedIps);
+         ip = Iterables.getLast(unassignedIps);
+      }
+      logger.debug(">> adding floatingIp(%s) to node(%s)", ip.getIp(), node.getId());
+
+      floatingIpApi.addToServer(ip.getIp(), node.getProviderId());
+      input.set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.getIp())).build());
+      floatingIpCache.invalidate(ZoneAndId.fromSlashEncoded(node.getId()));
+      return input;
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper("AllocateAndAddFloatingIpToNode").toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CreateSecurityGroupIfNeeded.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CreateSecurityGroupIfNeeded.java
new file mode 100644
index 0000000..6b5d519
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CreateSecurityGroupIfNeeded.java
@@ -0,0 +1,93 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.nameEquals;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.domain.Ingress;
+import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
+import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupApi;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Singleton
+public class CreateSecurityGroupIfNeeded implements Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+   protected final NovaApi novaApi;
+
+   @Inject
+   public CreateSecurityGroupIfNeeded(NovaApi novaApi) {
+      this.novaApi = checkNotNull(novaApi, "novaApi");
+   }
+
+   @Override
+   public SecurityGroupInZone apply(ZoneSecurityGroupNameAndPorts zoneSecurityGroupNameAndPorts) {
+      checkNotNull(zoneSecurityGroupNameAndPorts, "zoneSecurityGroupNameAndPorts");
+
+      String zoneId = zoneSecurityGroupNameAndPorts.getZone();
+      Optional<? extends SecurityGroupApi> api = novaApi.getSecurityGroupExtensionForZone(zoneId);
+      checkArgument(api.isPresent(), "Security groups are required, but the extension is not availablein zone %s!", zoneId);
+      logger.debug(">> creating securityGroup %s", zoneSecurityGroupNameAndPorts);
+      try {
+
+         SecurityGroup securityGroup = api.get().createWithDescription(
+                  zoneSecurityGroupNameAndPorts.getName(), zoneSecurityGroupNameAndPorts.getName());
+
+         logger.debug("<< created securityGroup(%s)", securityGroup);
+         for (int port : zoneSecurityGroupNameAndPorts.getPorts()) {
+            authorizeGroupToItselfAndAllIPsToTCPPort(api.get(), securityGroup, port);
+         }
+         return new SecurityGroupInZone(api.get().get(securityGroup.getId()), zoneId);
+      } catch (IllegalStateException e) {
+         logger.trace("<< trying to find securityGroup(%s): %s", zoneSecurityGroupNameAndPorts, e.getMessage());
+         SecurityGroup group = find(api.get().list(), nameEquals(zoneSecurityGroupNameAndPorts
+                  .getName()));
+         logger.debug("<< reused securityGroup(%s)", group.getId());
+         return new SecurityGroupInZone(group, zoneId);
+      }
+   }
+
+   private void authorizeGroupToItselfAndAllIPsToTCPPort(SecurityGroupApi securityGroupApi,
+            SecurityGroup securityGroup, int port) {
+      logger.debug(">> authorizing securityGroup(%s) permission to 0.0.0.0/0 on port %d", securityGroup, port);
+      securityGroupApi.createRuleAllowingCidrBlock(securityGroup.getId(), Ingress.builder().ipProtocol(
+               IpProtocol.TCP).fromPort(port).toPort(port).build(), "0.0.0.0/0");
+      logger.debug("<< authorized securityGroup(%s) permission to 0.0.0.0/0 on port %d", securityGroup, port);
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/FlavorInZoneToHardware.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/FlavorInZoneToHardware.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/FlavorInZoneToHardware.java
new file mode 100644
index 0000000..160944b
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/FlavorInZoneToHardware.java
@@ -0,0 +1,60 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.internal.VolumeImpl;
+import org.jclouds.domain.Location;
+import org.jclouds.openstack.nova.v2_0.domain.Flavor;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.FlavorInZone;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+
+/**
+ * A function for transforming the nova specific FlavorInZone object to the generic Hardware object.
+ * 
+ * @author Matt Stephenson
+ */
+public class FlavorInZoneToHardware implements Function<FlavorInZone, Hardware> {
+
+   private final Supplier<Map<String, Location>> locationIndex;
+
+   @Inject
+   public FlavorInZoneToHardware(Supplier<Map<String, Location>> locationIndex) {
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+   }
+
+   @Override
+   public Hardware apply(FlavorInZone flavorInZone) {
+      Location location = locationIndex.get().get(flavorInZone.getZone());
+      checkState(location != null, "location %s not in locationIndex: %s", flavorInZone.getZone(), locationIndex.get());
+      Flavor flavor = flavorInZone.getFlavor();
+      return new HardwareBuilder().id(flavorInZone.slashEncode()).providerId(flavor.getId()).name(flavor.getName())
+               .ram(flavor.getRam()).processor(new Processor(flavor.getVcpus(), 1.0)).volume(
+                        new VolumeImpl(Float.valueOf(flavor.getDisk()), true, true)).location(location).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
new file mode 100644
index 0000000..109da29
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
@@ -0,0 +1,70 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.domain.Location;
+import org.jclouds.openstack.nova.v2_0.domain.Image.Status;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ImageInZone;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Supplier;
+
+/**
+ * A function for transforming a nova-specific Image into a generic Image object.
+ * 
+ * @author Matt Stephenson
+ */
+public class ImageInZoneToImage implements Function<ImageInZone, Image> {
+   private final Map<Status, org.jclouds.compute.domain.Image.Status> toPortableImageStatus;
+   private final Function<org.jclouds.openstack.nova.v2_0.domain.Image, OperatingSystem> imageToOs;
+   private final Supplier<Map<String, Location>> locationIndex;
+
+   @Inject
+   public ImageInZoneToImage(Map<org.jclouds.openstack.nova.v2_0.domain.Image.Status, Image.Status> toPortableImageStatus, 
+            Function<org.jclouds.openstack.nova.v2_0.domain.Image, OperatingSystem> imageToOs,
+            Supplier<Map<String, Location>> locationIndex) {
+      this.toPortableImageStatus = checkNotNull(toPortableImageStatus, "toPortableImageStatus");
+      this.imageToOs = checkNotNull(imageToOs, "imageToOs");
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+   }
+
+   @Override
+   public Image apply(ImageInZone imageInZone) {
+      Location location = locationIndex.get().get(imageInZone.getZone());
+      checkState(location != null, "location %s not in locationIndex: %s", imageInZone.getZone(), locationIndex.get());
+      org.jclouds.openstack.nova.v2_0.domain.Image image = imageInZone.getImage();
+      return new ImageBuilder().id(imageInZone.slashEncode()).providerId(image.getId()).name(image.getName())
+               .userMetadata(image.getMetadata()).operatingSystem(imageToOs.apply(image)).description(image.getName())
+               .location(location).status(toPortableImageStatus.get(image.getStatus())).build();
+   }
+   
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this).toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageToOperatingSystem.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageToOperatingSystem.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageToOperatingSystem.java
new file mode 100644
index 0000000..f26c4e0
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageToOperatingSystem.java
@@ -0,0 +1,128 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Predicates.containsPattern;
+import static com.google.common.base.Predicates.equalTo;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.nova.v2_0.domain.Image;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+
+/**
+ * A function for transforming a nova specific Image into a generic OperatingSystem object.
+ * 
+ * @author Matt Stephenson
+ */
+public class ImageToOperatingSystem implements Function<Image, OperatingSystem> {
+   public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
+   // Windows Server 2008 R2 x64
+   public static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows (.*) (x[86][64])");
+
+   @javax.annotation.Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final Map<OsFamily, Map<String, String>> osVersionMap;
+
+   @Inject
+   public ImageToOperatingSystem(Map<OsFamily, Map<String, String>> osVersionMap) {
+      this.osVersionMap = osVersionMap;
+   }
+
+   public OperatingSystem apply(final Image from) {
+      OsFamily osFamily = null;
+      String osVersion = null;
+
+      String imageName = Objects.firstNonNull(from.getName(), "unspecified");
+
+      boolean is64Bit = true;
+
+      if (imageName.indexOf("Windows") != -1) {
+         osFamily = OsFamily.WINDOWS;
+         Matcher matcher = WINDOWS_PATTERN.matcher(from.getName());
+         if (matcher.find()) {
+            osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(1), osVersionMap);
+            is64Bit = matcher.group(2).equals("x64");
+         }
+      } else {
+         if (imageName.contains("Red Hat EL")) {
+            osFamily = OsFamily.RHEL;
+         } else if (imageName.contains("Oracle EL")) {
+            osFamily = OsFamily.OEL;
+         } else {
+            final Iterable<String> imageNameParts = Splitter.on(CharMatcher.WHITESPACE).trimResults().split(
+                     imageName.toLowerCase());
+
+            try {
+               osFamily = find(Arrays.asList(OsFamily.values()), new Predicate<OsFamily>() {
+                  @Override
+                  public boolean apply(OsFamily osFamily) {
+                     return any(imageNameParts, equalTo(osFamily.name().toLowerCase()));
+                  }
+               });
+            } catch (NoSuchElementException e) {
+               String ubuntuVersion = startsWithUbuntuVersion(imageNameParts);
+               if (ubuntuVersion != null) {
+                  osFamily = OsFamily.UBUNTU;
+                  osVersion = ubuntuVersion;
+               } else {
+                  logger.trace("could not parse operating system family for image(%s): %s", from.getId(), imageNameParts);
+                  osFamily = OsFamily.UNRECOGNIZED;
+               }
+            }
+         }
+         Matcher matcher = DEFAULT_PATTERN.matcher(imageName);
+         if (matcher.find() && matcher.groupCount() >= 3) {
+            osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(3), osVersionMap);
+         }
+      }
+      return new OperatingSystem(osFamily, imageName, osVersion, null, imageName, is64Bit);
+   }
+
+   String startsWithUbuntuVersion(final Iterable<String> imageNameParts) {
+      Map<String, String> ubuntuVersions = osVersionMap.get(OsFamily.UBUNTU);
+      for (String ubuntuKey : filter(ubuntuVersions.keySet(), not(equalTo("")))) {
+         if (any(imageNameParts, containsPattern("^" + ubuntuKey + ".*"))) {
+            return ubuntuVersions.get(ubuntuKey);
+         }
+      }
+      return null;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
new file mode 100644
index 0000000..fc772df
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
@@ -0,0 +1,75 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+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.domain.Location;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+
+
+/**
+ * A function for transforming a Nova-specific SecurityGroup into a generic
+ * SecurityGroup object.
+ * 
+ * @author Andrew Bayer
+ */
+@Singleton
+public class NovaSecurityGroupInZoneToSecurityGroup implements Function<SecurityGroupInZone, SecurityGroup> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   protected final Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> baseConverter;
+   protected final Supplier<Map<String, Location>> locationIndex;
+
+   @Inject
+   public NovaSecurityGroupInZoneToSecurityGroup(Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> baseConverter,
+                                                 Supplier<Map<String, Location>> locationIndex) {
+      this.baseConverter = checkNotNull(baseConverter, "baseConverter");
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+   }
+
+   @Override
+   public SecurityGroup apply(SecurityGroupInZone group) {
+      SecurityGroupBuilder builder = SecurityGroupBuilder.fromSecurityGroup(baseConverter.apply(group.getSecurityGroup()));
+
+      Location zone = locationIndex.get().get(group.getZone());
+      checkState(zone != null, "location %s not in locationIndex: %s", group.getZone(), locationIndex.get());
+
+      builder.location(zone);
+
+      builder.id(group.getZone() + "/" + group.getSecurityGroup().getId());
+
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupToSecurityGroup.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupToSecurityGroup.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupToSecurityGroup.java
new file mode 100644
index 0000000..d39f849
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupToSecurityGroup.java
@@ -0,0 +1,69 @@
+/*
+ * 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.openstack.nova.v2_0.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.openstack.nova.v2_0.domain.SecurityGroupRule;
+
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+
+
+/**
+ * A function for transforming a Nova-specific SecurityGroup into a generic
+ * SecurityGroup object.
+ * 
+ * @author Andrew Bayer
+ */
+@Singleton
+public class NovaSecurityGroupToSecurityGroup implements Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   protected Function<SecurityGroupRule,IpPermission> ruleToPermission;
+   
+   @Inject
+   public NovaSecurityGroupToSecurityGroup(Function<SecurityGroupRule,IpPermission> ruleToPermission) {
+      this.ruleToPermission = ruleToPermission;
+   }
+
+   @Override
+   public SecurityGroup apply(org.jclouds.openstack.nova.v2_0.domain.SecurityGroup group) {
+      SecurityGroupBuilder builder = new SecurityGroupBuilder();
+      
+      builder.id(group.getId());
+      builder.providerId(group.getId());
+      builder.ownerId(group.getTenantId());
+      builder.name(group.getName());
+      if (group.getRules() != null) {
+         builder.ipPermissions(transform(group.getRules(), ruleToPermission));
+      }
+
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
new file mode 100644
index 0000000..4993f0c
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
@@ -0,0 +1,77 @@
+/*
+ * 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.openstack.nova.v2_0.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.openstack.nova.v2_0.compute.predicates.AllNodesInGroupTerminated;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.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;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+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/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
new file mode 100644
index 0000000..269a333
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
@@ -0,0 +1,74 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.cache.LoadingCache;
+
+/**
+ * A function for removing and deallocating an ip address from a node
+ * 
+ * @author Adrian Cole
+ */
+public class RemoveFloatingIpFromNodeAndDeallocate implements Function<ZoneAndId, ZoneAndId> {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final NovaApi novaApi;
+   private final LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache;
+
+   @Inject
+   public RemoveFloatingIpFromNodeAndDeallocate(NovaApi novaApi,
+            @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache) {
+      this.novaApi = checkNotNull(novaApi, "novaApi");
+      this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
+   }
+
+   @Override
+   public ZoneAndId apply(ZoneAndId id) {
+      FloatingIPApi floatingIpApi = novaApi.getFloatingIPExtensionForZone(id.getZone()).get();
+      for (FloatingIP ip : floatingIpCache.getUnchecked(id)) {
+         logger.debug(">> removing floatingIp(%s) from node(%s)", ip, id);
+         floatingIpApi.removeFromServer(ip.getIp(), id.getId());
+         logger.debug(">> deallocating floatingIp(%s)", ip);
+         floatingIpApi.delete(ip.getId());
+      }
+      floatingIpCache.invalidate(id);
+      return id;
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper("RemoveFloatingIpFromNodeAndDecreate").toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5857efca/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
new file mode 100644
index 0000000..a98a62b
--- /dev/null
+++ b/dependencies/jclouds/openstack-nova/1.7.1-stratos/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
@@ -0,0 +1,99 @@
+/*
+ * 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.openstack.nova.v2_0.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.getFirst;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.logging.Logger;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
+import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
+
+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.util.concurrent.Atomics;
+
+
+/**
+ * A function for transforming a nova-specific SecurityGroupRule into a generic
+ * IpPermission object.
+ * 
+ * @author Andrew Bayer
+ */
+public class SecurityGroupRuleToIpPermission implements Function<SecurityGroupRule, IpPermission> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+   protected final Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone;
+   protected final Supplier<Map<String, Location>> locationIndex;
+   LoadingCache<ZoneAndName, SecurityGroupInZone> groupMap;
+
+   @Inject
+   public SecurityGroupRuleToIpPermission(@Named("SECURITYGROUP_PRESENT") Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone,
+                                          Supplier<Map<String, Location>> locationIndex,
+                                          LoadingCache<ZoneAndName, SecurityGroupInZone> groupMap) {
+      this.returnSecurityGroupExistsInZone = checkNotNull(returnSecurityGroupExistsInZone,
+              "returnSecurityGroupExistsInZone");
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+      this.groupMap = checkNotNull(groupMap, "groupMap");
+   }
+
+   @Override
+   public IpPermission apply(SecurityGroupRule rule) {
+      IpPermission.Builder builder = IpPermission.builder();
+      builder.ipProtocol(rule.getIpProtocol());
+      builder.fromPort(rule.getFromPort());
+      builder.toPort(rule.getToPort());
+      if (rule.getGroup() != null) {
+         String zone = getFirst(filter(locationIndex.get().keySet(), isSecurityGroupInZone(rule.getGroup().getName())),
+                 null);
+         if (zone != null) {
+            SecurityGroupInZone group = groupMap.getUnchecked(ZoneAndName.fromZoneAndName(zone, rule.getGroup().getName()));
+            builder.groupId(zone + "/" + group.getSecurityGroup().getId());
+         }
+      }
+      if (rule.getIpRange() != null)
+         builder.cidrBlock(rule.getIpRange());
+      
+      return builder.build();
+   }
+
+   protected Predicate<String> isSecurityGroupInZone(final String groupName) {
+      return new Predicate<String>() {
+
+         @Override
+         public boolean apply(String zone) {
+            AtomicReference<ZoneAndName> securityGroupInZoneRef = Atomics.newReference(ZoneAndName.fromZoneAndName(zone, groupName));
+            return returnSecurityGroupExistsInZone.apply(securityGroupInZoneRef);
+         }
+      };
+   }
+}