JCLOUDS-267. Add SecurityGroupExtension support for Nova.

This commit is contained in:
Andrew Bayer 2013-09-13 10:31:02 -07:00
parent e29cdb142a
commit 389ba6c94a
19 changed files with 1467 additions and 59 deletions

View File

@ -40,6 +40,7 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.domain.Location;
@ -49,10 +50,12 @@ import org.jclouds.net.domain.IpPermission;
import org.jclouds.openstack.nova.v2_0.compute.NovaComputeService;
import org.jclouds.openstack.nova.v2_0.compute.NovaComputeServiceAdapter;
import org.jclouds.openstack.nova.v2_0.compute.extensions.NovaImageExtension;
import org.jclouds.openstack.nova.v2_0.compute.extensions.NovaSecurityGroupExtension;
import org.jclouds.openstack.nova.v2_0.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.openstack.nova.v2_0.compute.functions.FlavorInZoneToHardware;
import org.jclouds.openstack.nova.v2_0.compute.functions.ImageInZoneToImage;
import org.jclouds.openstack.nova.v2_0.compute.functions.ImageToOperatingSystem;
import org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupInZoneToSecurityGroup;
import org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupToSecurityGroup;
import org.jclouds.openstack.nova.v2_0.compute.functions.OrphanedGroupsByZoneId;
import org.jclouds.openstack.nova.v2_0.compute.functions.SecurityGroupRuleToIpPermission;
@ -119,6 +122,9 @@ public class NovaComputeServiceContextModule extends
bind(new TypeLiteral<Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup>>() {
}).to(NovaSecurityGroupToSecurityGroup.class);
bind(new TypeLiteral<Function<SecurityGroupInZone, SecurityGroup>>() {
}).to(NovaSecurityGroupInZoneToSecurityGroup.class);
bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Multimap<String, String>>>() {
}).to(OrphanedGroupsByZoneId.class);
@ -153,6 +159,9 @@ public class NovaComputeServiceContextModule extends
bind(new TypeLiteral<ImageExtension>() {
}).to(NovaImageExtension.class);
bind(new TypeLiteral<SecurityGroupExtension>() {
}).to(NovaSecurityGroupExtension.class);
}
@Override
@ -187,7 +196,7 @@ public class NovaComputeServiceContextModule extends
@Provides
@Singleton
@Named(TIMEOUT_SECURITYGROUP_PRESENT)
@Named("SECURITYGROUP_PRESENT")
protected Predicate<AtomicReference<ZoneAndName>> securityGroupEventualConsistencyDelay(
FindSecurityGroupWithNameAndReturnTrue in,
@Named(TIMEOUT_SECURITYGROUP_PRESENT) long msDelay) {
@ -269,4 +278,9 @@ public class NovaComputeServiceContextModule extends
protected Optional<ImageExtension> provideImageExtension(Injector i) {
return Optional.of(i.getInstance(ImageExtension.class));
}
@Override
protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) {
return Optional.of(i.getInstance(SecurityGroupExtension.class));
}
}

View File

