openstack implicit security group integration with compute service; ensured hpcloud doesn't pickup kernel or ramdisk images

This commit is contained in:
Adrian Cole 2012-03-20 22:37:18 -07:00
parent ac2528ef6f
commit c9b5b1db87
55 changed files with 1380 additions and 360 deletions

View File

@ -204,7 +204,25 @@ public class NodePredicates {
}
};
}
/**
* Return nodes who have a value for {@link NodeMetadata#getGroup}
*
*/
public static Predicate<NodeMetadata> hasGroup() {
return new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata nodeMetadata) {
return nodeMetadata.getGroup() != null;
}
@Override
public String toString() {
return "hasGroup()";
}
};
}
/**
* Return nodes with specified group that are in the NODE_RUNNING state.
*

View File

@ -243,5 +243,5 @@ filesystem.propertiesbuilder=org.jclouds.filesystem.FilesystemBlobStorePropertie
hpcloud-objectstorage-lvs.contextbuilder=org.jclouds.hpcloud.objectstorage.lvs.HPCloudObjectStorageLasVegasContextBuilder
hpcloud-objectstorage-lvs.propertiesbuilder=org.jclouds.hpcloud.objectstorage.lvs.HPCloudObjectStorageLasVegasPropertiesBuilder
hpcloud-compute.contextbuilder=org.jclouds.openstack.nova.v1_1.NovaContextBuilder
hpcloud-compute.contextbuilder=org.jclouds.hpcloud.compute.HPCloudComputeContextBuilder
hpcloud-compute.propertiesbuilder=org.jclouds.hpcloud.compute.HPCloudComputePropertiesBuilder

View File

@ -16,32 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
package org.jclouds.hpcloud.compute;
import java.util.List;
import java.util.Properties;
import org.jclouds.hpcloud.compute.config.HPCloudComputeServiceContextModule;
import org.jclouds.openstack.nova.v1_1.NovaContextBuilder;
import com.google.inject.Module;
/**
* In-flight images will have the status attribute set to SAVING and the
* conditional progress element (0-100% completion) will also be returned. Other
* possible values for the status attribute include: UNKNOWN, ACTIVE, SAVING,
* ERROR, and DELETED. Images with an ACTIVE status are available for install.
* The optional minDisk and minRam attributes set the minimum disk and RAM
* requirements needed to create a server with the image.
*
* @author Adrian Cole
*/
public enum ImageStatus {
public class HPCloudComputeContextBuilder extends NovaContextBuilder {
UNRECOGNIZED, UNKNOWN, ACTIVE, SAVING, ERROR, DELETED;
public String value() {
return name();
public HPCloudComputeContextBuilder(Properties props) {
super(props);
}
public static ImageStatus fromValue(String v) {
try {
return valueOf(v);
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new HPCloudComputeServiceContextModule());
}
}

View File

@ -20,11 +20,12 @@ package org.jclouds.hpcloud.compute;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_TIMEOUT_NODE_TERMINATED;
import static org.jclouds.openstack.nova.v1_1.reference.NovaConstants.PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS;
import java.util.Properties;
import org.jclouds.openstack.nova.v1_1.NovaPropertiesBuilder;
import org.jclouds.openstack.nova.v1_1.reference.NovaConstants;
/**
*
@ -37,7 +38,9 @@ public class HPCloudComputePropertiesBuilder extends NovaPropertiesBuilder {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ISO3166_CODES, "US-NV");
properties.setProperty(PROPERTY_ENDPOINT, "https://region-a.geo-1.identity.hpcloudsvc.com:35357");
properties.setProperty(NovaConstants.PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS, "true");
properties.setProperty(PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS, "true");
// deallocating ip addresses can take a while
properties.setProperty(PROPERTY_TIMEOUT_NODE_TERMINATED, 60 * 1000 + "");
return properties;
}

View File

@ -0,0 +1,45 @@
package org.jclouds.hpcloud.compute;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.location.Zone;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.NovaComputeServiceAdapter;
import org.jclouds.openstack.nova.v1_1.compute.functions.RemoveFloatingIpFromNodeAndDeallocate;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ImageInZone;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
public class HPCloudComputeServiceAdapter extends NovaComputeServiceAdapter {
@Inject
public HPCloudComputeServiceAdapter(NovaClient novaClient, @Zone Supplier<Set<String>> zoneIds,
RemoveFloatingIpFromNodeAndDeallocate removeFloatingIpFromNodeAndDeallocate) {
super(novaClient, zoneIds, removeFloatingIpFromNodeAndDeallocate);
}
@Override
public Iterable<ImageInZone> listImages() {
return Iterables.filter(super.listImages(), new Predicate<ImageInZone>() {
@Override
public boolean apply(ImageInZone arg0) {
String imageName = arg0.getImage().getName();
return imageName.indexOf("Kernel") == -1 && imageName.indexOf("Ramdisk") == -1;
}
@Override
public String toString() {
return "notKernelOrRamdisk";
}
});
}
}

View File

@ -0,0 +1,37 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.hpcloud.compute.config;
import org.jclouds.hpcloud.compute.HPCloudComputeServiceAdapter;
import org.jclouds.openstack.nova.v1_1.compute.NovaComputeServiceAdapter;
import org.jclouds.openstack.nova.v1_1.compute.config.NovaComputeServiceContextModule;
/**
*
* @author Adrian Cole
*/
public class HPCloudComputeServiceContextModule extends NovaComputeServiceContextModule {
@Override
protected void configure() {
super.configure();
bind(NovaComputeServiceAdapter.class).to(HPCloudComputeServiceAdapter.class);
}
}

View File

@ -73,6 +73,7 @@ public class HPCloudComputeTemplateBuilderLiveTest extends BaseTemplateBuilderLi
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getImage().getName(), "Ubuntu Oneiric 11.10 Server 64-bit 20111212");
assertEquals(defaultTemplate.getLocation().getId(), "az-1.region-a.geo-1");
assertEquals(defaultTemplate.getOptions().as(NovaTemplateOptions.class).shouldAutoAssignFloatingIp(), true);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);

View File

@ -45,7 +45,6 @@ public class NovaPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_API_VERSION, "1.1");
properties.setProperty(PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS, "false");
properties.setProperty(PROPERTY_NOVA_TIMEOUT_SECURITYGROUP_PRESENT, "500");
return properties;
}

View File

@ -0,0 +1,147 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
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.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.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.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import org.jclouds.openstack.nova.v1_1.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;
/**
* @author Adrian Cole
*/
@Singleton
public class NovaComputeService extends BaseComputeService {
private final NovaClient novaClient;
private final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap;
private final Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId;
@Inject
protected NovaComputeService(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,
GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named("NODE_TERMINATED") Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, NovaClient novaClient,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials,
timeouts, executor);
this.novaClient = checkNotNull(novaClient, "novaClient");
this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap");
this.orphanedGroupsByZoneId = checkNotNull(orphanedGroupsByZoneId, "orphanedGroupsByZoneId");
}
@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);
}
private void cleanupOrphanedSecurityGroupsInZone(Set<String> groups, String zoneId) {
Optional<SecurityGroupClient> securityGroupClient = novaClient.getSecurityGroupExtensionForZone(zoneId);
if (securityGroupClient.isPresent()) {
for (String group : groups) {
for (SecurityGroup securityGroup : Iterables.filter(securityGroupClient.get().listSecurityGroups(),
SecurityGroupPredicates.nameEquals("jclouds#" + group))) {
ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, securityGroup.getName());
logger.debug(">> deleting securityGroup(%s)", zoneAndName);
securityGroupClient.get().deleteSecurityGroup(securityGroup.getId());
// TODO: test this clear happens
securityGroupMap.invalidate(zoneAndName);
logger.debug("<< deleted securityGroup(%s)", zoneAndName);
}
}
}
}
/**
* returns template options, except of type {@link NovaTemplateOptions}.
*/
@Override
public NovaTemplateOptions templateOptions() {
return NovaTemplateOptions.class.cast(super.templateOptions());
}
}

