mirror of https://github.com/apache/jclouds.git
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
b5e8458446
|
@ -74,7 +74,7 @@ public class HPCloudComputeTemplateBuilderLiveTest extends BaseTemplateBuilderLi
|
||||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
|
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
|
||||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||||
assertEquals(defaultTemplate.getLocation().getId(), "az-1.region-a.geo-1");
|
assertEquals(defaultTemplate.getLocation().getId(), "az-1.region-a.geo-1");
|
||||||
assertEquals(defaultTemplate.getOptions().as(NovaTemplateOptions.class).isAutoAssignFloatingIp(), true);
|
assertEquals(defaultTemplate.getOptions().as(NovaTemplateOptions.class).shouldAutoAssignFloatingIp(), true);
|
||||||
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
|
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.jclouds.openstack.nova.v1_1;
|
||||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||||
import static org.jclouds.openstack.nova.v1_1.reference.NovaConstants.PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS;
|
import static org.jclouds.openstack.nova.v1_1.reference.NovaConstants.PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS;
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.reference.NovaConstants.PROPERTY_NOVA_TIMEOUT_SECURITYGROUP_PRESENT;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -43,6 +44,8 @@ public class NovaPropertiesBuilder extends PropertiesBuilder {
|
||||||
properties.setProperty(KeystoneProperties.VERSION, "2.0");
|
properties.setProperty(KeystoneProperties.VERSION, "2.0");
|
||||||
properties.setProperty(PROPERTY_API_VERSION, "1.1");
|
properties.setProperty(PROPERTY_API_VERSION, "1.1");
|
||||||
properties.setProperty(PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS, "false");
|
properties.setProperty(PROPERTY_NOVA_AUTO_ALLOCATE_FLOATING_IPS, "false");
|
||||||
|
properties.setProperty(PROPERTY_NOVA_TIMEOUT_SECURITYGROUP_PRESENT, "500");
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,13 @@ 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.ServerInZone;
|
||||||
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
|
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.functions.RemoveFloatingIpFromNodeAndDeallocate;
|
||||||
|
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.Flavor;
|
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.Image;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.RebootType;
|
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.Server;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateServerOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -76,15 +79,24 @@ public class NovaComputeServiceAdapter implements
|
||||||
"removeFloatingIpFromNodeAndDeallocate");
|
"removeFloatingIpFromNodeAndDeallocate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that we do not validate extensions here, on basis that
|
||||||
|
* {@link ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet} has already
|
||||||
|
* done so.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public NodeAndInitialCredentials<ServerInZone> createNodeWithGroupEncodedIntoName(String tag, String name,
|
public NodeAndInitialCredentials<ServerInZone> createNodeWithGroupEncodedIntoName(String group, String name,
|
||||||
Template template) {
|
Template template) {
|
||||||
|
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
options.securityGroupNames(template.getOptions().as(NovaTemplateOptions.class).getSecurityGroupNames());
|
||||||
|
|
||||||
String zoneId = template.getLocation().getId();
|
String zoneId = template.getLocation().getId();
|
||||||
Server server = novaClient.getServerClientForZone(zoneId).createServer(name, template.getImage().getProviderId(),
|
Server server = novaClient.getServerClientForZone(zoneId).createServer(name, template.getImage().getProviderId(),
|
||||||
template.getHardware().getProviderId());
|
template.getHardware().getProviderId(), options);
|
||||||
ServerInZone serverInZone = new ServerInZone(server, zoneId);
|
ServerInZone serverInZone = new ServerInZone(server, zoneId);
|
||||||
return new NodeAndInitialCredentials<ServerInZone>(serverInZone, serverInZone.slashEncode(),
|
return new NodeAndInitialCredentials<ServerInZone>(serverInZone, serverInZone.slashEncode(), LoginCredentials
|
||||||
LoginCredentials.builder().password(server.getAdminPass()).build());
|
.builder().password(server.getAdminPass()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,8 @@ package org.jclouds.openstack.nova.v1_1.compute.config;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -40,18 +42,26 @@ 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.NovaComputeServiceAdapter;
|
||||||
import org.jclouds.openstack.nova.v1_1.compute.domain.FlavorInZone;
|
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.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.ServerInZone;
|
||||||
import org.jclouds.openstack.nova.v1_1.compute.domain.ZoneAndId;
|
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.FlavorInZoneToHardware;
|
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.ImageInZoneToImage;
|
||||||
import org.jclouds.openstack.nova.v1_1.compute.functions.NovaImageToOperatingSystem;
|
import org.jclouds.openstack.nova.v1_1.compute.functions.NovaImageToOperatingSystem;
|
||||||
import org.jclouds.openstack.nova.v1_1.compute.functions.ServerInZoneToNodeMetadata;
|
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.LoadFloatingIpsForInstance;
|
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.options.NovaTemplateOptions;
|
||||||
import org.jclouds.openstack.nova.v1_1.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
|
import org.jclouds.openstack.nova.v1_1.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.predicates.FindSecurityGroupWithNameAndReturnTrue;
|
||||||
import org.jclouds.openstack.nova.v1_1.reference.NovaConstants;
|
import org.jclouds.openstack.nova.v1_1.reference.NovaConstants;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
@ -102,6 +112,12 @@ public class NovaComputeServiceContextModule
|
||||||
|
|
||||||
bind(new TypeLiteral<CacheLoader<ZoneAndId, Iterable<String>>>() {
|
bind(new TypeLiteral<CacheLoader<ZoneAndId, Iterable<String>>>() {
|
||||||
}).annotatedWith(Names.named("FLOATINGIP")).to(LoadFloatingIpsForInstance.class);
|
}).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);
|
||||||
|
|
||||||
bind(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
|
bind(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
|
||||||
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
|
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
|
||||||
|
@ -123,6 +139,22 @@ public class NovaComputeServiceContextModule
|
||||||
return CacheBuilder.newBuilder().build(in);
|
return CacheBuilder.newBuilder().build(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected LoadingCache<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> securityGroupMap(
|
||||||
|
CacheLoader<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> in) {
|
||||||
|
return CacheBuilder.newBuilder().build(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Named("SECURITY")
|
||||||
|
protected Predicate<AtomicReference<ZoneAndName>> securityGroupEventualConsistencyDelay(
|
||||||
|
FindSecurityGroupWithNameAndReturnTrue in,
|
||||||
|
@Named(NovaConstants.PROPERTY_NOVA_TIMEOUT_SECURITYGROUP_PRESENT) long msDelay) {
|
||||||
|
return new RetryablePredicate<AtomicReference<ZoneAndName>>(in, msDelay, 100l, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Supplier<Map<String, Location>> createLocationIndexedById(
|
protected Supplier<Map<String, Location>> createLocationIndexedById(
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SecurityGroupInZone extends ZoneAndName {
|
||||||
|
protected final SecurityGroup securityGroup;
|
||||||
|
|
||||||
|
public SecurityGroupInZone(SecurityGroup securityGroup, String zoneId) {
|
||||||
|
super(zoneId, checkNotNull(securityGroup, "securityGroup").getName());
|
||||||
|
this.securityGroup = securityGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecurityGroup getServer() {
|
||||||
|
return securityGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// superclass hashCode/equals are good enough, and help us use ZoneAndName and ServerInZone
|
||||||
|
// interchangeably as Map keys
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[securityGroup=" + securityGroup + ", zoneId=" + zoneId + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
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.Objects;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpful when looking for resources by zone and name
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class ZoneAndName {
|
||||||
|
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");
|
||||||
|
return new ZoneAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ZoneAndName fromZoneAndName(String zoneId, String name) {
|
||||||
|
return new ZoneAndName(zoneId, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String slashEncodeZoneAndName(String zoneId, String name) {
|
||||||
|
return checkNotNull(zoneId, "zoneId") + "/" + checkNotNull(name, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String slashEncode() {
|
||||||
|
return slashEncodeZoneAndName(zoneId, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String zoneId;
|
||||||
|
protected final String name;
|
||||||
|
|
||||||
|
protected ZoneAndName(String zoneId, String name) {
|
||||||
|
this.zoneId = checkNotNull(zoneId, "zoneId");
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getZone() {
|
||||||
|
return zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
ZoneAndName that = ZoneAndName.class.cast(o);
|
||||||
|
return equal(this.zoneId, that.zoneId) && equal(this.name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(zoneId, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("").add("zoneId", zoneId).add("name", name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class ZoneSecurityGroupNameAndPorts extends ZoneAndName {
|
||||||
|
protected final List<Integer> ports;
|
||||||
|
|
||||||
|
public ZoneSecurityGroupNameAndPorts(String zoneId, String name, List<Integer> ports) {
|
||||||
|
super(zoneId, name);
|
||||||
|
this.ports = ImmutableList.<Integer> copyOf(checkNotNull(ports, "ports"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getPorts() {
|
||||||
|
return ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
ZoneSecurityGroupNameAndPorts that = ZoneSecurityGroupNameAndPorts.class.cast(o);
|
||||||
|
return super.equals(that) && equal(this.ports, that.ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(super.hashCode(), ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ToStringHelper string() {
|
||||||
|
return super.string().add("ports", ports);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
* 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.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
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.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.extensions.SecurityGroupClient;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class CreateSecurityGroupInZone implements Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> {
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
protected final NovaClient novaClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CreateSecurityGroupInZone(NovaClient novaClient) {
|
||||||
|
this.novaClient = checkNotNull(novaClient, "novaClient");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SecurityGroupInZone apply(ZoneSecurityGroupNameAndPorts zoneSecurityGroupNameAndPorts) {
|
||||||
|
checkNotNull(zoneSecurityGroupNameAndPorts, "zoneSecurityGroupNameAndPorts");
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void authorizeGroupToItselfAndAllIPsToTCPPort(SecurityGroupClient securityGroupClient,
|
||||||
|
SecurityGroup securityGroup, int port) {
|
||||||
|
logger.debug(">> authorizing securityGroup(%s) permission to port %d", securityGroup, port);
|
||||||
|
logger.trace(">> authorizing securityGroup(%s) permission to itself on port %d", securityGroup, port);
|
||||||
|
securityGroupClient.createSecurityGroupRuleAllowingSecurityGroupId(securityGroup.getId(), Ingress.builder()
|
||||||
|
.ipProtocol(IpProtocol.TCP).fromPort(port).toPort(port).build(), securityGroup.getId());
|
||||||
|
logger.trace(">> authorizing securityGroup(%s) permission to 0.0.0.0/0 on port %d", securityGroup, port);
|
||||||
|
securityGroupClient.createSecurityGroupRuleAllowingCidrBlock(securityGroup.getId(), Ingress.builder().ipProtocol(
|
||||||
|
IpProtocol.TCP).fromPort(port).toPort(port).build(), "0.0.0.0/0");
|
||||||
|
logger.debug("<< authorized securityGroup(%s) permission to port %d", securityGroup, port);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,22 +18,28 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.compute.options;
|
package org.jclouds.openstack.nova.v1_1.compute.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.util.Preconditions2;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains options supported in the {@code ComputeService#runNode} operation on
|
* Contains options supported in the {@code ComputeService#runNode} operation on the
|
||||||
* the "openstack-nova" provider.
|
* "openstack-nova" provider. <h2>Usage</h2> The recommended way to instantiate a
|
||||||
* <h2>Usage</h2> The recommended way to instantiate a NovaTemplateOptions object is
|
* NovaTemplateOptions object is to statically import NovaTemplateOptions.* and invoke a static
|
||||||
* to statically import NovaTemplateOptions.* and invoke a static creation method
|
* creation method followed by an instance mutator (if needed):
|
||||||
* followed by an instance mutator (if needed):
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* <code>
|
* <code>
|
||||||
* import static org.jclouds.aws.ec2.compute.options.NovaTemplateOptions.Builder.*;
|
* import static org.jclouds.aws.ec2.compute.options.NovaTemplateOptions.Builder.*;
|
||||||
|
@ -42,7 +48,7 @@ import com.google.common.base.Objects;
|
||||||
* templateBuilder.options(inboundPorts(22, 80, 8080, 443));
|
* templateBuilder.options(inboundPorts(22, 80, 8080, 443));
|
||||||
* Set<? extends NodeMetadata> set = client.createNodesInGroup(tag, 2, templateBuilder.build());
|
* Set<? extends NodeMetadata> set = client.createNodesInGroup(tag, 2, templateBuilder.build());
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adam Lowe
|
* @author Adam Lowe
|
||||||
*/
|
*/
|
||||||
public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
|
@ -58,38 +64,86 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
super.copyTo(to);
|
super.copyTo(to);
|
||||||
if (to instanceof NovaTemplateOptions) {
|
if (to instanceof NovaTemplateOptions) {
|
||||||
NovaTemplateOptions eTo = NovaTemplateOptions.class.cast(to);
|
NovaTemplateOptions eTo = NovaTemplateOptions.class.cast(to);
|
||||||
eTo.autoAssignFloatingIp(isAutoAssignFloatingIp());
|
eTo.autoAssignFloatingIp(shouldAutoAssignFloatingIp());
|
||||||
|
eTo.securityGroupNames(getSecurityGroupNames());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean autoAssignFloatingIp = false;
|
private boolean autoAssignFloatingIp = false;
|
||||||
|
private Set<String> securityGroupNames = ImmutableSet.of();
|
||||||
|
|
||||||
public static final NovaTemplateOptions NONE = new NovaTemplateOptions();
|
public static final NovaTemplateOptions NONE = new NovaTemplateOptions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #isAutoAssignFloatingIp()
|
* @see #shouldAutoAssignFloatingIp()
|
||||||
*/
|
*/
|
||||||
public NovaTemplateOptions autoAssignFloatingIp(boolean enable) {
|
public NovaTemplateOptions autoAssignFloatingIp(boolean enable) {
|
||||||
this.autoAssignFloatingIp = enable;
|
this.autoAssignFloatingIp = enable;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public NovaTemplateOptions securityGroupNames(String... securityGroupNames) {
|
||||||
|
return securityGroupNames(ImmutableSet.copyOf(checkNotNull(securityGroupNames, "securityGroupNames")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public NovaTemplateOptions securityGroupNames(Iterable<String> securityGroupNames) {
|
||||||
|
for (String groupName : checkNotNull(securityGroupNames, "securityGroupNames"))
|
||||||
|
Preconditions2.checkNotEmpty(groupName, "all security groups must be non-empty");
|
||||||
|
this.securityGroupNames = ImmutableSet.copyOf(securityGroupNames);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <h3>Note</h3>
|
||||||
|
*
|
||||||
|
* This requires that {@link NovaClient#getFloatingIPExtensionForZone(String)} to return
|
||||||
|
* {@link Optional#isPresent present}
|
||||||
|
*
|
||||||
* @return true if auto assignment of a floating ip to each vm is enabled
|
* @return true if auto assignment of a floating ip to each vm is enabled
|
||||||
*/
|
*/
|
||||||
public boolean isAutoAssignFloatingIp() {
|
public boolean shouldAutoAssignFloatingIp() {
|
||||||
return autoAssignFloatingIp;
|
return autoAssignFloatingIp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public Set<String> getSecurityGroupNames() {
|
||||||
|
return securityGroupNames;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see NovaTemplateOptions#isAutoAssignFloatingIp()
|
* @see NovaTemplateOptions#shouldAutoAssignFloatingIp()
|
||||||
*/
|
*/
|
||||||
public static NovaTemplateOptions autoAssignFloatingIp(boolean enable) {
|
public static NovaTemplateOptions autoAssignFloatingIp(boolean enable) {
|
||||||
return new NovaTemplateOptions().autoAssignFloatingIp(enable);
|
return new NovaTemplateOptions().autoAssignFloatingIp(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public static NovaTemplateOptions securityGroupNames(String... groupNames) {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
return NovaTemplateOptions.class.cast(options.securityGroupNames(groupNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public static NovaTemplateOptions securityGroupNames(Iterable<String> groupNames) {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
return NovaTemplateOptions.class.cast(options.securityGroupNames(groupNames));
|
||||||
|
}
|
||||||
|
|
||||||
// methods that only facilitate returning the correct object type
|
// methods that only facilitate returning the correct object type
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,7 +201,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
NovaTemplateOptions options = new NovaTemplateOptions();
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
return options.overrideLoginPassword(password);
|
return options.overrideLoginPassword(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateOptions#overrideLoginPrivateKey
|
* @see TemplateOptions#overrideLoginPrivateKey
|
||||||
*/
|
*/
|
||||||
|
@ -155,7 +209,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
NovaTemplateOptions options = new NovaTemplateOptions();
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
return options.overrideLoginPrivateKey(privateKey);
|
return options.overrideLoginPrivateKey(privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateOptions#overrideAuthenticateSudo
|
* @see TemplateOptions#overrideAuthenticateSudo
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -81,11 +81,16 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
|
||||||
|
|
||||||
String zone = template.getLocation().getId();
|
String zone = template.getLocation().getId();
|
||||||
|
|
||||||
if (templateOptions.isAutoAssignFloatingIp()) {
|
if (templateOptions.shouldAutoAssignFloatingIp()) {
|
||||||
checkArgument(novaClient.getFloatingIPExtensionForZone(zone).isPresent(),
|
checkArgument(novaClient.getFloatingIPExtensionForZone(zone).isPresent(),
|
||||||
"Floating IP settings are required by configuration, but the extension is not available!");
|
"Floating IPs are required by options, but the extension is not available! options: %s", templateOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
|
return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +101,7 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
|
||||||
Future<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group, name, template);
|
Future<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group, name, template);
|
||||||
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());
|
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());
|
||||||
|
|
||||||
if (templateOptions.isAutoAssignFloatingIp()) {
|
if (templateOptions.shouldAutoAssignFloatingIp()) {
|
||||||
return Futures.compose(future, allocateAndAddFloatingIpToNode, executor);
|
return Futures.compose(future, allocateAndAddFloatingIpToNode, executor);
|
||||||
} else {
|
} else {
|
||||||
return future;
|
return future;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Objects.ToStringHelper;
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ingress access to a destination protocol on particular ports
|
* Ingress access to a destination protocol on particular ports
|
||||||
|
@ -37,9 +38,9 @@ public class Ingress {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private IpProtocol ipProtocol;
|
protected IpProtocol ipProtocol;
|
||||||
private int fromPort;
|
protected int fromPort;
|
||||||
private int toPort;
|
protected int toPort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -73,9 +74,12 @@ public class Ingress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IpProtocol ipProtocol;
|
@SerializedName(value = "ip_protocol")
|
||||||
private final int fromPort;
|
protected final IpProtocol ipProtocol;
|
||||||
private final int toPort;
|
@SerializedName(value = "from_port")
|
||||||
|
protected final int fromPort;
|
||||||
|
@SerializedName(value = "to_port")
|
||||||
|
protected final int toPort;
|
||||||
|
|
||||||
protected Ingress(IpProtocol ipProtocol, int fromPort, int toPort) {
|
protected Ingress(IpProtocol ipProtocol, int fromPort, int toPort) {
|
||||||
this.fromPort = fromPort;
|
this.fromPort = fromPort;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.domain;
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ public class SecurityGroup {
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private Set<SecurityGroupRule> rules;
|
private Set<SecurityGroupRule> rules = ImmutableSet.<SecurityGroupRule> of();
|
||||||
|
|
||||||
public Builder id(String id) {
|
public Builder id(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -69,6 +71,22 @@ public class SecurityGroup {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @see #getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public Builder rules(SecurityGroupRule... rules) {
|
||||||
|
return rules(ImmutableSet.copyOf(checkNotNull(rules, "rules")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public Builder rules(Iterable<SecurityGroupRule> rules) {
|
||||||
|
this.rules = ImmutableSet.copyOf(checkNotNull(rules, "rules"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder rules(Set<SecurityGroupRule> rules) {
|
public Builder rules(Set<SecurityGroupRule> rules) {
|
||||||
this.rules = rules;
|
this.rules = rules;
|
||||||
return this;
|
return this;
|
||||||
|
@ -79,26 +97,27 @@ public class SecurityGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromSecurityGroup(SecurityGroup in) {
|
public Builder fromSecurityGroup(SecurityGroup in) {
|
||||||
return id(in.getId()).tenantId(in.getTenantId()).name(in.getName()).description(in.getDescription())
|
return id(in.getId()).tenantId(in.getTenantId()).name(in.getName()).description(in.getDescription()).rules(
|
||||||
.rules(in.getRules());
|
in.getRules());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String id;
|
protected final String id;
|
||||||
@SerializedName("tenant_id")
|
@SerializedName("tenant_id")
|
||||||
protected String tenantId;
|
protected final String tenantId;
|
||||||
protected String name;
|
protected final String name;
|
||||||
protected String description;
|
protected final String description;
|
||||||
protected Set<SecurityGroupRule> rules;
|
protected final Set<SecurityGroupRule> rules;
|
||||||
|
|
||||||
protected SecurityGroup(String id, String tenantId, @Nullable String name, @Nullable String description,
|
protected SecurityGroup(String id, String tenantId, @Nullable String name, @Nullable String description,
|
||||||
Set<SecurityGroupRule> rules) {
|
Set<SecurityGroupRule> rules) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.rules = ImmutableSet.copyOf(checkNotNull(rules, "rules"));
|
// if empty, leave null so this doesn't serialize to json
|
||||||
|
this.rules = checkNotNull(rules, "rules").size() == 0 ? null : ImmutableSet.copyOf(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -118,62 +137,31 @@ public class SecurityGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<SecurityGroupRule> getRules() {
|
public Set<SecurityGroupRule> getRules() {
|
||||||
return this.rules;
|
return this.rules == null ? ImmutableSet.<SecurityGroupRule> of() : rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object instanceof SecurityGroup) {
|
||||||
|
final SecurityGroup other = SecurityGroup.class.cast(object);
|
||||||
|
return equal(tenantId, other.tenantId) && equal(id, other.id) && equal(name, other.name);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
return Objects.hashCode(tenantId, id, name);
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
|
||||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
|
||||||
result = prime * result + ((rules == null) ? 0 : rules.hashCode());
|
|
||||||
result = prime * result + ((tenantId == null) ? 0 : tenantId.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
SecurityGroup other = (SecurityGroup) obj;
|
|
||||||
if (description == null) {
|
|
||||||
if (other.description != null)
|
|
||||||
return false;
|
|
||||||
} else if (!description.equals(other.description))
|
|
||||||
return false;
|
|
||||||
if (id == null) {
|
|
||||||
if (other.id != null)
|
|
||||||
return false;
|
|
||||||
} else if (!id.equals(other.id))
|
|
||||||
return false;
|
|
||||||
if (name == null) {
|
|
||||||
if (other.name != null)
|
|
||||||
return false;
|
|
||||||
} else if (!name.equals(other.name))
|
|
||||||
return false;
|
|
||||||
if (rules == null) {
|
|
||||||
if (other.rules != null)
|
|
||||||
return false;
|
|
||||||
} else if (!rules.equals(other.rules))
|
|
||||||
return false;
|
|
||||||
if (tenantId == null) {
|
|
||||||
if (other.tenantId != null)
|
|
||||||
return false;
|
|
||||||
} else if (!tenantId.equals(other.tenantId))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toStringHelper("").add("id", id).add("name", name).add("tenantId", tenantId)
|
return toStringHelper("").add("tenantId", getTenantId()).add("id", getId()).add("name", getName()).add(
|
||||||
.add("description", description).add("rules", rules).toString();
|
"description", description).add("rules", getRules()).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,16 +19,18 @@
|
||||||
package org.jclouds.openstack.nova.v1_1.domain;
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ForwardingObject;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a security group rule
|
* Defines a security group rule
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SecurityGroupRule implements Comparable<SecurityGroupRule> {
|
public class SecurityGroupRule extends Ingress {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
|
@ -38,125 +40,113 @@ public class SecurityGroupRule implements Comparable<SecurityGroupRule> {
|
||||||
return builder().fromSecurityGroupRule(this);
|
return builder().fromSecurityGroupRule(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder extends Ingress.Builder {
|
||||||
private String id;
|
private String id;
|
||||||
private int fromPort;
|
|
||||||
private Map<String, String> group;
|
|
||||||
// tcp/udp/icmp - move to enum
|
|
||||||
private IpProtocol ipProtocol;
|
|
||||||
|
|
||||||
private int toPort;
|
|
||||||
private String parentGroupId;
|
private String parentGroupId;
|
||||||
|
private TenantIdAndName group;
|
||||||
private Map<String, String> ipRange;
|
private String ipRange;
|
||||||
|
|
||||||
public Builder id(String id) {
|
public Builder id(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromPort(int fromPort) {
|
public Builder group(TenantIdAndName group) {
|
||||||
this.fromPort = fromPort;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder group(Map<String, String> group) {
|
|
||||||
this.group = group;
|
this.group = group;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder ipProtocol(IpProtocol ipProtocol) {
|
|
||||||
this.ipProtocol = ipProtocol;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder toPort(int toPort) {
|
|
||||||
this.toPort = toPort;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder parentGroupId(String parentGroupId) {
|
public Builder parentGroupId(String parentGroupId) {
|
||||||
this.parentGroupId = parentGroupId;
|
this.parentGroupId = parentGroupId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder ipRange(Map<String, String> ipRange) {
|
public Builder ipRange(String ipRange) {
|
||||||
this.ipRange = ipRange;
|
this.ipRange = ipRange;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public SecurityGroupRule build() {
|
public SecurityGroupRule build() {
|
||||||
return new SecurityGroupRule(id, fromPort, group, ipProtocol, toPort, parentGroupId, ipRange);
|
return new SecurityGroupRule(ipProtocol, fromPort, toPort, id, parentGroupId, group, ipRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromSecurityGroupRule(SecurityGroupRule in) {
|
public Builder fromSecurityGroupRule(SecurityGroupRule in) {
|
||||||
return id(in.getId()).fromPort(in.getFromPort()).group(in.getGroup()).ipProtocol(in.getIpProtocol())
|
return id(in.getId()).fromPort(in.getFromPort()).group(in.getGroup()).ipProtocol(in.getIpProtocol()).toPort(
|
||||||
.toPort(in.getToPort()).parentGroupId(in.getParentGroupId()).ipRange(in.getIpRange());
|
in.getToPort()).parentGroupId(in.getParentGroupId()).ipRange(in.getIpRange());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder ipProtocol(IpProtocol ipProtocol) {
|
||||||
|
super.ipProtocol(ipProtocol);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder fromPort(int fromPort) {
|
||||||
|
super.fromPort(fromPort);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder toPort(int toPort) {
|
||||||
|
super.toPort(toPort);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String id;
|
||||||
|
|
||||||
|
protected final TenantIdAndName group;
|
||||||
|
|
||||||
|
@SerializedName(value = "parent_group_id")
|
||||||
|
protected final String parentGroupId;
|
||||||
|
|
||||||
|
// type to get around unnecessary structure
|
||||||
|
private static class Cidr extends ForwardingObject {
|
||||||
|
private String cidr;
|
||||||
|
|
||||||
|
private Cidr(String cidr) {
|
||||||
|
this.cidr = cidr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object delegate() {
|
||||||
|
return cidr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String id;
|
|
||||||
|
|
||||||
@SerializedName(value = "from_port")
|
|
||||||
protected int fromPort;
|
|
||||||
|
|
||||||
protected Map<String, String> group;
|
|
||||||
|
|
||||||
@SerializedName(value = "ip_protocol")
|
|
||||||
// tcp/udp/icmp
|
|
||||||
protected IpProtocol ipProtocol;
|
|
||||||
|
|
||||||
@SerializedName(value = "to_port")
|
|
||||||
protected int toPort;
|
|
||||||
|
|
||||||
@SerializedName(value = "parent_group_id")
|
|
||||||
protected String parentGroupId;
|
|
||||||
|
|
||||||
@SerializedName(value = "ip_range")
|
@SerializedName(value = "ip_range")
|
||||||
protected Map<String, String> ipRange;
|
protected final Cidr ipRange;
|
||||||
|
|
||||||
protected SecurityGroupRule(String id, int fromPort, Map<String, String> group, IpProtocol ipProtocol, int toPort,
|
protected SecurityGroupRule(IpProtocol ipProtocol, int fromPort, int toPort, String id, String parentGroupId,
|
||||||
String parentGroupId, Map<String, String> ipRange) {
|
@Nullable TenantIdAndName group, @Nullable String ipRange) {
|
||||||
this.id = id;
|
super(ipProtocol, fromPort, toPort);
|
||||||
this.fromPort = fromPort;
|
this.parentGroupId = checkNotNull(parentGroupId, "parentGroupId");
|
||||||
|
this.id = checkNotNull(id, "id");
|
||||||
this.group = group;
|
this.group = group;
|
||||||
this.ipProtocol = ipProtocol;
|
this.ipRange = ipRange != null ? new Cidr(ipRange) : null;
|
||||||
this.toPort = toPort;
|
|
||||||
this.parentGroupId = parentGroupId;
|
|
||||||
this.ipRange = ipRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFromPort() {
|
|
||||||
return this.fromPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getGroup() {
|
|
||||||
return this.group;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IpProtocol getIpProtocol() {
|
|
||||||
return this.ipProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getToPort() {
|
|
||||||
return this.toPort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParentGroupId() {
|
public String getParentGroupId() {
|
||||||
return this.parentGroupId;
|
return this.parentGroupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getIpRange() {
|
public String getId() {
|
||||||
return this.ipRange;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Nullable
|
||||||
public int compareTo(SecurityGroupRule o) {
|
public TenantIdAndName getGroup() {
|
||||||
return this.id.compareTo(o.getId());
|
if (this.group == null || this.group.getName() == null)
|
||||||
|
return null;
|
||||||
|
return this.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getIpRange() {
|
||||||
|
return this.ipRange == null ? null : ipRange.cidr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -213,9 +203,9 @@ public class SecurityGroupRule implements Comparable<SecurityGroupRule> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toStringHelper("").add("id", id).add("fromPort", fromPort).add("group", group)
|
return toStringHelper("").add("id", id).add("fromPort", fromPort).add("group", getGroup()).add("ipProtocol",
|
||||||
.add("ipProtocol", ipProtocol).add("toPort", toPort).add("parentGroupId", parentGroupId)
|
ipProtocol).add("toPort", toPort).add("parentGroupId", parentGroupId).add("ipRange", getIpRange())
|
||||||
.add("ipRange", ipRange).toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* 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 static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class TenantIdAndName {
|
||||||
|
|
||||||
|
@SerializedName("tenant_id")
|
||||||
|
protected final String tenantId;
|
||||||
|
protected final String name;
|
||||||
|
|
||||||
|
public TenantIdAndName(String tenantId, String name) {
|
||||||
|
this.tenantId = checkNotNull(tenantId, "tenantId");
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
TenantIdAndName that = TenantIdAndName.class.cast(o);
|
||||||
|
return equal(this.tenantId, that.tenantId) && equal(this.name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(tenantId, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("").add("tenantId", tenantId).add("name", name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,15 +72,15 @@ public interface SecurityGroupClient {
|
||||||
*
|
*
|
||||||
* @return a new Security Group Rule
|
* @return a new Security Group Rule
|
||||||
*/
|
*/
|
||||||
SecurityGroupRule createSecurityGroupRuleAllowingCidrBlock(String parent_group_id, Ingress ip_protocol, String cidr);
|
SecurityGroupRule createSecurityGroupRuleAllowingCidrBlock(String parentGroup, Ingress ingress, String sourceCidr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Security Group Rule.
|
* Create a Security Group Rule.
|
||||||
*
|
*
|
||||||
* @return a new Security Group Rule
|
* @return a new Security Group Rule
|
||||||
*/
|
*/
|
||||||
SecurityGroupRule createSecurityGroupRuleAllowingSecurityGroupId(String group_id, Ingress ip_protocol,
|
SecurityGroupRule createSecurityGroupRuleAllowingSecurityGroupId(String parentGroup, Ingress ingress,
|
||||||
String parent_group_id);
|
String sourceCidr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a Security Group Rule.
|
* Delete a Security Group Rule.
|
||||||
|
|
|
@ -24,18 +24,22 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.encryption.internal.Base64;
|
import org.jclouds.encryption.internal.Base64;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
|
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
|
||||||
import org.jclouds.rest.MapBinder;
|
import org.jclouds.rest.MapBinder;
|
||||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
import org.jclouds.util.Preconditions2;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -85,7 +89,7 @@ public class CreateServerOptions implements MapBinder {
|
||||||
List<File> personality;
|
List<File> personality;
|
||||||
String key_name;
|
String key_name;
|
||||||
@SerializedName(value = "security_groups")
|
@SerializedName(value = "security_groups")
|
||||||
Set<SecurityGroup> securityGroups;
|
Set<SecurityGroup> securityGroupNames;
|
||||||
|
|
||||||
private ServerRequest(String name, String imageRef, String flavorRef) {
|
private ServerRequest(String name, String imageRef, String flavorRef) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -97,7 +101,7 @@ public class CreateServerOptions implements MapBinder {
|
||||||
|
|
||||||
private Map<String, String> metadata = Maps.newHashMap();
|
private Map<String, String> metadata = Maps.newHashMap();
|
||||||
private List<File> files = Lists.newArrayList();
|
private List<File> files = Lists.newArrayList();
|
||||||
private Set<String> securityGroups = Sets.newHashSet();
|
private Set<String> securityGroupNames = Sets.newHashSet();
|
||||||
private String keyName;
|
private String keyName;
|
||||||
private String adminPass;
|
private String adminPass;
|
||||||
|
|
||||||
|
@ -112,11 +116,11 @@ public class CreateServerOptions implements MapBinder {
|
||||||
server.personality = files;
|
server.personality = files;
|
||||||
if (keyName != null)
|
if (keyName != null)
|
||||||
server.key_name = keyName;
|
server.key_name = keyName;
|
||||||
if (securityGroups.size() > 0) {
|
if (securityGroupNames.size() > 0) {
|
||||||
server.securityGroups = Sets.newHashSet();
|
server.securityGroupNames = Sets.newHashSet();
|
||||||
for (String groupName : securityGroups) {
|
for (String groupName : securityGroupNames) {
|
||||||
SecurityGroup group = SecurityGroup.builder().name(groupName).build();
|
SecurityGroup group = SecurityGroup.builder().name(groupName).build();
|
||||||
server.securityGroups.add(group);
|
server.securityGroupNames.add(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (adminPass != null) {
|
if (adminPass != null) {
|
||||||
|
@ -192,19 +196,39 @@ public class CreateServerOptions implements MapBinder {
|
||||||
this.keyName = keyName;
|
this.keyName = keyName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the security group name to be used when creating a server.
|
|
||||||
*
|
*
|
||||||
* @param groupName
|
* <h3>Note</h3>
|
||||||
* @return
|
*
|
||||||
|
* This requires that {@link NovaClient#getSecurityGroupExtensionForZone(String)} to return
|
||||||
|
* {@link Optional#isPresent present}
|
||||||
|
*
|
||||||
|
* @return security groups the user specified to run servers with; zero length will create an
|
||||||
|
* implicit group starting with {@code jclouds#}
|
||||||
*/
|
*/
|
||||||
public CreateServerOptions withSecurityGroup(String groupName) {
|
public Set<String> getSecurityGroupNames() {
|
||||||
checkNotNull(groupName, "groupName");
|
return securityGroupNames;
|
||||||
this.securityGroups.add(groupName);
|
}
|
||||||
return this;
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @see #getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public CreateServerOptions securityGroupNames(String... securityGroupNames) {
|
||||||
|
return securityGroupNames(ImmutableSet.copyOf(checkNotNull(securityGroupNames, "securityGroupNames")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public CreateServerOptions securityGroupNames(Iterable<String> securityGroupNames) {
|
||||||
|
for (String groupName : checkNotNull(securityGroupNames, "securityGroupNames"))
|
||||||
|
Preconditions2.checkNotEmpty(groupName, "all security groups must be non-empty");
|
||||||
|
this.securityGroupNames = ImmutableSet.copyOf(securityGroupNames);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,13 +259,21 @@ public class CreateServerOptions implements MapBinder {
|
||||||
CreateServerOptions options = new CreateServerOptions();
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
return options.withKeyName(keyName);
|
return options.withKeyName(keyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
|
*/
|
||||||
|
public static CreateServerOptions securityGroupNames(String... groupNames) {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
return CreateServerOptions.class.cast(options.securityGroupNames(groupNames));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CreateServerOptions#withGroupName(String)
|
* @see CreateServerOptions#getSecurityGroupNames
|
||||||
*/
|
*/
|
||||||
public static CreateServerOptions withSecurityGroup(String name) {
|
public static CreateServerOptions securityGroupNames(Iterable<String> groupNames) {
|
||||||
CreateServerOptions options = new CreateServerOptions();
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
return options.withSecurityGroup(name);
|
return CreateServerOptions.class.cast(options.securityGroupNames(groupNames));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* 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.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
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.extensions.SecurityGroupClient;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AtomicReference is so that we can return the securityGroup that matched.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class FindSecurityGroupWithNameAndReturnTrue implements Predicate<AtomicReference<ZoneAndName>> {
|
||||||
|
|
||||||
|
private final NovaClient novaClient;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public FindSecurityGroupWithNameAndReturnTrue(NovaClient novaClient) {
|
||||||
|
this.novaClient = checkNotNull(novaClient, "novaClient");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean apply(AtomicReference<ZoneAndName> securityGroupInZoneRef) {
|
||||||
|
checkNotNull(securityGroupInZoneRef, "securityGroupRef");
|
||||||
|
final ZoneAndName securityGroupInZone = checkNotNull(securityGroupInZoneRef.get(), "securityGroupInZone");
|
||||||
|
|
||||||
|
Optional<SecurityGroupClient> client = novaClient.getSecurityGroupExtensionForZone(securityGroupInZone.getZone());
|
||||||
|
checkArgument(client.isPresent(), "Security groups are required, but the extension is not available!");
|
||||||
|
|
||||||
|
logger.trace("looking for security group %s", securityGroupInZone.slashEncode());
|
||||||
|
try {
|
||||||
|
SecurityGroup returnVal = Iterables.find(client.get().listSecurityGroups(), new Predicate<SecurityGroup>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(SecurityGroup input) {
|
||||||
|
return input.getName().equals(securityGroupInZone.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
securityGroupInZoneRef.set(new SecurityGroupInZone(returnVal, securityGroupInZone.getZone()));
|
||||||
|
return true;
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,12 @@ package org.jclouds.openstack.nova.v1_1.reference;
|
||||||
* @author Adam Lowe
|
* @author Adam Lowe
|
||||||
*/
|
*/
|
||||||
public class NovaConstants {
|
public class NovaConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eventual consistency delay for retrieving a security group after it is created (in ms)
|
||||||
|
*/
|
||||||
|
public static final String PROPERTY_NOVA_TIMEOUT_SECURITYGROUP_PRESENT = "jclouds.openstack-nova.timeout.securitygroup-present";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whenever a node is created, automatically allocate and assign a floating ip address, also
|
* Whenever a node is created, automatically allocate and assign a floating ip address, also
|
||||||
* deallocate when the node is destroyed.
|
* deallocate when the node is destroyed.
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* 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 org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||||
|
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.internal.BaseNovaComputeServiceContextExpectTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the compute service abstraction of the nova client.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "NovaComputeServiceAdapterExpectTest")
|
||||||
|
public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceContextExpectTest<Injector> {
|
||||||
|
|
||||||
|
public void testCreateNodeWithGroupEncodedIntoNameWhenSecurityGroupsArePresent() throws Exception {
|
||||||
|
|
||||||
|
HttpRequest createServer = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(URI.create("https://compute.north.host/v1.1/3456/servers"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
|
||||||
|
.put("X-Auth-Token", authToken).build())
|
||||||
|
.payload(payloadFromStringWithContentType(
|
||||||
|
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"security_groups\":[{\"name\":\"group2\"},{\"name\":\"group1\"}]}}","application/json"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||||
|
.payload(payloadFromResourceWithContentType("/new_server.json","application/json; charset=UTF-8")).build();
|
||||||
|
|
||||||
|
|
||||||
|
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
|
||||||
|
.put(keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess)
|
||||||
|
.put(extensionsOfNovaRequest, extensionsOfNovaResponse)
|
||||||
|
.put(listImagesDetail, listImagesDetailResponse)
|
||||||
|
.put(listFlavorsDetail, listFlavorsDetailResponse)
|
||||||
|
.put(createServer, createServerResponse).build();
|
||||||
|
|
||||||
|
Injector forSecurityGroups = requestsSendResponses(requestResponseMap);
|
||||||
|
|
||||||
|
Template template = forSecurityGroups.getInstance(TemplateBuilder.class).build();
|
||||||
|
template.getOptions().as(NovaTemplateOptions.class).securityGroupNames("group1", "group2");
|
||||||
|
|
||||||
|
NovaComputeServiceAdapter adapter = forSecurityGroups.getInstance(NovaComputeServiceAdapter.class);
|
||||||
|
|
||||||
|
NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92",
|
||||||
|
template);
|
||||||
|
assertNotNull(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Injector apply(ComputeServiceContext input) {
|
||||||
|
return input.utils().injector();
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,38 +46,7 @@ import com.google.common.collect.ImmutableMultimap;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "NovaComputeServiceExpectTest")
|
@Test(groups = "unit", testName = "NovaComputeServiceExpectTest")
|
||||||
public class NovaComputeServiceExpectTest extends BaseNovaComputeServiceExpectTest {
|
public class NovaComputeServiceExpectTest extends BaseNovaComputeServiceExpectTest {
|
||||||
HttpRequest listImagesDetail = HttpRequest.builder().method("GET").endpoint(
|
|
||||||
URI.create("https://compute.north.host/v1.1/3456/images/detail")).headers(
|
|
||||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
|
||||||
authToken).build()).build();
|
|
||||||
|
|
||||||
HttpResponse listImagesDetailResponse = HttpResponse.builder().statusCode(200).payload(
|
|
||||||
payloadFromResource("/image_list_detail.json")).build();
|
|
||||||
|
|
||||||
HttpRequest listFlavorsDetail = HttpRequest.builder().method("GET").endpoint(
|
|
||||||
URI.create("https://compute.north.host/v1.1/3456/flavors/detail")).headers(
|
|
||||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
|
||||||
authToken).build()).build();
|
|
||||||
|
|
||||||
HttpResponse listFlavorsDetailResponse = HttpResponse.builder().statusCode(200).payload(
|
|
||||||
payloadFromResource("/flavor_list_detail.json")).build();
|
|
||||||
|
|
||||||
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
|
|
||||||
URI.create("https://compute.north.host/v1.1/3456/servers/detail")).headers(
|
|
||||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
|
||||||
authToken).build()).build();
|
|
||||||
|
|
||||||
HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
|
|
||||||
payloadFromResource("/server_list_details.json")).build();
|
|
||||||
|
|
||||||
HttpRequest listFloatingIps = HttpRequest.builder().method("GET").endpoint(
|
|
||||||
URI.create("https://compute.north.host/v1.1/3456/os-floating-ips")).headers(
|
|
||||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
|
||||||
authToken).build()).build();
|
|
||||||
|
|
||||||
HttpResponse listFloatingIpsResponse = HttpResponse.builder().statusCode(200).payload(
|
|
||||||
payloadFromResource("/floatingip_list.json")).build();
|
|
||||||
|
|
||||||
public void testListServersWhenResponseIs2xx() throws Exception {
|
public void testListServersWhenResponseIs2xx() throws Exception {
|
||||||
|
|
||||||
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put(
|
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put(
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
/**
|
||||||
|
* 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.options;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions.Builder.authorizePublicKey;
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions.Builder.autoAssignFloatingIp;
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions.Builder.blockOnPort;
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions.Builder.inboundPorts;
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions.Builder.installPrivateKey;
|
||||||
|
import static org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions.Builder.securityGroupNames;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests possible uses of NovaTemplateOptions and NovaTemplateOptions.Builder.*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(testName = "NovaTemplateOptionsTest")
|
||||||
|
public class NovaTemplateOptionsTest {
|
||||||
|
|
||||||
|
public void testAs() {
|
||||||
|
TemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assertEquals(options.as(NovaTemplateOptions.class), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testsecurityGroupNamesIterableBadFormat() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.securityGroupNames(ImmutableSet.of("group1", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testsecurityGroupNamesIterable() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.securityGroupNames(ImmutableSet.of("group1", "group2"));
|
||||||
|
assertEquals(options.getSecurityGroupNames(), ImmutableSet.of("group1", "group2"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testsecurityGroupNamesIterableStatic() {
|
||||||
|
NovaTemplateOptions options = securityGroupNames(ImmutableSet.of("group1", "group2"));
|
||||||
|
assertEquals(options.getSecurityGroupNames(), ImmutableSet.of("group1", "group2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testsecurityGroupNamesVarArgsBadFormat() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.securityGroupNames("mygroup", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testsecurityGroupNamesVarArgs() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.securityGroupNames("group1", "group2");
|
||||||
|
assertEquals(options.getSecurityGroupNames(), ImmutableSet.of("group1", "group2"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultGroupsVarArgsEmpty() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assertEquals(options.getSecurityGroupNames(), ImmutableSet.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testsecurityGroupNamesVarArgsStatic() {
|
||||||
|
NovaTemplateOptions options = securityGroupNames("group1", "group2");
|
||||||
|
assertEquals(options.getSecurityGroupNames(), ImmutableSet.of("group1", "group2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testautoAssignFloatingIpDefault() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assert !options.shouldAutoAssignFloatingIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testautoAssignFloatingIp() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions().autoAssignFloatingIp(true);
|
||||||
|
assert options.shouldAutoAssignFloatingIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testautoAssignFloatingIpStatic() {
|
||||||
|
NovaTemplateOptions options = autoAssignFloatingIp(true);
|
||||||
|
assert options.shouldAutoAssignFloatingIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// superclass tests
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testinstallPrivateKeyBadFormat() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.installPrivateKey("whompy");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testinstallPrivateKey() throws IOException {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
|
||||||
|
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullinstallPrivateKey() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assertEquals(options.getPrivateKey(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testinstallPrivateKeyStatic() throws IOException {
|
||||||
|
NovaTemplateOptions options = installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
|
||||||
|
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testinstallPrivateKeyNPE() {
|
||||||
|
installPrivateKey(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testauthorizePublicKeyBadFormat() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.authorizePublicKey("whompy");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testauthorizePublicKey() throws IOException {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.authorizePublicKey("ssh-rsa");
|
||||||
|
assertEquals(options.getPublicKey(), "ssh-rsa");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullauthorizePublicKey() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assertEquals(options.getPublicKey(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testauthorizePublicKeyStatic() throws IOException {
|
||||||
|
NovaTemplateOptions options = authorizePublicKey("ssh-rsa");
|
||||||
|
assertEquals(options.getPublicKey(), "ssh-rsa");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testauthorizePublicKeyNPE() {
|
||||||
|
authorizePublicKey(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testblockOnPortBadFormat() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.blockOnPort(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testblockOnPort() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.blockOnPort(22, 30);
|
||||||
|
assertEquals(options.getPort(), 22);
|
||||||
|
assertEquals(options.getSeconds(), 30);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullblockOnPort() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assertEquals(options.getPort(), -1);
|
||||||
|
assertEquals(options.getSeconds(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testblockOnPortStatic() {
|
||||||
|
NovaTemplateOptions options = blockOnPort(22, 30);
|
||||||
|
assertEquals(options.getPort(), 22);
|
||||||
|
assertEquals(options.getSeconds(), 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testinboundPortsBadFormat() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.inboundPorts(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testinboundPorts() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
options.inboundPorts(22, 30);
|
||||||
|
assertEquals(options.getInboundPorts()[0], 22);
|
||||||
|
assertEquals(options.getInboundPorts()[1], 30);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultOpen22() {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
assertEquals(options.getInboundPorts()[0], 22);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testinboundPortsStatic() {
|
||||||
|
NovaTemplateOptions options = inboundPorts(22, 30);
|
||||||
|
assertEquals(options.getInboundPorts()[0], 22);
|
||||||
|
assertEquals(options.getInboundPorts()[1], 30);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,6 @@ import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupListTest;
|
||||||
import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupTest;
|
import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
@ -233,8 +232,8 @@ public class SecurityGroupClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecurityGroupRule createSecurityGroupRuleExpected() {
|
private SecurityGroupRule createSecurityGroupRuleExpected() {
|
||||||
return SecurityGroupRule.builder().fromPort(80).group(ImmutableMap.<String, String> of()).id("218").ipProtocol(
|
return SecurityGroupRule.builder().fromPort(80).id("218").ipProtocol(
|
||||||
IpProtocol.TCP).ipRange(ImmutableMap.of("cidr", "0.0.0.0/0")).parentGroupId("161").toPort(8080).build();
|
IpProtocol.TCP).ipRange("0.0.0.0/0").parentGroupId("161").toPort(8080).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
|
||||||
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code SecurityGroupClient}
|
* Tests behavior of {@code SecurityGroupClient}
|
||||||
*
|
*
|
||||||
|
@ -73,20 +75,20 @@ public class SecurityGroupClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
SecurityGroup securityGroup = null;
|
SecurityGroup securityGroup = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
securityGroup = client
|
securityGroup = client.createSecurityGroupWithNameAndDescription(SECURITY_GROUP_NAME, "test security group");
|
||||||
.createSecurityGroupWithNameAndDescription(SECURITY_GROUP_NAME, "test security group");
|
|
||||||
assertNotNull(securityGroup);
|
assertNotNull(securityGroup);
|
||||||
|
|
||||||
SecurityGroupRule rule = client.createSecurityGroupRuleAllowingCidrBlock(securityGroup.getId(), Ingress
|
for (int port : ImmutableSet.of(22, 8080)) {
|
||||||
.builder().ipProtocol(IpProtocol.TCP).fromPort(443).toPort(443).build(), "0.0.0.0/0");
|
SecurityGroupRule rule = client.createSecurityGroupRuleAllowingCidrBlock(securityGroup.getId(), Ingress
|
||||||
assertNotNull(rule);
|
.builder().ipProtocol(IpProtocol.TCP).fromPort(port).toPort(port).build(), "0.0.0.0/0");
|
||||||
|
assertNotNull(rule);
|
||||||
|
|
||||||
SecurityGroupRule rule2 = client.createSecurityGroupRuleAllowingSecurityGroupId(securityGroup.getId(),
|
SecurityGroupRule rule2 = client.createSecurityGroupRuleAllowingSecurityGroupId(securityGroup.getId(),
|
||||||
Ingress.builder().ipProtocol(IpProtocol.TCP).fromPort(443).toPort(443).build(), securityGroup
|
Ingress.builder().ipProtocol(IpProtocol.TCP).fromPort(port).toPort(port).build(), securityGroup
|
||||||
.getId());
|
.getId());
|
||||||
|
|
||||||
assertNotNull(rule2);
|
|
||||||
|
|
||||||
|
assertNotNull(rule2);
|
||||||
|
}
|
||||||
securityGroup = client.getSecurityGroup(securityGroup.getId());
|
securityGroup = client.getSecurityGroup(securityGroup.getId());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateServerOptions;
|
||||||
import org.jclouds.openstack.nova.v1_1.parse.ParseCreatedServerTest;
|
import org.jclouds.openstack.nova.v1_1.parse.ParseCreatedServerTest;
|
||||||
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
|
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -103,4 +104,30 @@ public class ServerClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
new ParseCreatedServerTest().expected().toString());
|
new ParseCreatedServerTest().expected().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateServerWithSecurityGroupsWhenResponseIs202() throws Exception {
|
||||||
|
|
||||||
|
HttpRequest createServer = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(URI.create("https://compute.north.host/v1.1/3456/servers"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
|
||||||
|
.put("X-Auth-Token", authToken).build())
|
||||||
|
.payload(payloadFromStringWithContentType(
|
||||||
|
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"security_groups\":[{\"name\":\"group2\"},{\"name\":\"group1\"}]}}","application/json"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||||
|
.payload(payloadFromResourceWithContentType("/new_server.json","application/json; charset=UTF-8")).build();
|
||||||
|
|
||||||
|
|
||||||
|
NovaClient clientWithNewServer = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
|
||||||
|
responseWithKeystoneAccess, createServer, createServerResponse);
|
||||||
|
|
||||||
|
assertEquals(clientWithNewServer.getServerClientForZone("az-1.region-a.geo-1").createServer("test-e92", "1241",
|
||||||
|
"100", new CreateServerOptions().securityGroupNames("group1", "group2")).toString(),
|
||||||
|
new ParseCreatedServerTest().expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
/**
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
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.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.parse.ParseComputeServiceTypicalSecurityGroupTest;
|
||||||
|
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.ImmutableMap.Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "CreateSecurityGroupInZoneExpectTest")
|
||||||
|
public class CreateSecurityGroupInZoneExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
|
||||||
|
public void testUpdateReferenceWhenSecurityGroupListContainsGroupName() 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(
|
||||||
|
String.format("{\"security_group\": {\"rules\": [], \"tenant_id\": \"37936628937291\", \"id\": %s, \"name\": \"jclouds#mygroup\", \"description\": \"jclouds#mygroup\"}}", groupId),
|
||||||
|
"application/json; charset=UTF-8")).build();
|
||||||
|
|
||||||
|
builder.put(createSecurityGroup, createSecurityGroupResponse);
|
||||||
|
|
||||||
|
int ruleId = 10331;
|
||||||
|
|
||||||
|
for (int port : ImmutableList.of(22,8080)){
|
||||||
|
|
||||||
|
HttpRequest createCidrRule = HttpRequest.builder().method("POST").endpoint(
|
||||||
|
URI.create("https://compute.north.host/v1.1/3456/os-security-group-rules")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||||
|
authToken).build())
|
||||||
|
.payload(
|
||||||
|
payloadFromStringWithContentType(
|
||||||
|
String.format("{\"security_group_rule\":{\"parent_group_id\":\"%s\",\"cidr\":\"0.0.0.0/0\",\"ip_protocol\":\"tcp\",\"from_port\":\"%d\",\"to_port\":\"%d\"}}",
|
||||||
|
groupId, port, port), "application/json")).build();
|
||||||
|
|
||||||
|
HttpResponse createCidrRuleResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(
|
||||||
|
payloadFromStringWithContentType(
|
||||||
|
String.format("{\"security_group_rule\": {\"from_port\": %d, \"group\": {}, \"ip_protocol\": \"tcp\", \"to_port\": %d, \"parent_group_id\": %d, \"ip_range\": {\"cidr\": \"0.0.0.0/0\"}, \"id\": %d}}",
|
||||||
|
port, port, groupId, ruleId++), "application/json; charset=UTF-8")).build();
|
||||||
|
|
||||||
|
builder.put(createCidrRule, createCidrRuleResponse);
|
||||||
|
|
||||||
|
HttpRequest createSelfRule = HttpRequest.builder().method("POST").endpoint(
|
||||||
|
URI.create("https://compute.north.host/v1.1/3456/os-security-group-rules")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||||
|
authToken).build())
|
||||||
|
.payload(
|
||||||
|
payloadFromStringWithContentType(
|
||||||
|
String.format("{\"security_group_rule\":{\"group_id\":\"%d\",\"parent_group_id\":\"%d\",\"ip_protocol\":\"tcp\",\"from_port\":\"%d\",\"to_port\":\"%d\"}}",
|
||||||
|
groupId, groupId, port, port), "application/json")).build();
|
||||||
|
|
||||||
|
// note server responds with group name in the rule!!
|
||||||
|
HttpResponse createSelfRuleResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(
|
||||||
|
payloadFromStringWithContentType(
|
||||||
|
String.format("{\"security_group_rule\": {\"from_port\": %d, \"group\": {\"tenant_id\": \"37936628937291\", \"name\": \"jclouds#mygroup\"}, \"ip_protocol\": \"tcp\", \"to_port\": %d, \"parent_group_id\": %d, \"ip_range\": {}, \"id\": %d}}",
|
||||||
|
port, port, groupId, ruleId++), "application/json; charset=UTF-8")).build();
|
||||||
|
|
||||||
|
builder.put(createSelfRule, createSelfRuleResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequest getSecurityGroup = HttpRequest.builder().method("GET").endpoint(
|
||||||
|
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());
|
||||||
|
|
||||||
|
CreateSecurityGroupInZone fn = new CreateSecurityGroupInZone(clientWhenSecurityGroupsExist);
|
||||||
|
|
||||||
|
// we can find it
|
||||||
|
assertEquals(fn.apply(
|
||||||
|
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds#mygroup", ImmutableList.of(22, 8080)))
|
||||||
|
.toString(), new SecurityGroupInZone(new ParseComputeServiceTypicalSecurityGroupTest().expected(),
|
||||||
|
"az-1.region-a.geo-1").toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
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.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupListTest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.predicates.FindSecurityGroupWithNameAndReturnTrue;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "FindSecurityGroupWithNameAndReturnTrueExpectTest")
|
||||||
|
public class FindSecurityGroupWithNameAndReturnTrueExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
|
||||||
|
public void testUpdateReferenceWhenSecurityGroupListContainsGroupName() throws Exception {
|
||||||
|
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.json")).build();
|
||||||
|
|
||||||
|
NovaClient clientWhenSecurityGroupsExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, listSecurityGroups,
|
||||||
|
listSecurityGroupsResponse);
|
||||||
|
|
||||||
|
FindSecurityGroupWithNameAndReturnTrue predicate = new FindSecurityGroupWithNameAndReturnTrue(
|
||||||
|
clientWhenSecurityGroupsExist);
|
||||||
|
|
||||||
|
AtomicReference<ZoneAndName> securityGroupInZoneRef = new AtomicReference<ZoneAndName>(ZoneAndName
|
||||||
|
.fromZoneAndName("az-1.region-a.geo-1", "name1"));
|
||||||
|
|
||||||
|
// we can find it
|
||||||
|
assertTrue(predicate.apply(securityGroupInZoneRef));
|
||||||
|
|
||||||
|
// the reference is now up to date, and includes the actual group found.
|
||||||
|
assertEquals(securityGroupInZoneRef.get().toString(), new SecurityGroupInZone(Iterables
|
||||||
|
.getOnlyElement(new ParseSecurityGroupListTest().expected()), "az-1.region-a.geo-1").toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDoesNotUpdateReferenceWhenSecurityGroupListMissingGroupName() throws Exception {
|
||||||
|
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.json")).build();
|
||||||
|
|
||||||
|
NovaClient clientWhenSecurityGroupsExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, listSecurityGroups,
|
||||||
|
listSecurityGroupsResponse);
|
||||||
|
|
||||||
|
FindSecurityGroupWithNameAndReturnTrue predicate = new FindSecurityGroupWithNameAndReturnTrue(
|
||||||
|
clientWhenSecurityGroupsExist);
|
||||||
|
|
||||||
|
ZoneAndName zoneAndGroup = ZoneAndName.fromZoneAndName("az-1.region-a.geo-1", "name2");
|
||||||
|
|
||||||
|
AtomicReference<ZoneAndName> securityGroupInZoneRef = new AtomicReference<ZoneAndName>(zoneAndGroup);
|
||||||
|
|
||||||
|
// we cannot find it
|
||||||
|
assertFalse(predicate.apply(securityGroupInZoneRef));
|
||||||
|
|
||||||
|
// the reference is the same
|
||||||
|
assertEquals(securityGroupInZoneRef.get(), zoneAndGroup);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* 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.internal;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.logging.config.NullLoggingModule;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for writing KeyStone Expect tests with the ComputeService abstraction
|
||||||
|
*
|
||||||
|
* @author Matt Stephenson
|
||||||
|
*/
|
||||||
|
public abstract class BaseNovaComputeServiceContextExpectTest<T> extends BaseNovaExpectTest<T> implements
|
||||||
|
Function<ComputeServiceContext, T> {
|
||||||
|
|
||||||
|
protected final HttpRequest listImagesDetail = HttpRequest.builder().method("GET").endpoint(
|
||||||
|
URI.create("https://compute.north.host/v1.1/3456/images/detail")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||||
|
authToken).build()).build();
|
||||||
|
|
||||||
|
protected final HttpResponse listImagesDetailResponse = HttpResponse.builder().statusCode(200).payload(
|
||||||
|
payloadFromResource("/image_list_detail.json")).build();
|
||||||
|
|
||||||
|
protected final HttpRequest listFlavorsDetail = HttpRequest.builder().method("GET").endpoint(
|
||||||
|
URI.create("https://compute.north.host/v1.1/3456/flavors/detail")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||||
|
authToken).build()).build();
|
||||||
|
|
||||||
|
protected final HttpResponse listFlavorsDetailResponse = HttpResponse.builder().statusCode(200).payload(
|
||||||
|
payloadFromResource("/flavor_list_detail.json")).build();
|
||||||
|
|
||||||
|
protected final HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
|
||||||
|
URI.create("https://compute.north.host/v1.1/3456/servers/detail")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||||
|
authToken).build()).build();
|
||||||
|
|
||||||
|
protected final HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
|
||||||
|
payloadFromResource("/server_list_details.json")).build();
|
||||||
|
|
||||||
|
protected final HttpRequest listFloatingIps = HttpRequest.builder().method("GET").endpoint(
|
||||||
|
URI.create("https://compute.north.host/v1.1/3456/os-floating-ips")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||||
|
authToken).build()).build();
|
||||||
|
|
||||||
|
protected final HttpResponse listFloatingIpsResponse = HttpResponse.builder().statusCode(200).payload(
|
||||||
|
payloadFromResource("/floatingip_list.json")).build();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
|
||||||
|
return apply(createComputeServiceContext(fn, module, props));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ComputeServiceContext createComputeServiceContext(Function<HttpRequest, HttpResponse> fn, Module module,
|
||||||
|
Properties props) {
|
||||||
|
return new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, identity, credential,
|
||||||
|
ImmutableSet.<Module> of(new ExpectModule(fn), new NullLoggingModule(), module), props);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,17 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.internal;
|
package org.jclouds.openstack.nova.v1_1.internal;
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpResponse;
|
|
||||||
import org.jclouds.logging.config.NullLoggingModule;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.inject.Module;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for writing KeyStone Expect tests with the ComputeService
|
* Base class for writing KeyStone Expect tests with the ComputeService
|
||||||
|
@ -36,11 +27,11 @@ import com.google.inject.Module;
|
||||||
*
|
*
|
||||||
* @author Matt Stephenson
|
* @author Matt Stephenson
|
||||||
*/
|
*/
|
||||||
public class BaseNovaComputeServiceExpectTest extends BaseNovaExpectTest<ComputeService> {
|
public class BaseNovaComputeServiceExpectTest extends BaseNovaComputeServiceContextExpectTest<ComputeService> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ComputeService createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
|
public ComputeService apply(ComputeServiceContext input) {
|
||||||
return new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, identity, credential,
|
return input.getComputeService();
|
||||||
ImmutableSet.<Module> of(new ExpectModule(fn), new NullLoggingModule(), module), props).getComputeService();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* 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.parse;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.json.BaseItemParserTest;
|
||||||
|
import org.jclouds.json.config.GsonModule;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
|
||||||
|
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.SecurityGroupRule;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.TenantIdAndName;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ParseSecurityGroupTest")
|
||||||
|
public class ParseComputeServiceTypicalSecurityGroupTest extends BaseItemParserTest<SecurityGroup> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/securitygroup_details_computeservice_typical.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SelectJson("security_group")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public SecurityGroup expected() {
|
||||||
|
|
||||||
|
Set<SecurityGroupRule> securityGroupRules = ImmutableSet.<SecurityGroupRule> of(
|
||||||
|
SecurityGroupRule.builder().fromPort(22)
|
||||||
|
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("2769")
|
||||||
|
.ipRange("0.0.0.0/0").id("10331").build(),
|
||||||
|
SecurityGroupRule.builder().fromPort(22).group(new TenantIdAndName("37936628937291", "jclouds#mygroup"))
|
||||||
|
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("2769")
|
||||||
|
.id("10332").build(),
|
||||||
|
SecurityGroupRule.builder().fromPort(8080)
|
||||||
|
.ipProtocol(IpProtocol.TCP).toPort(8080).parentGroupId("2769")
|
||||||
|
.ipRange("0.0.0.0/0").id("10333").build(),
|
||||||
|
SecurityGroupRule.builder().fromPort(8080).group(new TenantIdAndName("37936628937291", "jclouds#mygroup"))
|
||||||
|
.ipProtocol(IpProtocol.TCP).toPort(8080).parentGroupId("2769")
|
||||||
|
.id("10334").build()
|
||||||
|
);
|
||||||
|
|
||||||
|
return SecurityGroup.builder().description("jclouds#mygroup").id("2769").tenantId("37936628937291").rules(securityGroupRules)
|
||||||
|
.name("jclouds#mygroup").build();
|
||||||
|
}
|
||||||
|
protected Injector injector() {
|
||||||
|
return Guice.createInjector(new NovaParserModule(), new GsonModule());
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.parse;
|
package org.jclouds.openstack.nova.v1_1.parse;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -34,7 +32,6 @@ import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -56,17 +53,15 @@ public class ParseSecurityGroupListTest extends BaseSetParserTest<SecurityGroup>
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Set<SecurityGroup> expected() {
|
public Set<SecurityGroup> expected() {
|
||||||
|
|
||||||
Map<String, String> anyCidr = ImmutableMap.<String, String> of("cidr", "0.0.0.0/0");
|
|
||||||
|
|
||||||
Set<SecurityGroupRule> securityGroupRules = ImmutableSet.<SecurityGroupRule> of(
|
Set<SecurityGroupRule> securityGroupRules = ImmutableSet.<SecurityGroupRule> of(
|
||||||
SecurityGroupRule.builder().fromPort(22).group(new HashMap<String, String>())
|
SecurityGroupRule.builder().fromPort(22)
|
||||||
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("3").ipRange(anyCidr)
|
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("3").ipRange("0.0.0.0/0")
|
||||||
.id("107").build(),
|
.id("107").build(),
|
||||||
SecurityGroupRule.builder().fromPort(7600).group(new HashMap<String, String>())
|
SecurityGroupRule.builder().fromPort(7600)
|
||||||
.ipProtocol(IpProtocol.TCP).toPort(7600).parentGroupId("3").ipRange(anyCidr)
|
.ipProtocol(IpProtocol.TCP).toPort(7600).parentGroupId("3").ipRange("0.0.0.0/0")
|
||||||
.id("118").build(),
|
.id("118").build(),
|
||||||
SecurityGroupRule.builder().fromPort(8084).group(new HashMap<String, String>())
|
SecurityGroupRule.builder().fromPort(8084)
|
||||||
.ipProtocol(IpProtocol.TCP).toPort(8084).parentGroupId("3").ipRange(anyCidr)
|
.ipProtocol(IpProtocol.TCP).toPort(8084).parentGroupId("3").ipRange("0.0.0.0/0")
|
||||||
.id("119").build());
|
.id("119").build());
|
||||||
|
|
||||||
return ImmutableSet.of(SecurityGroup.builder().description("description1").id("1").tenantId("tenant1")
|
return ImmutableSet.of(SecurityGroup.builder().description("description1").id("1").tenantId("tenant1")
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.parse;
|
package org.jclouds.openstack.nova.v1_1.parse;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -30,10 +29,10 @@ import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.IpProtocol;
|
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.SecurityGroup;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
|
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.TenantIdAndName;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -44,7 +43,6 @@ import com.google.inject.Injector;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "ParseSecurityGroupTest")
|
@Test(groups = "unit", testName = "ParseSecurityGroupTest")
|
||||||
public class ParseSecurityGroupTest extends BaseItemParserTest<SecurityGroup> {
|
public class ParseSecurityGroupTest extends BaseItemParserTest<SecurityGroup> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String resource() {
|
public String resource() {
|
||||||
return "/securitygroup_details.json";
|
return "/securitygroup_details.json";
|
||||||
|
@ -56,17 +54,17 @@ public class ParseSecurityGroupTest extends BaseItemParserTest<SecurityGroup> {
|
||||||
public SecurityGroup expected() {
|
public SecurityGroup expected() {
|
||||||
|
|
||||||
Set<SecurityGroupRule> securityGroupRules = ImmutableSet.<SecurityGroupRule> of(
|
Set<SecurityGroupRule> securityGroupRules = ImmutableSet.<SecurityGroupRule> of(
|
||||||
SecurityGroupRule.builder().fromPort(22).group(new HashMap<String, String>())
|
SecurityGroupRule.builder().fromPort(22)
|
||||||
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("28")
|
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("28")
|
||||||
.ipRange(ImmutableMap.of("cidr", "10.2.6.0/24")).id("108").build(),
|
.ipRange("10.2.6.0/24").id("108").build(),
|
||||||
SecurityGroupRule.builder().fromPort(22).group(ImmutableMap.of("tenant_id", "admin", "name", "11111"))
|
SecurityGroupRule.builder().fromPort(22).group(new TenantIdAndName("admin", "11111"))
|
||||||
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("28")
|
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("28")
|
||||||
.ipRange(new HashMap<String, String>()).id("109").build());
|
.id("109").build());
|
||||||
|
|
||||||
return SecurityGroup.builder().description("description0").id("0").tenantId("tenant0").rules(securityGroupRules)
|
return SecurityGroup.builder().description("description0").id("0").tenantId("tenant0").rules(securityGroupRules)
|
||||||
.name("name0").build();
|
.name("name0").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Injector injector() {
|
protected Injector injector() {
|
||||||
return Guice.createInjector(new NovaParserModule(), new GsonModule());
|
return Guice.createInjector(new NovaParserModule(), new GsonModule());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
"security_group": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,11 +78,12 @@ public interface MediaAsyncClient {
|
||||||
* @see MediaClient#cloneMedia(URI, CloneMediaParams)
|
* @see MediaClient#cloneMedia(URI, CloneMediaParams)
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
|
@Path("/action/cloneMedia")
|
||||||
@Consumes(VCloudDirectorMediaType.MEDIA)
|
@Consumes(VCloudDirectorMediaType.MEDIA)
|
||||||
@Produces(VCloudDirectorMediaType.CLONE_MEDIA_PARAMS)
|
@Produces(VCloudDirectorMediaType.CLONE_MEDIA_PARAMS)
|
||||||
@JAXBResponseParser
|
@JAXBResponseParser
|
||||||
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
|
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
|
||||||
ListenableFuture<Media> cloneMedia(@EndpointParam URI cloneLink,
|
ListenableFuture<Media> cloneMedia(@EndpointParam URI vdcRef,
|
||||||
@BinderParam(BindToXMLPayload.class) CloneMediaParams params);
|
@BinderParam(BindToXMLPayload.class) CloneMediaParams params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,6 +45,7 @@ import static org.testng.Assert.assertTrue;
|
||||||
import static org.testng.Assert.fail;
|
import static org.testng.Assert.fail;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
|
@ -115,7 +116,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
|
|
||||||
Media sourceMedia = Media.builder()
|
Media sourceMedia = Media.builder()
|
||||||
.type(VCloudDirectorMediaType.MEDIA)
|
.type(VCloudDirectorMediaType.MEDIA)
|
||||||
.name("Test media 1")
|
.name("Test media "+random.nextInt())
|
||||||
.size(iso.length)
|
.size(iso.length)
|
||||||
.imageType(Media.ImageType.ISO)
|
.imageType(Media.ImageType.ISO)
|
||||||
.description("Test media generated by testCreateMedia()")
|
.description("Test media generated by testCreateMedia()")
|
||||||
|
@ -129,6 +130,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
media.getFiles().size()));
|
media.getFiles().size()));
|
||||||
File uploadFile = getFirst(media.getFiles(), null);
|
File uploadFile = getFirst(media.getFiles(), null);
|
||||||
assertNotNull(uploadFile, String.format(OBJ_FIELD_REQ, MEDIA, "files.first"));
|
assertNotNull(uploadFile, String.format(OBJ_FIELD_REQ, MEDIA, "files.first"));
|
||||||
|
assertEquals(uploadFile.getSize(), new Long(iso.length));
|
||||||
assertTrue(equal(uploadFile.getSize(), sourceMedia.getSize()), String.format(OBJ_FIELD_EQ, MEDIA, "uploadFile.size()",
|
assertTrue(equal(uploadFile.getSize(), sourceMedia.getSize()), String.format(OBJ_FIELD_EQ, MEDIA, "uploadFile.size()",
|
||||||
sourceMedia.getSize(), uploadFile.getSize()));
|
sourceMedia.getSize(), uploadFile.getSize()));
|
||||||
|
|
||||||
|
@ -144,14 +146,12 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
media = mediaClient.getMedia(media.getHref());
|
media = mediaClient.getMedia(media.getHref());
|
||||||
|
|
||||||
if (media.getTasks().size() == 1) {
|
if (media.getTasks().size() == 1) {
|
||||||
Task task = Iterables.getOnlyElement(media.getTasks());
|
Task uploadTask = Iterables.getOnlyElement(media.getTasks());
|
||||||
assertEquals(task.getStatus(), "running");
|
Checks.checkTask(uploadTask);
|
||||||
|
assertEquals(uploadTask.getStatus(), "running");
|
||||||
|
assertTrue(retryTaskSuccess.apply(uploadTask), String.format(TASK_COMPLETE_TIMELY, "uploadTask"));
|
||||||
|
media = mediaClient.getMedia(media.getHref());
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = Iterables.getOnlyElement(media.getFiles());
|
|
||||||
assertEquals(file.getSize(), new Long(iso.length));
|
|
||||||
assertEquals(file.getBytesTransferred(), new Long(iso.length));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(testName = "GET /media/{id}", dependsOnMethods = { "testCreateMedia" })
|
@Test(testName = "GET /media/{id}", dependsOnMethods = { "testCreateMedia" })
|
||||||
|
@ -170,8 +170,12 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
dependsOnMethods = { "testGetMedia" })
|
dependsOnMethods = { "testGetMedia" })
|
||||||
public void testGetMediaOwner() {
|
public void testGetMediaOwner() {
|
||||||
Owner directOwner = mediaClient.getOwner(media.getHref());
|
Owner directOwner = mediaClient.getOwner(media.getHref());
|
||||||
assertEquals(owner, directOwner, String.format(GETTER_RETURNS_SAME_OBJ,
|
assertEquals(owner.toBuilder()
|
||||||
"getOwner()", "owner", "media.getOwner()", owner.toString(), directOwner.toString()));
|
.user(owner.getUser().toBuilder().id(null).build())
|
||||||
|
.build(),
|
||||||
|
directOwner.toBuilder().links(Collections.<Link>emptySet()).build(),
|
||||||
|
String.format(GETTER_RETURNS_SAME_OBJ,
|
||||||
|
"getOwner()", "owner", "media.getOwner()", owner.toString(), directOwner.toString()));
|
||||||
|
|
||||||
// parent type
|
// parent type
|
||||||
Checks.checkResourceType(directOwner);
|
Checks.checkResourceType(directOwner);
|
||||||
|
@ -187,7 +191,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
oldMedia = media;
|
oldMedia = media;
|
||||||
media = vdcClient.cloneMedia(vdcURI, CloneMediaParams.builder()
|
media = vdcClient.cloneMedia(vdcURI, CloneMediaParams.builder()
|
||||||
.source(Reference.builder().fromEntity(media).build())
|
.source(Reference.builder().fromEntity(media).build())
|
||||||
.name("copied test media")
|
.name("copied "+media.getName())
|
||||||
.description("copied by testCloneMedia()")
|
.description("copied by testCloneMedia()")
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
@ -262,7 +266,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(testName = "GET /media/{id}/metadata",
|
@Test(testName = "GET /media/{id}/metadata",
|
||||||
dependsOnMethods = { "testGetMedia" })
|
dependsOnMethods = { "testSetMetadataValue" })
|
||||||
public void testGetMetadata() {
|
public void testGetMetadata() {
|
||||||
metadata = mediaClient.getMetadataClient().getMetadata(media.getHref());
|
metadata = mediaClient.getMetadataClient().getMetadata(media.getHref());
|
||||||
// required for testing
|
// required for testing
|
||||||
|
@ -273,7 +277,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(testName = "POST /media/{id}/metadata",
|
@Test(testName = "POST /media/{id}/metadata",
|
||||||
dependsOnMethods = { "testGetMetadata" })
|
dependsOnMethods = { "testGetMedia" })
|
||||||
public void testMergeMetadata() {
|
public void testMergeMetadata() {
|
||||||
// test new
|
// test new
|
||||||
Set<MetadataEntry> inputEntries = ImmutableSet.of(MetadataEntry.builder().entry("testKey", "testValue").build());
|
Set<MetadataEntry> inputEntries = ImmutableSet.of(MetadataEntry.builder().entry("testKey", "testValue").build());
|
||||||
|
@ -326,16 +330,16 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(testName = "GET /media/{id}/metadata/{key}",
|
@Test(testName = "GET /media/{id}/metadata/{key}",
|
||||||
dependsOnMethods = { "testMergeMetadata" })
|
dependsOnMethods = { "testSetMetadataValue" })
|
||||||
public void testGetMetadataValue() {
|
public void testGetMetadataValue() {
|
||||||
metadataValue = mediaClient.getMetadataClient().getMetadataValue(media.getHref(), "key");
|
metadataValue = mediaClient.getMetadataClient().getMetadataValue(media.getHref(), "key");
|
||||||
Checks.checkMetadataValueFor(MEDIA, metadataValue);
|
Checks.checkMetadataValueFor(MEDIA, metadataValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(testName = "PUT /media/{id}/metadata/{key}",
|
@Test(testName = "PUT /media/{id}/metadata/{key}",
|
||||||
dependsOnMethods = { "testGetMetadataValue" })
|
dependsOnMethods = { "testMergeMetadata" })
|
||||||
public void testSetMetadataValue() {
|
public void testSetMetadataValue() {
|
||||||
metadataEntryValue = "newValue";
|
metadataEntryValue = "value";
|
||||||
MetadataValue newValue = MetadataValue.builder().value(metadataEntryValue).build();
|
MetadataValue newValue = MetadataValue.builder().value(metadataEntryValue).build();
|
||||||
|
|
||||||
Task setMetadataEntry = mediaClient.getMetadataClient().setMetadata(media.getHref(), "key", newValue);
|
Task setMetadataEntry = mediaClient.getMetadataClient().setMetadata(media.getHref(), "key", newValue);
|
||||||
|
@ -347,7 +351,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(testName = "DELETE /media/{id}/metadata/{key}",
|
@Test(testName = "DELETE /media/{id}/metadata/{key}",
|
||||||
dependsOnMethods = { "testSetMetadataValue" } )
|
dependsOnMethods = { "testGetMetadata", "testGetMetadataValue" } )
|
||||||
public void testDeleteMetadata() {
|
public void testDeleteMetadata() {
|
||||||
Task deleteMetadataEntry = mediaClient.getMetadataClient().deleteMetadataEntry(media.getHref(), "testKey");
|
Task deleteMetadataEntry = mediaClient.getMetadataClient().deleteMetadataEntry(media.getHref(), "testKey");
|
||||||
Checks.checkTask(deleteMetadataEntry);
|
Checks.checkTask(deleteMetadataEntry);
|
||||||
|
@ -394,7 +398,7 @@ public class MediaClientLiveTest extends BaseVCloudDirectorClientLiveTest {
|
||||||
Error expected = Error.builder()
|
Error expected = Error.builder()
|
||||||
.message(String.format(
|
.message(String.format(
|
||||||
"No access to entity \"(com.vmware.vcloud.entity.media:%s)\".",
|
"No access to entity \"(com.vmware.vcloud.entity.media:%s)\".",
|
||||||
media.getId()))
|
media.getId().substring("urn:vcloud:media:".length())))
|
||||||
.majorErrorCode(403)
|
.majorErrorCode(403)
|
||||||
.minorErrorCode("ACCESS_TO_RESOURCE_IS_FORBIDDEN")
|
.minorErrorCode("ACCESS_TO_RESOURCE_IS_FORBIDDEN")
|
||||||
.build();
|
.build();
|
||||||
|
|
Loading…
Reference in New Issue