@ -0,0 +1,422 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.compute.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.nameIn;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleCidr;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleEndPort;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleGroup;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleProtocol;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleStartPort;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.location.Zone;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.domain.Ingress;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.ServerWithSecurityGroups;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsApi;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s. Implementation
* is optional by providers.
*
* @author Andrew Bayer
*/
public class NovaSecurityGroupExtension implements SecurityGroupExtension {
protected final NovaApi api;
protected final ListeningExecutorService userExecutor;
protected final Supplier<Set<String>> zoneIds;
protected final Function<SecurityGroupInZone, SecurityGroup> groupConverter;
protected final LoadingCache<ZoneAndName, SecurityGroupInZone> groupCreator;
protected final GroupNamingConvention.Factory namingConvention;
@Inject
public NovaSecurityGroupExtension(NovaApi api,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
@Zone Supplier<Set<String>> zoneIds,
Function<SecurityGroupInZone, SecurityGroup> groupConverter,
LoadingCache<ZoneAndName, SecurityGroupInZone> groupCreator,
GroupNamingConvention.Factory namingConvention) {
this.api = checkNotNull(api, "api");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.zoneIds = checkNotNull(zoneIds, "zoneIds");
this.groupConverter = checkNotNull(groupConverter, "groupConverter");
this.groupCreator = checkNotNull(groupCreator, "groupCreator");
this.namingConvention = checkNotNull(namingConvention, "namingConvention");
}
@Override
public Set<SecurityGroup> listSecurityGroups() {
Iterable<? extends SecurityGroupInZone> rawGroups = pollSecurityGroups();
Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
groupConverter);
return ImmutableSet.copyOf(groups);
}
@Override
public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) {
String zone = location.getId();
if (zone == null) {
return ImmutableSet.of();
}
return listSecurityGroupsInLocation(zone);
}
public Set<SecurityGroup> listSecurityGroupsInLocation(String zone) {
Iterable<? extends SecurityGroupInZone> rawGroups = pollSecurityGroupsByZone(zone);
Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
groupConverter);
return ImmutableSet.copyOf(groups);
}
@Override
public Set<SecurityGroup> listSecurityGroupsForNode(String id) {
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(checkNotNull(id, "id"));
String zone = zoneAndId.getZone();
String instanceId = zoneAndId.getId();
Optional<? extends ServerWithSecurityGroupsApi> serverApi = api.getServerWithSecurityGroupsExtensionForZone(zone);
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!serverApi.isPresent() || !sgApi.isPresent()) {
return ImmutableSet.of();
}
ServerWithSecurityGroups instance = serverApi.get().get(instanceId);
if (instance == null) {
return ImmutableSet.of();
}
Set<String> groupNames = instance.getSecurityGroupNames();
Set<? extends SecurityGroupInZone> rawGroups =
sgApi.get().list().filter(nameIn(groupNames)).transform(groupToGroupInZone(zone)).toSet();
return ImmutableSet.copyOf(transform(filter(rawGroups, notNull()), groupConverter));
}
@Override
public SecurityGroup getSecurityGroupById(String id) {
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(checkNotNull(id, "id"));
String zone = zoneAndId.getZone();
String groupId = zoneAndId.getId();
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!sgApi.isPresent()) {
return null;
}
SecurityGroupInZone rawGroup = new SecurityGroupInZone(sgApi.get().get(groupId), zone);
return groupConverter.apply(rawGroup);
}
@Override
public SecurityGroup createSecurityGroup(String name, Location location) {
String zone = location.getId();
if (zone == null) {
return null;
}
return createSecurityGroup(name, zone);
}
public SecurityGroup createSecurityGroup(String name, String zone) {
String markerGroup = namingConvention.create().sharedNameForGroup(name);
ZoneSecurityGroupNameAndPorts zoneAndName = new ZoneSecurityGroupNameAndPorts(zone, markerGroup, ImmutableSet.<Integer> of());
SecurityGroupInZone rawGroup = groupCreator.apply(zoneAndName);
return groupConverter.apply(rawGroup);
}
@Override
public boolean removeSecurityGroup(String id) {
checkNotNull(id, "id");
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(id);
String zone = zoneAndId.getZone();
String groupId = zoneAndId.getId();
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!sgApi.isPresent()) {
return false;
}
if (sgApi.get().get(groupId) == null) {
return false;
}
sgApi.get().delete(groupId);
// TODO: test this clear happens
groupCreator.invalidate(new ZoneSecurityGroupNameAndPorts(zone, groupId, ImmutableSet.<Integer> of()));
return true;
}
@Override
public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
String zone = group.getLocation().getId();
String id = group.getId();
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!sgApi.isPresent()) {
return null;
}
if (ipPermission.getCidrBlocks().size() > 0) {
for (String cidr : ipPermission.getCidrBlocks()) {
sgApi.get().createRuleAllowingCidrBlock(id,
Ingress.builder()
.ipProtocol(ipPermission.getIpProtocol())
.fromPort(ipPermission.getFromPort())
.toPort(ipPermission.getToPort())
.build(),
cidr);
}
}
if (ipPermission.getGroupIds().size() > 0) {
for (String zoneAndGroupRaw : ipPermission.getGroupIds()) {
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(zoneAndGroupRaw);
String groupId = zoneAndId.getId();
sgApi.get().createRuleAllowingSecurityGroupId(id,
Ingress.builder()
.ipProtocol(ipPermission.getIpProtocol())
.fromPort(ipPermission.getFromPort())
.toPort(ipPermission.getToPort())
.build(),
groupId);
}
}
return getSecurityGroupById(ZoneAndId.fromZoneAndId(zone, id).slashEncode());
}
@Override
public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
String zone = group.getLocation().getId();
String id = group.getId();
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!sgApi.isPresent()) {
return null;
}
if (Iterables.size(ipRanges) > 0) {
for (String cidr : ipRanges) {
sgApi.get().createRuleAllowingCidrBlock(id,
Ingress.builder()
.ipProtocol(protocol)
.fromPort(startPort)
.toPort(endPort)
.build(),
cidr);
}
}
if (Iterables.size(groupIds) > 0) {
for (String zoneAndGroupRaw : groupIds) {
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(zoneAndGroupRaw);
String groupId = zoneAndId.getId();
sgApi.get().createRuleAllowingSecurityGroupId(id,
Ingress.builder()
.ipProtocol(protocol)
.fromPort(startPort)
.toPort(endPort)
.build(),
groupId);
}
}
return getSecurityGroupById(ZoneAndId.fromZoneAndId(zone, id).slashEncode());
}
@Override
public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
String zone = group.getLocation().getId();
String id = group.getId();
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!sgApi.isPresent()) {
return null;
}
org.jclouds.openstack.nova.v2_0.domain.SecurityGroup securityGroup = sgApi.get().get(id);
if (ipPermission.getCidrBlocks().size() > 0) {
for (String cidr : ipPermission.getCidrBlocks()) {
for (SecurityGroupRule rule : filter(securityGroup.getRules(),
and(ruleCidr(cidr), ruleProtocol(ipPermission.getIpProtocol()),
ruleStartPort(ipPermission.getFromPort()),
ruleEndPort(ipPermission.getToPort())))) {
sgApi.get().deleteRule(rule.getId());
}
}
}
if (ipPermission.getGroupIds().size() > 0) {
for (String groupId : ipPermission.getGroupIds()) {
for (SecurityGroupRule rule : filter(securityGroup.getRules(),
and(ruleGroup(groupId), ruleProtocol(ipPermission.getIpProtocol()),
ruleStartPort(ipPermission.getFromPort()),
ruleEndPort(ipPermission.getToPort())))) {
sgApi.get().deleteRule(rule.getId());
}
}
}
return getSecurityGroupById(ZoneAndId.fromZoneAndId(zone, id).slashEncode());
}
@Override
public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
String zone = group.getLocation().getId();
String id = group.getId();
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(zone);
if (!sgApi.isPresent()) {
return null;
}
org.jclouds.openstack.nova.v2_0.domain.SecurityGroup securityGroup = sgApi.get().get(id);
if (Iterables.size(ipRanges) > 0) {
for (String cidr : ipRanges) {
for (SecurityGroupRule rule : filter(securityGroup.getRules(),
and(ruleCidr(cidr),
ruleProtocol(protocol),
ruleStartPort(startPort),
ruleEndPort(endPort)))) {
sgApi.get().deleteRule(rule.getId());
}
}
}
if (Iterables.size(groupIds) > 0) {
for (String groupId : groupIds) {
for (SecurityGroupRule rule : filter(securityGroup.getRules(),
and(ruleGroup(groupId),
ruleProtocol(protocol),
ruleStartPort(startPort),
ruleEndPort(endPort)))) {
sgApi.get().deleteRule(rule.getId());
}
}
}
return getSecurityGroupById(ZoneAndId.fromZoneAndId(zone, id).slashEncode());
}
@Override
public boolean supportsTenantIdGroupNamePairs() {
return false;
}
@Override
public boolean supportsGroupIds() {
return true;
}
@Override
public boolean supportsPortRangesForGroups() {
return false;
}
protected Iterable<? extends SecurityGroupInZone> pollSecurityGroups() {
Iterable<? extends Set<? extends SecurityGroupInZone>> groups
= transform(zoneIds.get(), allSecurityGroupsInZone());
return concat(groups);
}
protected Iterable<? extends SecurityGroupInZone> pollSecurityGroupsByZone(String zone) {
return allSecurityGroupsInZone().apply(zone);
}
protected Function<String, Set<? extends SecurityGroupInZone>> allSecurityGroupsInZone() {
return new Function<String, Set<? extends SecurityGroupInZone>>() {
@Override
public Set<? extends SecurityGroupInZone> apply(final String from) {
Optional<? extends SecurityGroupApi> sgApi = api.getSecurityGroupExtensionForZone(from);
if (!sgApi.isPresent()) {
return ImmutableSet.of();
}
return sgApi.get().list().transform(groupToGroupInZone(from)).toSet();
}
};
}
protected Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroupInZone> groupToGroupInZone(final String zone) {
return new Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroupInZone>() {
@Override
public SecurityGroupInZone apply(org.jclouds.openstack.nova.v2_0.domain.SecurityGroup group) {
return new SecurityGroupInZone(group, zone);
}
};
}
}