View File

@ -34,10 +34,6 @@ import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.Zone;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.FlavorInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ImageInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ServerInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.compute.functions.RemoveFloatingIpFromNodeAndDeallocate;
import org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v1_1.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
@ -45,12 +41,17 @@ import org.jclouds.openstack.nova.v1_1.domain.Flavor;
import org.jclouds.openstack.nova.v1_1.domain.Image;
import org.jclouds.openstack.nova.v1_1.domain.RebootType;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.FlavorInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ImageInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ServerInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.options.CreateServerOptions;
import org.jclouds.openstack.nova.v1_1.predicates.ImagePredicates;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import static com.google.common.collect.Iterables.*;
import com.google.common.collect.ImmutableSet.Builder;
/**
@ -103,7 +104,7 @@ public class NovaComputeServiceAdapter implements
public Iterable<FlavorInZone> listHardwareProfiles() {
Builder<FlavorInZone> builder = ImmutableSet.<FlavorInZone> builder();
for (final String zoneId : zoneIds.get()) {
builder.addAll(Iterables.transform(novaClient.getFlavorClientForZone(zoneId).listFlavorsInDetail(),
builder.addAll(transform(novaClient.getFlavorClientForZone(zoneId).listFlavorsInDetail(),
new Function<Flavor, FlavorInZone>() {
@Override
@ -120,15 +121,15 @@ public class NovaComputeServiceAdapter implements
public Iterable<ImageInZone> listImages() {
Builder<ImageInZone> builder = ImmutableSet.<ImageInZone> builder();
for (final String zoneId : zoneIds.get()) {
builder.addAll(Iterables.transform(novaClient.getImageClientForZone(zoneId).listImagesInDetail(),
new Function<Image, ImageInZone>() {
builder.addAll(transform(filter(novaClient.getImageClientForZone(zoneId).listImagesInDetail(), ImagePredicates
.statusEquals(Image.Status.ACTIVE)), new Function<Image, ImageInZone>() {
@Override
public ImageInZone apply(Image arg0) {
return new ImageInZone(arg0, zoneId);
}
@Override
public ImageInZone apply(Image arg0) {
return new ImageInZone(arg0, zoneId);
}
}));
}));
}
return builder.build();
}
@ -137,7 +138,7 @@ public class NovaComputeServiceAdapter implements
public Iterable<ServerInZone> listNodes() {
Builder<ServerInZone> builder = ImmutableSet.<ServerInZone> builder();
for (final String zoneId : zoneIds.get()) {
builder.addAll(Iterables.transform(novaClient.getServerClientForZone(zoneId).listServersInDetail(),
builder.addAll(transform(novaClient.getServerClientForZone(zoneId).listServersInDetail(),
new Function<Server, ServerInZone>() {
@Override

View File

@ -27,6 +27,7 @@ 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;
@ -39,23 +40,25 @@ import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.NovaComputeService;
import org.jclouds.openstack.nova.v1_1.compute.NovaComputeServiceAdapter;
import org.jclouds.openstack.nova.v1_1.compute.domain.FlavorInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ImageInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ServerInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v1_1.compute.functions.CreateSecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.openstack.nova.v1_1.compute.functions.FlavorInZoneToHardware;
import org.jclouds.openstack.nova.v1_1.compute.functions.ImageInZoneToImage;
import org.jclouds.openstack.nova.v1_1.compute.functions.NovaImageToOperatingSystem;
import org.jclouds.openstack.nova.v1_1.compute.functions.OrphanedGroupsByZoneId;
import org.jclouds.openstack.nova.v1_1.compute.functions.ServerInZoneToNodeMetadata;
import org.jclouds.openstack.nova.v1_1.compute.loaders.CreateOrUpdateSecurityGroupAsNeeded;
import org.jclouds.openstack.nova.v1_1.compute.loaders.FindSecurityGroupOrCreate;
import org.jclouds.openstack.nova.v1_1.compute.loaders.LoadFloatingIpsForInstance;
import org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v1_1.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.FlavorInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ImageInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ServerInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v1_1.predicates.FindSecurityGroupWithNameAndReturnTrue;
import org.jclouds.openstack.nova.v1_1.reference.NovaConstants;
import org.jclouds.predicates.RetryablePredicate;
@ -68,6 +71,7 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
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;
@ -92,10 +96,15 @@ public class NovaComputeServiceContextModule
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<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.v1_1.domain.Image, OperatingSystem>>() {
@ -112,12 +121,12 @@ public class NovaComputeServiceContextModule
bind(new TypeLiteral<CacheLoader<ZoneAndId, Iterable<String>>>() {
}).annotatedWith(Names.named("FLOATINGIP")).to(LoadFloatingIpsForInstance.class);
bind(new TypeLiteral<Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>>() {
}).to(CreateSecurityGroupInZone.class);
bind(new TypeLiteral<CacheLoader<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>>() {
}).to(CreateOrUpdateSecurityGroupAsNeeded.class);
}).to(CreateSecurityGroupIfNeeded.class);
bind(new TypeLiteral<CacheLoader<ZoneAndName, SecurityGroupInZone>>() {
}).to(FindSecurityGroupOrCreate.class);
bind(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
@ -141,8 +150,8 @@ public class NovaComputeServiceContextModule
@Provides
@Singleton
protected LoadingCache<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> securityGroupMap(
CacheLoader<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> in) {
protected LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap(
CacheLoader<ZoneAndName, SecurityGroupInZone> in) {
return CacheBuilder.newBuilder().build(in);
}

View File

@ -34,8 +34,8 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import org.jclouds.rest.InsufficientResourcesException;

View File

@ -20,6 +20,8 @@ package org.jclouds.openstack.nova.v1_1.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.v1_1.predicates.SecurityGroupPredicates.nameEquals;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -29,11 +31,11 @@ import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v1_1.domain.Ingress;
import org.jclouds.openstack.nova.v1_1.domain.IpProtocol;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import com.google.common.base.Function;
@ -44,14 +46,14 @@ import com.google.common.base.Optional;
* @author Adrian Cole
*/
@Singleton
public class CreateSecurityGroupInZone implements Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> {
public class CreateSecurityGroupIfNeeded implements Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final NovaClient novaClient;
@Inject
public CreateSecurityGroupInZone(NovaClient novaClient) {
public CreateSecurityGroupIfNeeded(NovaClient novaClient) {
this.novaClient = checkNotNull(novaClient, "novaClient");
}
@ -62,16 +64,24 @@ public class CreateSecurityGroupInZone implements Function<ZoneSecurityGroupName
String zoneId = zoneSecurityGroupNameAndPorts.getZone();
Optional<SecurityGroupClient> client = novaClient.getSecurityGroupExtensionForZone(zoneId);
checkArgument(client.isPresent(), "Security groups are required, but the extension is not available!");
logger.debug(">> creating securityGroup %s", zoneSecurityGroupNameAndPorts);
SecurityGroup securityGroup = client.get().createSecurityGroupWithNameAndDescription(
zoneSecurityGroupNameAndPorts.getName(), zoneSecurityGroupNameAndPorts.getName());
try {
logger.debug("<< created securityGroup(%s)", securityGroup);
for (int port : zoneSecurityGroupNameAndPorts.getPorts()) {
authorizeGroupToItselfAndAllIPsToTCPPort(client.get(), securityGroup, port);
SecurityGroup securityGroup = client.get().createSecurityGroupWithNameAndDescription(
zoneSecurityGroupNameAndPorts.getName(), zoneSecurityGroupNameAndPorts.getName());
logger.debug("<< created securityGroup(%s)", securityGroup);
for (int port : zoneSecurityGroupNameAndPorts.getPorts()) {
authorizeGroupToItselfAndAllIPsToTCPPort(client.get(), securityGroup, port);
}
return new SecurityGroupInZone(client.get().getSecurityGroup(securityGroup.getId()), zoneId);
} catch (IllegalStateException e) {
logger.trace("<< trying to find securityGroup(%s): %s", zoneSecurityGroupNameAndPorts, e.getMessage());
SecurityGroup group = find(client.get().listSecurityGroups(), nameEquals(zoneSecurityGroupNameAndPorts
.getName()));
logger.debug("<< reused securityGroup(%s)", group.getId());
return new SecurityGroupInZone(group, zoneId);
}
return new SecurityGroupInZone(client.get().getSecurityGroup(securityGroup.getId()), zoneId);
}
private void authorizeGroupToItselfAndAllIPsToTCPPort(SecurityGroupClient securityGroupClient,

View File

@ -30,8 +30,8 @@ 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.v1_1.compute.domain.FlavorInZone;
import org.jclouds.openstack.nova.v1_1.domain.Flavor;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.FlavorInZone;
import com.google.common.base.Function;
import com.google.common.base.Supplier;

View File

@ -29,7 +29,7 @@ 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.v1_1.compute.domain.ImageInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ImageInZone;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@ -55,8 +55,8 @@ public class ImageInZoneToImage implements Function<ImageInZone, Image> {
Location location = locationIndex.get().get(imageInZone.getZone());
checkState(location != null, "location %s not in locationIndex: %s", imageInZone.getZone(), locationIndex.get());
org.jclouds.openstack.nova.v1_1.domain.Image image = imageInZone.getImage();
return new ImageBuilder()
.id(imageInZone.slashEncode()).providerId(image.getId()).name(image.getName()).operatingSystem(
imageToOs.apply(image)).description(image.getName()).location(location).build();
return new ImageBuilder().id(imageInZone.slashEncode()).providerId(image.getId()).name(image.getName())
.userMetadata(image.getMetadata()).operatingSystem(imageToOs.apply(image)).description(image.getName())
.location(location).build();
}
}

View File

@ -0,0 +1,79 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.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.v1_1.compute.predicates.AllNodesInGroupTerminated;
import org.jclouds.openstack.nova.v1_1.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;
}
}