View File

@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
/**
* A function for transforming a Nova-specific SecurityGroup into a generic
* SecurityGroup object.
*
* @author Andrew Bayer
*/
@Singleton
public class NovaSecurityGroupInZoneToSecurityGroup implements Function<SecurityGroupInZone, SecurityGroup> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> baseConverter;
protected final Supplier<Map<String, Location>> locationIndex;
@Inject
public NovaSecurityGroupInZoneToSecurityGroup(Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> baseConverter,
Supplier<Map<String, Location>> locationIndex) {
this.baseConverter = checkNotNull(baseConverter, "baseConverter");
this.locationIndex = checkNotNull(locationIndex, "locationIndex");
}
@Override
public SecurityGroup apply(SecurityGroupInZone group) {
SecurityGroupBuilder builder = SecurityGroupBuilder.fromSecurityGroup(baseConverter.apply(group.getSecurityGroup()));
Location zone = locationIndex.get().get(group.getZone());
checkState(zone != null, "location %s not in locationIndex: %s", group.getZone(), locationIndex.get());
builder.location(zone);
return builder.build();
}
}

View File

@ -16,12 +16,8 @@
*/
package org.jclouds.openstack.nova.v2_0.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
@ -34,9 +30,6 @@ import org.jclouds.net.domain.IpPermission;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
@ -67,7 +60,9 @@ public class NovaSecurityGroupToSecurityGroup implements Function<org.jclouds.op
builder.providerId(group.getId());
builder.ownerId(group.getTenantId());
builder.name(group.getName());
if (group.getRules() != null) {
builder.ipPermissions(transform(group.getRules(), ruleToPermission));
}
return builder.build();
}

View File

@ -17,7 +17,6 @@
package org.jclouds.openstack.nova.v2_0.compute.loaders;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.openstack.nova.v2_0.config.NovaProperties.TIMEOUT_SECURITYGROUP_PRESENT;
import java.util.concurrent.atomic.AtomicReference;
@ -44,7 +43,7 @@ public class FindSecurityGroupOrCreate extends CacheLoader<ZoneAndName, Security
@Inject
public FindSecurityGroupOrCreate(
@Named(TIMEOUT_SECURITYGROUP_PRESENT) Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone,
@Named("SECURITYGROUP_PRESENT") Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone,
Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> groupCreator) {
this.returnSecurityGroupExistsInZone = checkNotNull(returnSecurityGroupExistsInZone,
"returnSecurityGroupExistsInZone");

View File

@ -31,7 +31,7 @@ public class SecurityGroupInZone extends ZoneAndName {
this.securityGroup = securityGroup;
}
public SecurityGroup getServer() {
public SecurityGroup getSecurityGroup() {
return securityGroup;
}

View File

@ -77,7 +77,7 @@ public interface SecurityGroupApi {
* @return a new Security Group Rule
*/
SecurityGroupRule createRuleAllowingSecurityGroupId(String parentGroup, Ingress ingress,
String sourceCidr);
String groupId);
/**
* Delete a Security Group Rule.

View File

@ -18,9 +18,14 @@ package org.jclouds.openstack.nova.v2_0.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
/**
* Predicates handy when working with SecurityGroups
@ -52,6 +57,28 @@ public class SecurityGroupPredicates {
};
}
/**
* matches name of the given security group against a list
*
* @param names
* @return predicate that matches one of the names
*/
public static Predicate<SecurityGroup> nameIn(final Set<String> names) {
checkNotNull(names, "names must be defined");
return new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup ext) {
return Predicates.in(names).apply(ext.getName());
}
@Override
public String toString() {
return "nameIn(" + names + ")";
}
};
}
/**
* matches name of the given security group
*
@ -73,4 +100,114 @@ public class SecurityGroupPredicates {
}
};
}
/**
* matches a security group rule by its cidr
*
* @param cidr
* @return predicate that matches cidr
*/
public static Predicate<SecurityGroupRule> ruleCidr(final String cidr) {
checkNotNull(cidr, "cidr must be defined");
return new Predicate<SecurityGroupRule>() {
@Override
public boolean apply(SecurityGroupRule ext) {
return cidr.equals(ext.getIpRange());
}
@Override
public String toString() {
return "cidr(" + cidr + ")";
}
};
}
/**
* matches a security group rule by the security group it allows
*
* @param groupName
* @return predicate that matches group
*/
public static Predicate<SecurityGroupRule> ruleGroup(final String groupName) {
checkNotNull(groupName, "groupName must be defined");
return new Predicate<SecurityGroupRule>() {
@Override
public boolean apply(SecurityGroupRule ext) {
return ext.getGroup() != null && groupName.equals(ext.getGroup().getName());
}
@Override
public String toString() {
return "ruleGroup(" + groupName + ")";
}
};
}
/**
* matches a security group rule by the protocol
*
* @param protocol
* @return predicate that matches protocol
*/
public static Predicate<SecurityGroupRule> ruleProtocol(final IpProtocol protocol) {
checkNotNull(protocol, "protocol must be defined");
return new Predicate<SecurityGroupRule>() {
@Override
public boolean apply(SecurityGroupRule ext) {
return protocol.equals(ext.getIpProtocol());
}
@Override
public String toString() {
return "ruleProtocol(" + protocol + ")";
}
};
}
/**
* matches a security group rule by the start port
*
* @param startPort
* @return predicate that matches startPort
*/
public static Predicate<SecurityGroupRule> ruleStartPort(final int startPort) {
checkNotNull(startPort, "startPort must be defined");
return new Predicate<SecurityGroupRule>() {
@Override
public boolean apply(SecurityGroupRule ext) {
return startPort == ext.getFromPort();
}
@Override
public String toString() {
return "ruleStartPort(" + startPort + ")";
}
};
}
/**
* matches a security group rule by the end port
*
* @param endPort
* @return predicate that matches endPort
*/
public static Predicate<SecurityGroupRule> ruleEndPort(final int endPort) {
checkNotNull(endPort, "endPort must be defined");
return new Predicate<SecurityGroupRule>() {
@Override
public boolean apply(SecurityGroupRule ext) {
return endPort == ext.getToPort();
}
@Override
public String toString() {
return "ruleEndPort(" + endPort + ")";
}
};
}
}

View File