View File

@ -27,7 +27,7 @@ import javax.inject.Named;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import com.google.common.base.Function;

View File

@ -20,8 +20,13 @@ package org.jclouds.openstack.nova.v1_1.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.net.Inet4Address;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
@ -42,16 +47,16 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.compute.domain.ServerInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ServerInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
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.Iterables;
import com.google.common.net.InetAddresses;
/**
* A function for transforming a nova-specific Server into a generic NodeMetadata object.
@ -97,15 +102,29 @@ public class ServerInZoneToNodeMetadata implements Function<ServerInZone, NodeMe
builder.operatingSystem(findOperatingSystemForServerOrNull(serverInZone));
builder.hardware(findHardwareForServerOrNull(serverInZone));
builder.state(from.getStatus().getNodeState());
builder.publicAddresses(getPublicAddresses(serverInZone));
builder.privateAddresses(Iterables.transform(from.getPrivateAddresses(),
AddressToStringTransformationFunction.INSTANCE));
builder.publicAddresses(filter(getPublicAddresses(serverInZone), isInet4Address));
builder.privateAddresses(filter(transform(from.getPrivateAddresses(),
AddressToStringTransformationFunction.INSTANCE), isInet4Address));
return builder.build();
}
public static final Predicate<String> isInet4Address = new Predicate<String>() {
@Override
public boolean apply(String input) {
try {
// Note we can do this, as InetAddress is now on the white list
return (InetAddresses.forString(input) instanceof Inet4Address);
} catch (IllegalArgumentException e) {
// could be a hostname
return true;
}
}
};
protected Iterable<String> getPublicAddresses(ServerInZone serverInZone) {
return Iterables.concat(Iterables.transform(serverInZone.getServer().getPublicAddresses(),
return concat(transform(serverInZone.getServer().getPublicAddresses(),
AddressToStringTransformationFunction.INSTANCE), floatingIpCache.getUnchecked(serverInZone));
}
@ -131,7 +150,7 @@ public class ServerInZoneToNodeMetadata implements Function<ServerInZone, NodeMe
public <T extends ComputeMetadata> T findObjectOfTypeForServerOrNull(Set<? extends T> supply, String type,
final String objectId, final ZoneAndId serverInZone) {
try {
return Iterables.find(supply, new Predicate<T>() {
return find(supply, new Predicate<T>() {
@Override
public boolean apply(T input) {
return input.getId().equals(ZoneAndId.fromZoneAndId(serverInZone.getZone(), objectId).slashEncode());

View File

@ -1,83 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.compute.loaders;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
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.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.compute.domain.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneSecurityGroupNameAndPorts;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CreateOrUpdateSecurityGroupAsNeeded extends
CacheLoader<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final Predicate<AtomicReference<ZoneAndName>> securityGroupEventualConsistencyDelay;
protected final Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator;
@Inject
public CreateOrUpdateSecurityGroupAsNeeded(
@Named("SECURITY") Predicate<AtomicReference<ZoneAndName>> securityGroupEventualConsistencyDelay,
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator) {
this.securityGroupEventualConsistencyDelay = checkNotNull(securityGroupEventualConsistencyDelay,
"securityGroupEventualConsistencyDelay");
this.groupCreator = checkNotNull(groupCreator, "groupCreator");
}
@Override
public SecurityGroupInZone load(ZoneSecurityGroupNameAndPorts zoneSecurityGroupNameAndPorts) {
checkNotNull(zoneSecurityGroupNameAndPorts, "zoneSecurityGroupNameAndPorts");
AtomicReference<ZoneAndName> securityGroupInZoneRef = new AtomicReference<ZoneAndName>(
zoneSecurityGroupNameAndPorts);
if (securityGroupEventualConsistencyDelay.apply(securityGroupInZoneRef)) {
ZoneAndName securityGroupInZone = securityGroupInZoneRef.get();
checkState(
securityGroupInZone instanceof SecurityGroupInZone,
"programming error: predicate %s should update the atomic reference to the actual security group found",
securityGroupEventualConsistencyDelay);
// TODO: check ports are actually present!
return SecurityGroupInZone.class.cast(securityGroupInZone);
} else {
return groupCreator.apply(zoneSecurityGroupNameAndPorts);
}
}
}

View File

@ -0,0 +1,88 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.compute.loaders;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;
/**
*
* @author Adrian Cole
*/
public class FindSecurityGroupOrCreate extends CacheLoader<ZoneAndName, SecurityGroupInZone> {
protected final Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone;
protected final Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator;
@Inject
public FindSecurityGroupOrCreate(
@Named("SECURITY") Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone,
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator) {
this.returnSecurityGroupExistsInZone = checkNotNull(returnSecurityGroupExistsInZone,
"returnSecurityGroupExistsInZone");
this.groupCreator = checkNotNull(groupCreator, "groupCreator");
}
@Override
public SecurityGroupInZone load(ZoneAndName in) {
AtomicReference<ZoneAndName> securityGroupInZoneRef = new AtomicReference<ZoneAndName>(checkNotNull(in,
"zoneSecurityGroupNameAndPorts"));
if (returnSecurityGroupExistsInZone.apply(securityGroupInZoneRef)) {
return returnExistingSecurityGroup(securityGroupInZoneRef);
} else {
return createNewSecurityGroup(in);
}
}
private SecurityGroupInZone returnExistingSecurityGroup(AtomicReference<ZoneAndName> securityGroupInZoneRef) {
ZoneAndName securityGroupInZone = securityGroupInZoneRef.get();
checkState(securityGroupInZone instanceof SecurityGroupInZone,
"programming error: predicate %s should update the atomic reference to the actual security group found",
returnSecurityGroupExistsInZone);
return SecurityGroupInZone.class.cast(securityGroupInZone);
}
private SecurityGroupInZone createNewSecurityGroup(ZoneAndName in) {
checkState(
checkNotNull(in, "zoneSecurityGroupNameAndPorts") instanceof ZoneSecurityGroupNameAndPorts,
"programming error: when issuing get to this cacheloader, you need to pass an instance of ZoneSecurityGroupNameAndPorts, not %s",
in);
ZoneSecurityGroupNameAndPorts zoneSecurityGroupNameAndPorts = ZoneSecurityGroupNameAndPorts.class.cast(in);
return groupCreator.apply(zoneSecurityGroupNameAndPorts);
}
@Override
public String toString() {
return "returnExistingSecurityGroupInZoneOrCreateAsNeeded()";
}
}