@ -0,0 +1,423 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.compute.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.Properties;
import java.util.Set;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaComputeServiceExpectTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
/**
*
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "NovaSecurityGroupExtensionExpectTest")
public class NovaSecurityGroupExtensionExpectTest extends BaseNovaComputeServiceExpectTest {
protected String zone = "az-1.region-a.geo-1";
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();
overrides.setProperty("jclouds.zones", zone);
return overrides;
}
public void testListSecurityGroups() {
HttpRequest list = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_list.json")).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess);
requestResponseMap.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
requestResponseMap.put(list, listResponse).build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
Set<SecurityGroup> groups = extension.listSecurityGroups();
assertEquals(groups.size(), 1);
}
public void testListSecurityGroupsInLocation() {
HttpRequest list = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_list.json")).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess);
requestResponseMap.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
requestResponseMap.put(list, listResponse).build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
Set<SecurityGroup> groups = extension.listSecurityGroupsInLocation(new LocationBuilder()
.scope(LocationScope.ZONE)
.id(zone)
.description("zone")
.build());
assertEquals(groups.size(), 1);
}
public void testListSecurityGroupsForNode() {
HttpRequest serverReq = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-create-server-ext/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse serverResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/server_with_security_groups_extension.json")).build();
HttpRequest list = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_list.json")).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess);
requestResponseMap.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
requestResponseMap.put(serverReq, serverResponse);
requestResponseMap.put(list, listResponse).build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
Set<SecurityGroup> groups = extension.listSecurityGroupsForNode(zone + "/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb");
assertEquals(groups.size(), 1);
}
public void testGetSecurityGroupById() {
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160")).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_extension.json")).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess);
requestResponseMap.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
requestResponseMap.put(getSecurityGroup, getSecurityGroupResponse).build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroup group = extension.getSecurityGroupById(zone + "/160");
assertEquals(group.getId(), "160");
}
public void testCreateSecurityGroup() {
HttpRequest create = HttpRequest.builder().method("POST").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/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-test\",\"description\":\"jclouds-test\"}}",
"application/json")).build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_created.json")).build();
HttpRequest list = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups")).headers(
ImmutableMultimap.<String, String>builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_list_extension.json")).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess);
requestResponseMap.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
requestResponseMap.put(create, createResponse);
requestResponseMap.put(list, listResponse).build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroup group = extension.createSecurityGroup("test", new LocationBuilder()
.scope(LocationScope.ZONE)
.id(zone)
.description("zone")
.build());
assertEquals(group.getId(), "160");
}
public void testRemoveSecurityGroup() {
HttpRequest delete = HttpRequest.builder().method("DELETE").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160"))
.headers(
ImmutableMultimap.<String, String>builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(202).build();
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160")).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_extension.json")).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess);
requestResponseMap.put(extensionsOfNovaRequest, extensionsOfNovaResponse);
requestResponseMap.put(getSecurityGroup, getSecurityGroupResponse);
requestResponseMap.put(delete, deleteResponse).build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
assertTrue(extension.removeSecurityGroup(zone + "/160"), "Expected removal of securitygroup to be successful");
}
public void testAddIpPermissionCidrFromIpPermission() {
HttpRequest createRule = HttpRequest
.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-group-rules")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(
payloadFromStringWithContentType(
"{\"security_group_rule\":{\"parent_group_id\":\"160\",\"cidr\":\"10.2.6.0/24\",\"ip_protocol\":\"tcp\",\"from_port\":\"22\",\"to_port\":\"22\"}}",
"application/json")).build();
HttpResponse createRuleResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygrouprule_created_cidr.json")).build();
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse getSecurityGroupNoRulesResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension_norules.json")).build();
HttpResponse getSecurityGroupResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension.json")).build();
SecurityGroupExtension extension = orderedRequestsSendResponses(ImmutableList.of(keystoneAuthWithUsernameAndPasswordAndTenantName,
extensionsOfNovaRequest, getSecurityGroup, createRule, getSecurityGroup),
ImmutableList.of(responseWithKeystoneAccess, extensionsOfNovaResponse, getSecurityGroupNoRulesResponse,
createRuleResponse, getSecurityGroupResponse)).getSecurityGroupExtension().get();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(22);
builder.toPort(22);
builder.cidrBlock("10.2.6.0/24");
IpPermission perm = builder.build();
SecurityGroup origGroup = extension.getSecurityGroupById(zone + "/160");
assertNotNull(origGroup);
SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
assertNotNull(newGroup);
}
public void testAddIpPermissionCidrFromParams() {
HttpRequest createRule = HttpRequest
.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-group-rules")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(
payloadFromStringWithContentType(
"{\"security_group_rule\":{\"parent_group_id\":\"160\",\"cidr\":\"10.2.6.0/24\",\"ip_protocol\":\"tcp\",\"from_port\":\"22\",\"to_port\":\"22\"}}",
"application/json")).build();
HttpResponse createRuleResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygrouprule_created_cidr.json")).build();
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse getSecurityGroupNoRulesResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension_norules.json")).build();
HttpResponse getSecurityGroupResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension.json")).build();
SecurityGroupExtension extension = orderedRequestsSendResponses(ImmutableList.of(keystoneAuthWithUsernameAndPasswordAndTenantName,
extensionsOfNovaRequest, getSecurityGroup, createRule, getSecurityGroup),
ImmutableList.of(responseWithKeystoneAccess, extensionsOfNovaResponse, getSecurityGroupNoRulesResponse,
createRuleResponse, getSecurityGroupResponse)).getSecurityGroupExtension().get();
SecurityGroup origGroup = extension.getSecurityGroupById(zone + "/160");
assertNotNull(origGroup);
SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
22,
22,
emptyMultimap(),
ImmutableSet.of("10.2.6.0/24"),
emptyStringSet(),
origGroup);
assertNotNull(newGroup);
}
public void testAddIpPermissionGroupFromIpPermission() {
HttpRequest createRule = HttpRequest
.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-group-rules")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(
payloadFromStringWithContentType(
"{\"security_group_rule\":{\"group_id\":\"11111\",\"parent_group_id\":\"160\",\"ip_protocol\":\"tcp\",\"from_port\":\"22\",\"to_port\":\"22\"}}",
"application/json")).build();
HttpResponse createRuleResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygrouprule_created_group.json")).build();
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse getSecurityGroupNoRulesResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension_norules.json")).build();
HttpResponse getSecurityGroupResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension.json")).build();
SecurityGroupExtension extension = orderedRequestsSendResponses(ImmutableList.of(keystoneAuthWithUsernameAndPasswordAndTenantName,
extensionsOfNovaRequest, getSecurityGroup, createRule, getSecurityGroup),
ImmutableList.of(responseWithKeystoneAccess, extensionsOfNovaResponse, getSecurityGroupNoRulesResponse,
createRuleResponse, getSecurityGroupResponse)).getSecurityGroupExtension().get();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(22);
builder.toPort(22);
builder.groupId("admin/11111");
IpPermission perm = builder.build();
SecurityGroup origGroup = extension.getSecurityGroupById(zone + "/160");
assertNotNull(origGroup);
SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
assertNotNull(newGroup);
}
public void testAddIpPermissionGroupFromParams() {
HttpRequest createRule = HttpRequest
.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-group-rules")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(
payloadFromStringWithContentType(
"{\"security_group_rule\":{\"group_id\":\"11111\",\"parent_group_id\":\"160\",\"ip_protocol\":\"tcp\",\"from_port\":\"22\",\"to_port\":\"22\"}}",
"application/json")).build();
HttpResponse createRuleResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygrouprule_created_group.json")).build();
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-groups/160")).headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
authToken).build()).build();
HttpResponse getSecurityGroupNoRulesResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension_norules.json")).build();
HttpResponse getSecurityGroupResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/securitygroup_details_extension.json")).build();
SecurityGroupExtension extension = orderedRequestsSendResponses(ImmutableList.of(keystoneAuthWithUsernameAndPasswordAndTenantName,
extensionsOfNovaRequest, getSecurityGroup, createRule, getSecurityGroup),
ImmutableList.of(responseWithKeystoneAccess, extensionsOfNovaResponse, getSecurityGroupNoRulesResponse,
createRuleResponse, getSecurityGroupResponse)).getSecurityGroupExtension().get();
SecurityGroup origGroup = extension.getSecurityGroupById(zone + "/160");
assertNotNull(origGroup);
SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
22,
22,
emptyMultimap(),
emptyStringSet(),
ImmutableSet.of("admin/11111"),
origGroup);
assertNotNull(newGroup);
}
private Multimap<String, String> emptyMultimap() {
return LinkedHashMultimap.create();
}
private Set<String> emptyStringSet() {
return Sets.newLinkedHashSet();
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.compute.extensions;
import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest;
import org.testng.annotations.Test;
/**
* Live test for openstack-nova {@link org.jclouds.compute.extensions.SecurityGroupExtension} implementation.
*
* @author Andrew Bayer
*
*/
@Test(groups = "live", singleThreaded = true, testName = "NovaSecurityGroupExtensionLiveTest")
public class NovaSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
public NovaSecurityGroupExtensionLiveTest() {
provider = "openstack-nova";
}
}

View File

@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.compute.functions;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupToSecurityGroupTest.securityGroupWithCidr;
import static org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupToSecurityGroupTest.securityGroupWithGroup;
import static org.testng.Assert.assertEquals;
import java.util.Map;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "NovaSecurityGroupInZoneToSecurityGroupTest")
public class NovaSecurityGroupInZoneToSecurityGroupTest {
private static final SecurityGroupRuleToIpPermission ruleConverter = new SecurityGroupRuleToIpPermission();
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 testApplyWithGroup() {
NovaSecurityGroupInZoneToSecurityGroup parser = createGroupParser();
SecurityGroupInZone origGroup = new SecurityGroupInZone(securityGroupWithGroup(), zone.getId());
SecurityGroup newGroup = parser.apply(origGroup);
assertEquals(newGroup.getId(), origGroup.getSecurityGroup().getId());
assertEquals(newGroup.getProviderId(), origGroup.getSecurityGroup().getId());
assertEquals(newGroup.getName(), origGroup.getSecurityGroup().getName());
assertEquals(newGroup.getOwnerId(), origGroup.getSecurityGroup().getTenantId());
assertEquals(newGroup.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getSecurityGroup().getRules(), ruleConverter)));
assertEquals(newGroup.getLocation().getId(), origGroup.getZone());
}
@Test
public void testApplyWithCidr() {
NovaSecurityGroupInZoneToSecurityGroup parser = createGroupParser();
SecurityGroupInZone origGroup = new SecurityGroupInZone(securityGroupWithCidr(), zone.getId());
SecurityGroup newGroup = parser.apply(origGroup);
assertEquals(newGroup.getId(), origGroup.getSecurityGroup().getId());
assertEquals(newGroup.getProviderId(), origGroup.getSecurityGroup().getId());
assertEquals(newGroup.getName(), origGroup.getSecurityGroup().getName());
assertEquals(newGroup.getOwnerId(), origGroup.getSecurityGroup().getTenantId());
assertEquals(newGroup.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getSecurityGroup().getRules(), ruleConverter)));
assertEquals(newGroup.getLocation().getId(), origGroup.getZone());
}
private NovaSecurityGroupInZoneToSecurityGroup createGroupParser() {
NovaSecurityGroupToSecurityGroup baseParser = new NovaSecurityGroupToSecurityGroup(ruleConverter);
NovaSecurityGroupInZoneToSecurityGroup parser = new NovaSecurityGroupInZoneToSecurityGroup(baseParser, locationIndex);
return parser;
}
}