View File

@ -22,8 +22,8 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import com.google.common.base.Function;

View File

@ -0,0 +1,58 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.compute.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.collect.Iterables.all;
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
import static org.jclouds.compute.predicates.NodePredicates.inGroup;
import static org.jclouds.compute.predicates.NodePredicates.locationId;
import static org.jclouds.compute.predicates.NodePredicates.parentLocationId;
import javax.inject.Inject;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
/**
* @author Adrian Cole
*/
public class AllNodesInGroupTerminated implements Predicate<ZoneAndName> {
private final ComputeService computeService;
//TODO: TESTME
@Inject
public AllNodesInGroupTerminated(ComputeService computeService) {
this.computeService = checkNotNull(computeService, "computeService");
}
@Override
public boolean apply(ZoneAndName input) {
// new nodes can have the zone as their location, existing nodes, the parent is the
// location
return all(computeService.listNodesDetailsMatching(Predicates.<ComputeMetadata> or(locationId(input.getZone()),
parentLocationId(input.getZone()))), and(inGroup(input.getName()), TERMINATED));
}
}

View File

@ -21,20 +21,24 @@ package org.jclouds.openstack.nova.v1_1.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
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.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
@ -43,8 +47,14 @@ import org.jclouds.concurrent.Futures;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.functions.AllocateAndAddFloatingIpToNode;
import org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Ints;
/**
*
@ -55,7 +65,9 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
CreateNodesWithGroupEncodedIntoNameThenAddToSet {
private final AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode;
private final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache;
private final NovaClient novaClient;
private final Provider<TemplateBuilder> templateBuilderProvider;
@Inject
protected ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet(
@ -64,9 +76,13 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
@Named("NAMING_CONVENTION") String nodeNamingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode, NovaClient novaClient) {
Provider<TemplateBuilder> templateBuilderProvider,
AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache, NovaClient novaClient) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, executor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
this.securityGroupCache = checkNotNull(securityGroupCache, "securityGroupCache");
this.allocateAndAddFloatingIpToNode = checkNotNull(allocateAndAddFloatingIpToNode,
"allocateAndAddFloatingIpToNode");
this.novaClient = checkNotNull(novaClient, "novaClient");
@ -75,23 +91,38 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
@Override
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
// ensure we don't mutate the input template
Template mutableTemplate = templateBuilderProvider.get().fromTemplate(template).build();
// TODO: make NovaTemplateOptions with the following:
// security group, key pair
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(mutableTemplate.getOptions());
String zone = template.getLocation().getId();
String zone = mutableTemplate.getLocation().getId();
if (templateOptions.shouldAutoAssignFloatingIp()) {
checkArgument(novaClient.getFloatingIPExtensionForZone(zone).isPresent(),
"Floating IPs are required by options, but the extension is not available! options: %s", templateOptions);
"Floating IPs are required by options, but the extension is not available! options: %s",
templateOptions);
}
boolean securityGroupExensionPresent = novaClient.getSecurityGroupExtensionForZone(zone).isPresent();
List<Integer> inboundPorts = Ints.asList(templateOptions.getInboundPorts());
if (templateOptions.getSecurityGroupNames().size() > 0) {
checkArgument(novaClient.getSecurityGroupExtensionForZone(zone).isPresent(),
"Security groups are required by options, but the extension is not available! options: %s", templateOptions);
"Security groups are required by options, but the extension is not available! options: %s",
templateOptions);
} else if (securityGroupExensionPresent && inboundPorts.size() > 0) {
String securityGroupName = "jclouds#" + group;
try {
securityGroupCache.get(new ZoneSecurityGroupNameAndPorts(zone, securityGroupName, inboundPorts));
} catch (ExecutionException e) {
throw Throwables.propagate(e.getCause());
}
templateOptions.securityGroupNames(securityGroupName);
}
return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses);
}
@Override

View File

@ -27,20 +27,47 @@ import java.util.Set;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Resource;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.gson.annotations.SerializedName;
/**
* An image is a collection of files you use to create or rebuild a server.
* Operators provide pre-built OS images by default. You may also create custom
* images.
* An image is a collection of files you use to create or rebuild a server. Operators provide
* pre-built OS images by default. You may also create custom images.
*
* @author Jeremy Daggett
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Images-d1e4427.html"
* @see <a href= "http://docs.openstack.org/api/openstack-compute/1.1/content/Images-d1e4427.html"
* />
*/
public class Image extends Resource {
/**
* In-flight images will have the status attribute set to SAVING and the conditional progress
* element (0-100% completion) will also be returned. Other possible values for the status
* attribute include: UNKNOWN, ACTIVE, SAVING, ERROR, and DELETED. Images with an ACTIVE status
* are available for install. The optional minDisk and minRam attributes set the minimum disk and
* RAM requirements needed to create a server with the image.
*
* @author Adrian Cole
*/
public static enum Status {
UNRECOGNIZED, UNKNOWN, ACTIVE, SAVING, ERROR, DELETED;
public String value() {
return name();
}
public static Status fromValue(String v) {
try {
return valueOf(v);
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Builder builder() {
return new Builder();
}
@ -55,12 +82,12 @@ public class Image extends Resource {
private Date created;
private String tenantId;
private String userId;
private ImageStatus status;
private Status status;
private int progress;
private int minDisk;
private int minRam;
private Resource server;
private Map<String, String> metadata = Maps.newHashMap();
private Map<String, String> metadata = Maps.newLinkedHashMap();
public Builder updated(Date updated) {
this.updated = updated;
@ -82,7 +109,7 @@ public class Image extends Resource {
return this;
}
public Builder status(ImageStatus status) {
public Builder status(Status status) {
this.status = status;
return this;
}
@ -114,12 +141,12 @@ public class Image extends Resource {
public Image build() {
return new Image(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam,
server, metadata);
server, metadata);
}
public Builder fromImage(Image in) {
return fromResource(in).status(in.getStatus()).updated(in.getUpdated()).created(in.getCreated())
.progress(in.getProgress()).server(in.getServer()).metadata(in.getMetadata());
return fromResource(in).status(in.getStatus()).updated(in.getUpdated()).created(in.getCreated()).progress(
in.getProgress()).server(in.getServer()).metadata(in.getMetadata());
}
/**
@ -155,21 +182,21 @@ public class Image extends Resource {
}
}
private Date updated;
private Date created;
private final Date updated;
private final Date created;
@SerializedName("tenant_id")
private String tenantId;
private final String tenantId;
@SerializedName("user_id")
private String userId;
private ImageStatus status;
private int progress;
private int minDisk;
private int minRam;
private Resource server;
private Map<String, String> metadata = Maps.newHashMap();
private final String userId;
private final Status status;
private final int progress;
private final int minDisk;
private final int minRam;
private final Resource server;
private final Map<String, String> metadata;
protected Image(String id, String name, Set<Link> links, Date updated, Date created, String tenantId, String userId,
ImageStatus status, int progress, int minDisk, int minRam, Resource server, Map<String, String> metadata) {
Status status, int progress, int minDisk, int minRam, Resource server, Map<String, String> metadata) {
super(id, name, links);
this.updated = updated;
this.created = created;
@ -180,7 +207,7 @@ public class Image extends Resource {
this.minDisk = minDisk;
this.minRam = minRam;
this.server = server;
this.metadata = metadata;
this.metadata = ImmutableMap.<String, String> copyOf(metadata);
}
public Date getUpdated() {
@ -199,7 +226,7 @@ public class Image extends Resource {
return this.userId;
}
public ImageStatus getStatus() {
public Status getStatus() {
return this.status;
}
@ -220,15 +247,16 @@ public class Image extends Resource {
}
public Map<String, String> getMetadata() {
return this.metadata;
// in case this was assigned in gson
return ImmutableMap.copyOf(Maps.filterValues(this.metadata, Predicates.notNull()));
}
@Override
public String toString() {
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("updated", updated)
.add("created", created).add("tenantId", tenantId).add("userId", userId).add("status", status)
.add("progress", progress).add("minDisk", minDisk).add("minRam", minRam).add("server", server)
.add("metadata", metadata).toString();
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("updated", updated).add(
"created", created).add("tenantId", tenantId).add("userId", userId).add("status", status).add(
"progress", progress).add("minDisk", minDisk).add("minRam", minRam).add("server", server).add(
"metadata", metadata).toString();
}
}

View File

@ -26,22 +26,19 @@ import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.nova.v1_1.domain.Address.Type;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
import org.jclouds.util.InetAddresses2;
import org.jclouds.util.Multimaps2;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
@ -57,6 +54,47 @@ import com.google.gson.annotations.SerializedName;
* />
*/
public class Server extends Resource {
/**
* Servers contain a status attribute that can be used as an indication of the current server
* state. Servers with an ACTIVE status are available for use.
*
* Other possible values for the status attribute include: BUILD, REBUILD, SUSPENDED, RESIZE,
* VERIFY_RESIZE, REVERT_RESIZE, PASSWORD, REBOOT, HARD_REBOOT, DELETED, UNKNOWN, and ERROR.
*
* @author Adrian Cole
*/
public static enum Status {
ACTIVE(NodeState.RUNNING), BUILD(NodeState.PENDING), REBUILD(NodeState.PENDING), SUSPENDED(NodeState.SUSPENDED), RESIZE(
NodeState.PENDING), VERIFY_RESIZE(NodeState.PENDING), REVERT_RESIZE(NodeState.PENDING), PASSWORD(
NodeState.PENDING), REBOOT(NodeState.PENDING), HARD_REBOOT(NodeState.PENDING), DELETED(
NodeState.TERMINATED), UNKNOWN(NodeState.UNRECOGNIZED), ERROR(NodeState.ERROR), UNRECOGNIZED(
NodeState.UNRECOGNIZED);
private final NodeState nodeState;
Status(NodeState nodeState) {
this.nodeState = nodeState;
}
public String value() {
return name();
}
public static Status fromValue(String v) {
try {
return valueOf(v.replaceAll("\\(.*", ""));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
public NodeState getNodeState() {
return nodeState;
}
}
public static Builder builder() {
return new Builder();
}
@ -74,7 +112,7 @@ public class Server extends Resource {
private String hostId;
private String accessIPv4;
private String accessIPv6;
private ServerStatus status;
private Status status;
private String configDrive;
private Resource image;
private Resource flavor;
@ -151,7 +189,7 @@ public class Server extends Resource {
/**
* @see Server#getStatus()
*/
public Builder status(ServerStatus status) {
public Builder status(Status status) {
this.status = status;
return this;
}
@ -309,7 +347,7 @@ public class Server extends Resource {
protected final String hostId;
protected final String accessIPv4;
protected final String accessIPv6;
protected final ServerStatus status;
protected final Status status;
protected final Resource image;
protected final Resource flavor;
protected final String adminPass;
@ -323,8 +361,8 @@ public class Server extends Resource {
protected Server(String id, String name, Set<Link> links, @Nullable String uuid, String tenantId, String userId,
Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
@Nullable String accessIPv6, ServerStatus status, @Nullable String configDrive, Resource image,
Resource flavor, String adminPass, @Nullable String keyName, Multimap<Address.Type, Address> addresses,
@Nullable String accessIPv6, Status status, @Nullable String configDrive, Resource image, Resource flavor,
String adminPass, @Nullable String keyName, Multimap<Address.Type, Address> addresses,
Map<String, String> metadata) {
super(id, name, links);
this.uuid = uuid; // TODO: see what version this came up in
@ -390,7 +428,7 @@ public class Server extends Resource {
return Strings.emptyToNull(this.accessIPv6);
}
public ServerStatus getStatus() {
public Status getStatus() {
return this.status;
}
@ -408,7 +446,8 @@ public class Server extends Resource {
}
public Map<String, String> getMetadata() {
return this.metadata;
// in case this was assigned in gson
return ImmutableMap.copyOf(Maps.filterValues(this.metadata, Predicates.notNull()));
}
/**
@ -439,29 +478,7 @@ public class Server extends Resource {
* @return the ip addresses assigned to the server
*/
public Multimap<Type, Address> getAddresses() {
ImmutableSetMultimap.Builder<Type, Address> returnMapBuilder = new ImmutableSetMultimap.Builder<Type, Address>();
Set<Address> publicAddresses = addresses.get(Address.Type.PUBLIC);
Set<Address> privateAddresses = addresses.get(Address.Type.PRIVATE);
if (publicAddresses != null) {
returnMapBuilder.putAll(Address.Type.PUBLIC, Iterables.filter(publicAddresses, Predicates
.not(IsPrivateAddress.INSTANCE)));
}
if (privateAddresses != null) {
returnMapBuilder.putAll(Address.Type.PRIVATE, Iterables.filter(privateAddresses, IsPrivateAddress.INSTANCE));
returnMapBuilder.putAll(Address.Type.PUBLIC, Iterables.filter(privateAddresses, Predicates
.not(IsPrivateAddress.INSTANCE)));
}
ImmutableSetMultimap<Type, Address> returnMap = returnMapBuilder.build();
return returnMap.size() > 0 ? returnMap : Multimaps2.fromOldSchool(addresses);
}
private static enum IsPrivateAddress implements Predicate<Address> {
INSTANCE;
public boolean apply(Address in) {
return InetAddresses2.IsPrivateIPAddress.INSTANCE.apply(in.getAddr());
}
return Multimaps2.fromOldSchool(addresses);
}
/**

View File

@ -1,61 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.domain;
import org.jclouds.compute.domain.NodeState;
/**
* Servers contain a status attribute that can be used as an indication of the
* current server state. Servers with an ACTIVE status are available for use.
*
* Other possible values for the status attribute include: BUILD, REBUILD,
* SUSPENDED, RESIZE, VERIFY_RESIZE, REVERT_RESIZE, PASSWORD, REBOOT,
* HARD_REBOOT, DELETED, UNKNOWN, and ERROR.
*
* @author Adrian Cole
*/
public enum ServerStatus {
ACTIVE(NodeState.RUNNING), BUILD(NodeState.PENDING), REBUILD(NodeState.PENDING), SUSPENDED(NodeState.SUSPENDED), RESIZE(
NodeState.PENDING), VERIFY_RESIZE(NodeState.PENDING), REVERT_RESIZE(NodeState.PENDING), PASSWORD(
NodeState.PENDING), REBOOT(NodeState.PENDING), HARD_REBOOT(NodeState.PENDING), DELETED(NodeState.TERMINATED), UNKNOWN(
NodeState.UNRECOGNIZED), ERROR(NodeState.ERROR), UNRECOGNIZED(NodeState.UNRECOGNIZED);
private final NodeState nodeState;
ServerStatus(NodeState nodeState) {
this.nodeState = nodeState;
}
public String value() {
return name();
}
public static ServerStatus fromValue(String v) {
try {
return valueOf(v.replaceAll("\\(.*",""));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
public NodeState getNodeState() {
return nodeState;
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Preconditions.checkNotNull;
@ -26,15 +26,15 @@ import org.jclouds.openstack.nova.v1_1.domain.Image;
* @author Adrian Cole
*/
public class ImageInZone extends ZoneAndId {
protected final Image server;
protected final Image image;
public ImageInZone(Image server, String zoneId) {
super(zoneId, checkNotNull(server, "server").getId());
this.server = server;
public ImageInZone(Image image, String zoneId) {
super(zoneId, checkNotNull(image, "image").getId());
this.image = image;
}
public Image getImage() {
return server;
return image;
}
// superclass hashCode/equals are good enough, and help us use ZoneAndId and ImageInZone
@ -42,7 +42,7 @@ public class ImageInZone extends ZoneAndId {
@Override
public String toString() {
return "[server=" + server + ", zoneId=" + zoneId + "]";
return "[image=" + image + ", zoneId=" + zoneId + "]";
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -16,12 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.base.Objects.ToStringHelper;
@ -33,6 +34,25 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole
*/
public class ZoneAndName {
public final static Function<ZoneAndName, String> NAME_FUNCTION = new Function<ZoneAndName, String>(){
@Override
public String apply(ZoneAndName input) {
return input.getName();
}
};
public final static Function<ZoneAndName, String> ZONE_FUNCTION = new Function<ZoneAndName, String>(){
@Override
public String apply(ZoneAndName input) {
return input.getZone();
}
};
public static ZoneAndName fromSlashEncoded(String name) {
Iterable<String> parts = Splitter.on('/').split(checkNotNull(name, "name"));
checkArgument(Iterables.size(parts) == 2, "name must be in format zoneId/name");

View File

@ -16,29 +16,29 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.domain;
package org.jclouds.openstack.nova.v1_1.domain.zonescoped;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
public class ZoneSecurityGroupNameAndPorts extends ZoneAndName {
protected final List<Integer> ports;
protected final Set<Integer> ports;
public ZoneSecurityGroupNameAndPorts(String zoneId, String name, List<Integer> ports) {
public ZoneSecurityGroupNameAndPorts(String zoneId, String name, Iterable<Integer> ports) {
super(zoneId, name);
this.ports = ImmutableList.<Integer> copyOf(checkNotNull(ports, "ports"));
this.ports = ImmutableSet.<Integer> copyOf(checkNotNull(ports, "ports"));
}
public List<Integer> getPorts() {
public Set<Integer> getPorts() {
return ports;
}

View File

@ -55,6 +55,8 @@ public class NovaErrorHandler implements HttpErrorHandler {
exception = new InsufficientResourcesException(message, exception);
else if (message.indexOf("has no fixed_ips") != -1)
exception = new IllegalStateException(message, exception);
else if (message.indexOf("already exists") != -1)
exception = new IllegalStateException(message, exception);
break;
case 401:
case 403:

View File

@ -29,9 +29,9 @@ import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import org.jclouds.rest.ResourceNotFoundException;

View File

@ -0,0 +1,57 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.openstack.nova.v1_1.domain.Image;
import org.jclouds.openstack.nova.v1_1.domain.Image.Status;
import com.google.common.base.Predicate;
/**
* Predicates handy when working with Images
*
* @author Adrian Cole
*/
public class ImagePredicates {
/**
* matches status of the given image
*
* @param status
* @return predicate that matches status
*/
public static Predicate<Image> statusEquals(final Status status) {
checkNotNull(status, "status must be defined");
return new Predicate<Image>() {
@Override
public boolean apply(Image image) {
return status.equals(image.getStatus());
}
@Override
public String toString() {
return "statusEquals(" + status + ")";
}
};
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import com.google.common.base.Predicate;
/**
* Predicates handy when working with SecurityGroups
*
* @author Adrian Cole
*/
public class SecurityGroupPredicates {
/**
* matches name of the given extension
*
* @param name
* @return predicate that matches name
*/
public static Predicate<SecurityGroup> nameEquals(final String name) {
checkNotNull(name, "name must be defined");
return new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup ext) {
return name.equals(ext.getName());
}
@Override
public String toString() {
return "nameEquals(" + name + ")";
}
};
}
}

View File

@ -65,6 +65,17 @@ public class NovaErrorHandlerTest {
IllegalStateException.class);
}
@Test
public void test400MakesIllegalStateExceptionOnAlreadyExists() {
assertCodeMakes(
"POST",
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/37936628937291/servers"),
400,
"HTTP/1.1 400 Bad Request",
"{\"badRequest\": {\"message\": \"Server with the name 'test' already exists\", \"code\": 400}}",
IllegalStateException.class);
}
@Test
public void test400MakesInsufficientResourcesExceptionOnQuotaExceeded() {

View File

@ -29,8 +29,8 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.compute.domain.ServerInZone;
import org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ServerInZone;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaComputeServiceContextExpectTest;
import org.testng.annotations.Test;

View File

@ -46,7 +46,7 @@ import com.google.common.collect.ImmutableSet;
* @author Matt Stephenson
*/
@Test(groups = "unit", testName = "AllocateAndAddFloatingIpToNodeTest")
public class AllocateAndAddFloatingIpToNodeTest extends BaseNovaComputeServiceExpectTest {
public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeServiceExpectTest {
final Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("openstack-nova").description(
"openstack-nova").build();
final Location zone = new LocationBuilder().id("az-1.region-a.geo-1").description("az-1.region-a.geo-1").scope(

View File

@ -29,8 +29,8 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.openstack.nova.v1_1.compute.domain.FlavorInZone;
import org.jclouds.openstack.nova.v1_1.domain.Flavor;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.FlavorInZone;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;

View File

@ -30,8 +30,8 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.openstack.nova.v1_1.compute.domain.ImageInZone;
import org.jclouds.openstack.nova.v1_1.domain.Image;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ImageInZone;
import org.testng.annotations.Test;
import com.google.common.base.Function;

View File

@ -0,0 +1,108 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.compute.functions;
import static org.testng.Assert.assertEquals;
import java.util.Map;
import java.util.Set;
import org.easymock.classextension.EasyMock;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ServerInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.parse.ParseCreatedServerTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseServerTest;
import org.testng.annotations.Test;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
/**
*
*
* @author Adrian Cole
*/
@Test(testName = "OrphanedGroupsByZoneIdTest")
public class OrphanedGroupsByZoneIdTest {
Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("openstack-nova").description(
"openstack-nova").build();
Location zone = new LocationBuilder().id("az-1.region-a.geo-1").description("az-1.region-a.geo-1").scope(
LocationScope.ZONE).parent(provider).build();
Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
.<String, Location> of("az-1.region-a.geo-1", zone));
@Test
public void testWhenComputeServiceSaysAllNodesAreDeadBothGroupsAreReturned() {
ServerInZone withoutHost = new ServerInZone(new ParseCreatedServerTest().expected(), "az-1.region-a.geo-1");
ServerInZone withHost = new ServerInZone(new ParseServerTest().expected(), "az-1.region-a.geo-1");
LoadingCache<ZoneAndId, Iterable<String>> mockLoadingCache = EasyMock.createMock(LoadingCache.class);
EasyMock.expect(mockLoadingCache.getUnchecked(withoutHost)).andReturn(ImmutableSet.<String> of());
EasyMock.expect(mockLoadingCache.getUnchecked(withHost)).andReturn(ImmutableSet.<String> of());
EasyMock.replay(mockLoadingCache);
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex, Suppliers
.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of()), Suppliers
.<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()), mockLoadingCache);
Set<? extends NodeMetadata> set = ImmutableSet.of(converter.apply(withHost), converter.apply(withoutHost));
assertEquals(new OrphanedGroupsByZoneId(Predicates.<ZoneAndName> alwaysTrue()).apply(set), ImmutableMultimap
.<String, String> builder().putAll("az-1.region-a.geo-1", "sample", "test").build());
EasyMock.verify(mockLoadingCache);
}
@Test
public void testWhenComputeServiceSaysAllNodesAreDeadNoGroupsAreReturned() {
ServerInZone withoutHost = new ServerInZone(new ParseCreatedServerTest().expected(), "az-1.region-a.geo-1");
ServerInZone withHost = new ServerInZone(new ParseServerTest().expected(), "az-1.region-a.geo-1");
LoadingCache<ZoneAndId, Iterable<String>> mockLoadingCache = EasyMock.createMock(LoadingCache.class);
EasyMock.expect(mockLoadingCache.getUnchecked(withoutHost)).andReturn(ImmutableSet.<String> of());
EasyMock.expect(mockLoadingCache.getUnchecked(withHost)).andReturn(ImmutableSet.<String> of());
EasyMock.replay(mockLoadingCache);
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex, Suppliers
.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of()), Suppliers
.<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()), mockLoadingCache);
Set<? extends NodeMetadata> set = ImmutableSet.of(converter.apply(withHost), converter.apply(withoutHost));
assertEquals(new OrphanedGroupsByZoneId(Predicates.<ZoneAndName> alwaysFalse()).apply(set), ImmutableMultimap
.<String, String> of());
EasyMock.verify(mockLoadingCache);
}
}

View File

@ -35,9 +35,9 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.openstack.nova.v1_1.compute.domain.ServerInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ServerInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.parse.ParseCreatedServerTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseServerTest;
import org.testng.annotations.Test;
@ -134,8 +134,8 @@ public class ServerInZoneToNodeMetadataTest {
assertEquals(convertedNodeMetadata.getPrivateAddresses(), ImmutableSet.of("10.176.42.16"));
assertNotNull(convertedNodeMetadata.getPublicAddresses());
assertEquals(convertedNodeMetadata.getPublicAddresses(), ImmutableSet.of("67.23.10.132", "::babe:67.23.10.132",
"67.23.10.131", "::babe:4317:0A83", "::babe:10.176.42.16"));
// note jclouds doesn't yet support ipv6 b/c not tested yet
assertEquals(convertedNodeMetadata.getPublicAddresses(), ImmutableSet.of("67.23.10.132", "67.23.10.131"));
assertNotNull(convertedNodeMetadata.getUserMetadata());
assertEquals(convertedNodeMetadata.getUserMetadata(), ImmutableMap.<String, String> of("Server Label",

View File

@ -0,0 +1,145 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.compute.loaders;
import static org.easymock.EasyMock.createMock;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.atomic.AtomicReference;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true, testName = "FindSecurityGroupOrCreateTest")
public class FindSecurityGroupOrCreateTest {
@Test
public void testWhenNotFoundCreatesANewSecurityGroup() throws Exception {
Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone = Predicates.alwaysFalse();
SecurityGroupInZone securityGroupInZone = createMock(SecurityGroupInZone.class);
ZoneSecurityGroupNameAndPorts input = new ZoneSecurityGroupNameAndPorts("zone", "groupName", ImmutableSet
.<Integer> of(22, 8080));
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator = Functions.forMap(ImmutableMap
.<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> of(input, securityGroupInZone));
FindSecurityGroupOrCreate parser = new FindSecurityGroupOrCreate(
returnSecurityGroupExistsInZone, groupCreator);
assertEquals(parser.load(input), securityGroupInZone);
}
@Test
public void testWhenFoundReturnsSecurityGroupFromAtomicReferenceValueUpdatedDuringPredicateCheck() throws Exception {
final SecurityGroupInZone securityGroupInZone = createMock(SecurityGroupInZone.class);
Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone = new Predicate<AtomicReference<ZoneAndName>>(){
@Override
public boolean apply(AtomicReference<ZoneAndName> input) {
input.set(securityGroupInZone);
return true;
}
};
ZoneAndName input = ZoneAndName.fromZoneAndName("zone", "groupName");
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator = new Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>() {
@Override
public SecurityGroupInZone apply(ZoneSecurityGroupNameAndPorts input) {
assert false;
return null;
}
};
FindSecurityGroupOrCreate parser = new FindSecurityGroupOrCreate(
returnSecurityGroupExistsInZone, groupCreator);
assertEquals(parser.load(input), securityGroupInZone);
}
@Test(expectedExceptions = IllegalStateException.class)
public void testWhenFoundPredicateMustUpdateAtomicReference() throws Exception {
Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone = Predicates.alwaysTrue();
ZoneAndName input = ZoneAndName.fromZoneAndName("zone", "groupName");
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator = new Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>() {
@Override
public SecurityGroupInZone apply(ZoneSecurityGroupNameAndPorts input) {
assert false;
return null;
}
};
FindSecurityGroupOrCreate parser = new FindSecurityGroupOrCreate(
returnSecurityGroupExistsInZone, groupCreator);
parser.load(input);
}
@Test(expectedExceptions = IllegalStateException.class)
public void testWhenNotFoundInputMustBeZoneSecurityGroupNameAndPorts() throws Exception {
Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone = Predicates.alwaysFalse();
ZoneAndName input = ZoneAndName.fromZoneAndName("zone", "groupName");
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator = new Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>() {
@Override
public SecurityGroupInZone apply(ZoneSecurityGroupNameAndPorts input) {
assert false;
return null;
}
};
FindSecurityGroupOrCreate parser = new FindSecurityGroupOrCreate(
returnSecurityGroupExistsInZone, groupCreator);
parser.load(input);
}
}

View File

@ -26,8 +26,8 @@ import static org.testng.Assert.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import org.testng.annotations.Test;

View File

@ -28,7 +28,7 @@ import java.util.Set;
import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerStatus;
import org.jclouds.openstack.nova.v1_1.domain.Server.Status;
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
@ -136,7 +136,7 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
private void blockUntilServerActive(String serverId, ServerClient client) throws InterruptedException {
Server currentDetails = null;
for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.ACTIVE; currentDetails = client
for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != Status.ACTIVE; currentDetails = client
.getServer(serverId)) {
System.out.printf("blocking on status active%n%s%n", currentDetails);
Thread.sleep(5 * 1000);

View File

@ -25,9 +25,9 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v1_1.compute.functions.CreateSecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseComputeServiceTypicalSecurityGroupTest;
import org.testng.annotations.Test;
@ -35,32 +35,32 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableMap.Builder;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "CreateSecurityGroupInZoneExpectTest")
public class CreateSecurityGroupInZoneExpectTest extends BaseNovaClientExpectTest {
@Test(groups = "unit", testName = "CreateSecurityGroupIfNeededTest")
public class CreateSecurityGroupIfNeededTest extends BaseNovaClientExpectTest {
HttpRequest createSecurityGroup = HttpRequest.builder().method("POST").endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build())
.payload(
payloadFromStringWithContentType(
"{\"security_group\":{\"name\":\"jclouds#mygroup\",\"description\":\"jclouds#mygroup\"}}",
"application/json")).build();
public void testUpdateReferenceWhenSecurityGroupListContainsGroupName() throws Exception {
public void testCreateNewGroup() throws Exception {
Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
builder.put(keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess);
builder.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
HttpRequest createSecurityGroup = HttpRequest.builder().method("POST").endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build())
.payload(
payloadFromStringWithContentType(
"{\"security_group\":{\"name\":\"jclouds#mygroup\",\"description\":\"jclouds#mygroup\"}}",
"application/json")).build();
int groupId = 2769;
HttpResponse createSecurityGroupResponse = HttpResponse.builder().statusCode(200)
.payload(
payloadFromStringWithContentType(
@ -68,7 +68,7 @@ public class CreateSecurityGroupInZoneExpectTest extends BaseNovaClientExpectTes
"application/json; charset=UTF-8")).build();
builder.put(createSecurityGroup, createSecurityGroupResponse);
int ruleId = 10331;
for (int port : ImmutableList.of(22,8080)){
@ -110,25 +110,61 @@ public class CreateSecurityGroupInZoneExpectTest extends BaseNovaClientExpectTes
}
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-security-groups/"+groupId)).headers(
URI.create("https://compute.north.host/v1.1/3456/os-security-groups/" + groupId)).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse getSecurityGroupResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_computeservice_typical.json")).build();
builder.put(getSecurityGroup, getSecurityGroupResponse);
NovaClient clientWhenSecurityGroupsExist = requestsSendResponses(builder.build());
NovaClient clientCanCreateSecurityGroup = requestsSendResponses(builder.build());
CreateSecurityGroupInZone fn = new CreateSecurityGroupInZone(clientWhenSecurityGroupsExist);
CreateSecurityGroupIfNeeded fn = new CreateSecurityGroupIfNeeded(clientCanCreateSecurityGroup);
// we can find it
assertEquals(fn.apply(
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds#mygroup", ImmutableList.of(22, 8080)))
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds#mygroup", ImmutableSet.of(22, 8080)))
.toString(), new SecurityGroupInZone(new ParseComputeServiceTypicalSecurityGroupTest().expected(),
"az-1.region-a.geo-1").toString());
}
public void testReturnExistingGroupOnAlreadyExists() throws Exception {
Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
builder.put(keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess);
builder.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
HttpResponse createSecurityGroupResponse = HttpResponse.builder().statusCode(400)
.payload(
payloadFromStringWithContentType(
"{\"badRequest\": {\"message\": \"Security group test already exists\", \"code\": 400}}",
"application/json; charset=UTF-8")).build();
builder.put(createSecurityGroup, createSecurityGroupResponse);
HttpRequest listSecurityGroups = HttpRequest.builder().method("GET").endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse listSecurityGroupsResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_list_details_computeservice_typical.json")).build();
builder.put(listSecurityGroups, listSecurityGroupsResponse);
NovaClient clientWhenSecurityGroupsExist = requestsSendResponses(builder.build());
CreateSecurityGroupIfNeeded fn = new CreateSecurityGroupIfNeeded(clientWhenSecurityGroupsExist);
// we can find it
assertEquals(fn.apply(
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds#mygroup", ImmutableSet.of(22, 8080)))
.toString(), new SecurityGroupInZone(new ParseComputeServiceTypicalSecurityGroupTest().expected(),
"az-1.region-a.geo-1").toString());
}
}

View File

@ -28,8 +28,8 @@ import java.util.concurrent.atomic.AtomicReference;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.domain.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupListTest;
import org.jclouds.openstack.nova.v1_1.predicates.FindSecurityGroupWithNameAndReturnTrue;

View File

@ -31,7 +31,7 @@ import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerStatus;
import org.jclouds.openstack.nova.v1_1.domain.Server.Status;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
@ -62,7 +62,7 @@ public class ParseCreatedServerTest extends BaseItemParserTest<Server> {
.name("test-e92")
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-03-19T06:21:13Z"))
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-03-19T06:21:13Z"))
.status(ServerStatus.BUILD)
.status(Status.BUILD)
.adminPass("ZWuHcmTMQ7eXoHeM")
.image(
Resource

View File

@ -27,11 +27,11 @@ import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Image;
import org.jclouds.openstack.nova.v1_1.domain.ImageStatus;
import org.jclouds.openstack.nova.v1_1.domain.Image.Status;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
@ -63,7 +63,7 @@ public class ParseImageTest extends BaseItemParserTest<Image> {
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-08-10T12:00:00Z"))
.tenantId("12345")
.userId("joe")
.status(ImageStatus.SAVING)
.status(Status.SAVING)
.progress(80)
.minDisk(5)
.minRam(256)

View File

@ -27,12 +27,12 @@ import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerStatus;
import org.jclouds.openstack.nova.v1_1.domain.Server.Status;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
@ -66,7 +66,7 @@ public class ParseServerTest extends BaseItemParserTest<Server> {
.hostId("e4d909c290d0fb1ca068ffaddf22cbd0")
.accessIPv4("67.23.10.132")
.accessIPv6("::babe:67.23.10.132")
.status(ServerStatus.BUILD)
.status(Status.BUILD)
.image(
Resource
.builder()

View File

@ -0,0 +1,46 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.predicates;
import static org.jclouds.openstack.nova.v1_1.predicates.ImagePredicates.statusEquals;
import org.jclouds.openstack.nova.v1_1.domain.Image;
import org.jclouds.openstack.nova.v1_1.domain.Image.Status;
import org.jclouds.openstack.nova.v1_1.parse.ParseImageTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ImagePredicatesTest")
public class ImagePredicatesTest {
Image ref = new ParseImageTest().expected();
@Test
public void teststatusEqualsWhenEqual() {
assert statusEquals(Status.SAVING).apply(ref);
}
@Test
public void teststatusEqualsWhenNotEqual() {
assert !statusEquals(Status.DELETED).apply(ref);
}
}

View File

@ -0,0 +1,44 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.predicates;
import static org.jclouds.openstack.nova.v1_1.predicates.SecurityGroupPredicates.nameEquals;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "SecurityGroupPredicatesTest")
public class SecurityGroupPredicatesTest {
SecurityGroup ref = SecurityGroup.builder().name("jclouds").description("description").build();
@Test
public void testnameEqualsWhenEqual() {
assert nameEquals("jclouds").apply(ref);
}
@Test
public void testnameEqualsWhenNotEqual() {
assert !nameEquals("foo").apply(ref);
}
}

View File

@ -0,0 +1,53 @@
{
"security_groups":[
{
"rules": [{
"from_port": 22,
"group": {},
"ip_protocol": "tcp",
"to_port": 22,
"parent_group_id": 2769,
"ip_range": {
"cidr": "0.0.0.0/0"
},
"id": 10331
}, {
"from_port": 22,
"group": {
"tenant_id": "37936628937291",
"name": "jclouds#mygroup"
},
"ip_protocol": "tcp",
"to_port": 22,
"parent_group_id": 2769,
"ip_range": {},
"id": 10332
}, {
"from_port": 8080,
"group": {},
"ip_protocol": "tcp",
"to_port": 8080,
"parent_group_id": 2769,
"ip_range": {
"cidr": "0.0.0.0/0"
},
"id": 10333
}, {
"from_port": 8080,
"group": {
"tenant_id": "37936628937291",
"name": "jclouds#mygroup"
},
"ip_protocol": "tcp",
"to_port": 8080,
"parent_group_id": 2769,
"ip_range": {},
"id": 10334
}],
"tenant_id": "37936628937291",
"id": 2769,
"name": "jclouds#mygroup",
"description": "jclouds#mygroup"
}
]
}