View File

@ -18,19 +18,13 @@ package org.jclouds.openstack.nova.v2_0.compute.functions;
import static com.google.common.collect.Iterables.transform;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.TenantIdAndName;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
/**
@ -41,8 +35,7 @@ public class NovaSecurityGroupToSecurityGroupTest {
private static final SecurityGroupRuleToIpPermission ruleConverter = new SecurityGroupRuleToIpPermission();
@Test
public void testApplyWithGroup() {
public static org.jclouds.openstack.nova.v2_0.domain.SecurityGroup securityGroupWithGroup() {
TenantIdAndName group = TenantIdAndName.builder().tenantId("tenant").name("name").build();
SecurityGroupRule ruleToConvert = SecurityGroupRule.builder()
@ -62,19 +55,10 @@ public class NovaSecurityGroupToSecurityGroupTest {
.rules(ruleToConvert)
.build();
NovaSecurityGroupToSecurityGroup parser = createGroupParser();
SecurityGroup newGroup = parser.apply(origGroup);
assertEquals(newGroup.getId(), origGroup.getId());
assertEquals(newGroup.getProviderId(), origGroup.getId());
assertEquals(newGroup.getName(), origGroup.getName());
assertEquals(newGroup.getOwnerId(), origGroup.getTenantId());
assertEquals(newGroup.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getRules(), ruleConverter)));
return origGroup;
}
@Test
public void testApplyWithCidr() {
public static org.jclouds.openstack.nova.v2_0.domain.SecurityGroup securityGroupWithCidr() {
SecurityGroupRule ruleToConvert = SecurityGroupRule.builder()
.id("some-id")
.ipProtocol(IpProtocol.TCP)
@ -92,8 +76,31 @@ public class NovaSecurityGroupToSecurityGroupTest {
.rules(ruleToConvert)
.build();
return origGroup;
}
@Test
public void testApplyWithGroup() {
NovaSecurityGroupToSecurityGroup parser = createGroupParser();
org.jclouds.openstack.nova.v2_0.domain.SecurityGroup origGroup = securityGroupWithGroup();
SecurityGroup newGroup = parser.apply(origGroup);
assertEquals(newGroup.getId(), origGroup.getId());
assertEquals(newGroup.getProviderId(), origGroup.getId());
assertEquals(newGroup.getName(), origGroup.getName());
assertEquals(newGroup.getOwnerId(), origGroup.getTenantId());
assertEquals(newGroup.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getRules(), ruleConverter)));
}
@Test
public void testApplyWithCidr() {
NovaSecurityGroupToSecurityGroup parser = createGroupParser();
org.jclouds.openstack.nova.v2_0.domain.SecurityGroup origGroup = securityGroupWithCidr();
SecurityGroup group = parser.apply(origGroup);
assertEquals(group.getId(), origGroup.getId());

View File

@ -17,10 +17,22 @@
package org.jclouds.openstack.nova.v2_0.predicates;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.nameEquals;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.nameIn;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleCidr;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleEndPort;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleGroup;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleProtocol;
import static org.jclouds.openstack.nova.v2_0.predicates.SecurityGroupPredicates.ruleStartPort;
import static org.testng.Assert.assertTrue;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.TenantIdAndName;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
@ -28,15 +40,90 @@ import org.testng.annotations.Test;
@Test(groups = "unit", testName = "SecurityGroupPredicatesTest")
public class SecurityGroupPredicatesTest {
SecurityGroup ref = SecurityGroup.builder().id("12345").name("jclouds").description("description").build();
SecurityGroupRule ruleRef = SecurityGroupRule.builder().id("6789").parentGroupId("12345").ipRange("0.0.0.0/0")
.fromPort(10).toPort(20).ipProtocol(IpProtocol.TCP)
.group(TenantIdAndName.builder().tenantId("11111111").name("abcd").build())
.build();
@Test
public void testnameEqualsWhenEqual() {
assert nameEquals("jclouds").apply(ref);
assertTrue(nameEquals("jclouds").apply(ref), "expected 'jclouds' as the name of " + ref);
}
@Test
public void testnameEqualsWhenNotEqual() {
assert !nameEquals("foo").apply(ref);
assertTrue(!nameEquals("foo").apply(ref), "expected 'foo' not to be the name of " + ref);
}
@Test
public void testNameInWhenIn() {
assertTrue(nameIn(ImmutableSet.of("jclouds", "pants")).apply(ref),
"expected the name of " + ref + " to be one of 'jclouds' or 'pants'");
}
@Test
public void testNameInWhenNotIn() {
assertTrue(!nameIn(ImmutableSet.of("foo", "pants")).apply(ref),
"expected the name of " + ref + " to not be either of 'foo' or 'pants'");
}
@Test
public void testRuleCidrWhenEqual() {
assertTrue(ruleCidr("0.0.0.0/0").apply(ruleRef),
"expected the CIDR to be '0.0.0.0/0' for " + ruleRef);
}
@Test
public void testRuleCidrWhenNotEqual() {
assertTrue(!ruleCidr("1.1.1.1/0").apply(ruleRef),
"expected the CIDR to not be '1.1.1.1/0' for " + ruleRef);
}
@Test
public void testRuleGroupWhenEqual() {
assertTrue(ruleGroup("abcd").apply(ruleRef),
"expected the group to be equal to 'abcd' for " + ruleRef);
}
@Test
public void testRuleGroupWhenNotEqual() {
assertTrue(!ruleGroup("pants").apply(ruleRef),
"expected the group to not be equal to 'pants' for " + ruleRef);
}
@Test
public void testRuleProtocolWhenEqual() {
assertTrue(ruleProtocol(IpProtocol.TCP).apply(ruleRef),
"expected TCP for " + ruleRef);
}
@Test
public void testRuleProtocolWhenNotEqual() {
assertTrue(!ruleProtocol(IpProtocol.UDP).apply(ruleRef),
"expected not UDP for " + ruleRef);
}
@Test
public void testRuleStartPortWhenEqual() {
assertTrue(ruleStartPort(10).apply(ruleRef),
"expected start port 10 for " + ruleRef);
}
@Test
public void testRuleStartPortWhenNotEqual() {
assertTrue(!ruleStartPort(50).apply(ruleRef),
"expected start port not to be 50 for " + ruleRef);
}
@Test
public void testRuleEndPortWhenEqual() {
assertTrue(ruleEndPort(20).apply(ruleRef),
"expected end port 20 for " + ruleRef);
}
@Test
public void testRuleEndPortWhenNotEqual() {
assertTrue(!ruleEndPort(50).apply(ruleRef),
"expected end port not to be 50 for " + ruleRef);
}
}

View File

@ -0,0 +1,34 @@
{
"security_group":
{
"rules": [
{
"from_port": 22,
"group": {},
"ip_protocol": "tcp",
"to_port": 22,
"parent_group_id": 160,
"ip_range": {
"cidr": "10.2.6.0/24"
},
"id": 108
},
{
"from_port": 22,
"group": {
"tenant_id": "admin",
"name": "11111"
},
"ip_protocol": "tcp",
"to_port": 22,
"parent_group_id": 160,
"ip_range": {},
"id": 109
}
],
"tenant_id": "tenant0",
"id": 160,
"name": "name0",
"description": "description0"
}
}

View File

@ -0,0 +1,10 @@
{
"security_group":
{
"rules": [],
"tenant_id": "tenant0",
"id": 160,
"name": "name0",
"description": "description0"
}
}

View File

@ -0,0 +1,51 @@
{
"security_groups":[
{
"rules":[
{
"from_port":22,
"group":{
},
"ip_protocol":"tcp",
"to_port":22,
"parent_group_id":3,
"ip_range":{
"cidr":"0.0.0.0/0"
},
"id":107
},
{
"from_port":7600,
"group":{
},
"ip_protocol":"tcp",
"to_port":7600,
"parent_group_id":3,
"ip_range":{
"cidr":"0.0.0.0/0"
},
"id":118
},
{
"from_port":8084,
"group":{
},
"ip_protocol":"tcp",
"to_port":8084,
"parent_group_id":3,
"ip_range":{
"cidr":"0.0.0.0/0"
},
"id":119
}
],
"tenant_id":"dev_16767499955063",
"id":160,
"name":"jclouds-test",
"description":"jclouds-test"
}
]
}

View File

@ -0,0 +1,13 @@
{
"security_group_rule": {
"from_port": 22,
"group": {},
"ip_protocol": "tcp",
"to_port": 22,
"parent_group_id": 160,
"ip_range": {
"cidr": "10.2.6.0/24"
},
"id": 108
}
}

View File

@ -0,0 +1,14 @@
{
"security_group_rule": {
"from_port": 22,
"group": {
"tenant_id": "admin",
"name": "11111"
},
"ip_protocol": "tcp",
"to_port": 22,
"parent_group_id": 160,
"ip_range": {},
"id": 109
}
}

View File

@ -0,0 +1 @@
{"server": {"status": "ACTIVE", "updated": "2012-05-04T12:15:01Z", "hostId": "02c7c81e36024d2bfdb473cb762900138bc07777922479d3d4f8f690", "user_id": "1e8a56719e0d4ab4b7edb85c77f7290f", "name": "test", "links": [{"href": "http://172.16.89.148:8774/v2/4287930c796741aa898425f40832cb3c/servers/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb", "rel": "self"}, {"href": "http://172.16.89.148:8774/4287930c796741aa898425f40832cb3c/servers/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb", "rel": "bookmark"}], "created": "2012-05-04T12:14:57Z", "tenant_id": "4287930c796741aa898425f40832cb3c", "image": {"id": "ea17cc36-f7c9-40cd-b6bf-a952b74870f2", "links": [{"href": "http://172.16.89.148:8774/4287930c796741aa898425f40832cb3c/images/ea17cc36-f7c9-40cd-b6bf-a952b74870f2", "rel": "bookmark"}]}, "addresses": {"private": [{"version": 4, "addr": "10.0.0.8"}]}, "accessIPv4": "", "accessIPv6": "", "key_name": "", "progress": 0, "flavor": {"id": "1", "links": [{"href": "http://172.16.89.148:8774/4287930c796741aa898425f40832cb3c/flavors/1", "rel": "bookmark"}]}, "config_drive": "", "id": "8d0a6ca5-8849-4b3d-b86e-f24c92490ebb", "security_groups": [{"name": "name1"}], "metadata": {}}}