+ * This API is an extension that may or may not be present in your OpenStack cloud. Use the Optional return type
+ * to determine if it is present.
+ */
+ @Delegate
+ Optional getSecurityGroupApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/AddressPair.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/AddressPair.java
index 4e317cee11..a222908f88 100644
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/AddressPair.java
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/AddressPair.java
@@ -101,19 +101,10 @@ public class AddressPair {
* In this case, both parameters are required.
* @return the Builder for AddressPair
*/
- public static Builder createOptions(String macAddress, String ipAddress) {
+ public static Builder builder(String macAddress, String ipAddress) {
return new Builder(macAddress, ipAddress);
}
- /**
- * Returns a builder, but requires the user to specify any parameters required when updating a resource.
- * In this case, there are none.
- * @return the Builder for AddressPair
- */
- public static Builder updateOptions() {
- return new Builder();
- }
-
/**
* Gets a Builder configured as this object.
*/
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Rule.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Rule.java
new file mode 100644
index 0000000000..e3b7aca259
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Rule.java
@@ -0,0 +1,375 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.beans.ConstructorProperties;
+import javax.inject.Named;
+
+import org.jclouds.javax.annotation.Nullable;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+/**
+ * Contains a mapping between a MAC address and an IP address.
+ */
+public class Rule {
+
+ private String id;
+ @Named("tenant_id")
+ private String tenantId;
+ private RuleDirection direction;
+ @Named("security_group_id")
+ private String securityGroupId;
+ private RuleEthertype ethertype;
+ @Named("port_range_min")
+ private Integer portRangeMin;
+ @Named("port_range_max")
+ private Integer portRangeMax;
+ private RuleProtocol protocol;
+ @Named("remote_group_id")
+ private String remoteGroupId;
+ @Named("remote_ip_prefix")
+ private String remoteIpPrefix;
+
+ @ConstructorProperties({"id", "tenant_id", "direction", "security_group_id", "ethertype", "port_range_min",
+ "port_range_max", "protocol", "remote_group_id", "remote_ip_prefix"})
+ protected Rule(String id, String tenantId, RuleDirection direction, String securityGroupId,
+ RuleEthertype ethertype, Integer portRangeMin, Integer portRangeMax,
+ RuleProtocol protocol, String remoteGroupId, String remoteIpPrefix) {
+ this.id = id;
+ this.tenantId = tenantId;
+ this.direction = direction;
+ this.securityGroupId = securityGroupId;
+ this.ethertype = ethertype;
+ this.portRangeMin = portRangeMin;
+ this.portRangeMax = portRangeMax;
+ this.protocol = protocol;
+ this.remoteGroupId = remoteGroupId;
+ this.remoteIpPrefix = remoteIpPrefix;
+ }
+
+ private Rule(Rule rule) {
+ this(rule.id,
+ rule.tenantId,
+ rule.direction,
+ rule.securityGroupId,
+ rule.ethertype,
+ rule.portRangeMin,
+ rule.portRangeMax,
+ rule.protocol,
+ rule.remoteGroupId,
+ rule.remoteIpPrefix
+ );
+ }
+
+ private Rule() {}
+
+ /**
+ * @return The identifier for this rule.
+ */
+ @Nullable
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @return The identifier of the tenant for this rule.
+ */
+ @Nullable
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ /**
+ * @return The direction in which the security group rule is applied.
+ */
+ @Nullable
+ public RuleDirection getDirection() {
+ return direction;
+ }
+
+ /**
+ * @return The security group ID to associate with this security group rule.
+ */
+ @Nullable
+ public String getSecurityGroupId() {
+ return securityGroupId;
+ }
+
+ /**
+ * @return The internet protocol version type of this rule.
+ */
+ @Nullable
+ public RuleEthertype getEthertype() {
+ return ethertype;
+ }
+
+ /**
+ * @return The minimum port number in the range that is matched by the security group rule. If the protocol is TCP
+ * or UDP, this value must be less than or equal to the value of the port_range_max attribute. If the protocol is
+ * ICMP, this value must be an ICMP type.
+ */
+ @Nullable
+ public Integer getPortRangeMin() {
+ return portRangeMin;
+ }
+
+ /**
+ * @return The maximum port number in the range that is matched by the security group rule. The port_range_min
+ * attribute constrains the port_range_max attribute. If the protocol is ICMP, this value must be an ICMP type.
+ */
+ @Nullable
+ public Integer getPortRangeMax() {
+ return portRangeMax;
+ }
+
+ /**
+ * @return The protocol that is matched by the security group rule. Valid values are null, tcp, udp, and icmp.
+ */
+ @Nullable
+ public RuleProtocol getProtocol() {
+ return protocol;
+ }
+
+ /**
+ * @return The remote group ID to be associated with this security group rule.
+ */
+ @Nullable
+ public String getRemoteGroupId() {
+ return remoteGroupId;
+ }
+
+ /**
+ * @return The remote IP prefix to be associated with this security group rule. This attribute matches the specified
+ * IP prefix as the source IP address of the IP packet.
+ */
+ @Nullable
+ public String getRemoteIpPrefix() {
+ return remoteIpPrefix;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ Rule that = (Rule) o;
+
+ return Objects.equal(this.id, that.id) &&
+ Objects.equal(this.tenantId, that.tenantId) &&
+ Objects.equal(this.direction, that.direction) &&
+ Objects.equal(this.securityGroupId, that.securityGroupId) &&
+ Objects.equal(this.ethertype, that.ethertype) &&
+ Objects.equal(this.portRangeMin, that.portRangeMin) &&
+ Objects.equal(this.portRangeMax, that.portRangeMax) &&
+ Objects.equal(this.protocol, that.protocol) &&
+ Objects.equal(this.remoteGroupId, that.remoteGroupId) &&
+ Objects.equal(this.remoteIpPrefix, that.remoteIpPrefix);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, tenantId, direction, securityGroupId, ethertype, portRangeMin,
+ portRangeMax, protocol, remoteGroupId, remoteIpPrefix);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id)
+ .add("tenantId", tenantId)
+ .add("direction", direction)
+ .add("securityGroupId", securityGroupId)
+ .add("ethertype", ethertype)
+ .add("portRangeMin", portRangeMin)
+ .add("portRangeMax", portRangeMax)
+ .add("protocol", protocol)
+ .add("remoteGroupId", remoteGroupId)
+ .add("remoteIpPrefix", remoteIpPrefix)
+ .toString();
+ }
+
+
+ /*
+ * Methods to get the Create and Update builders follow
+ */
+
+ /**
+ * @return the Builder for creating a new SecurityGroupRule
+ */
+ public static CreateBuilder createOptions(RuleDirection direction, String securityGroupId) {
+ return new CreateBuilder(direction, securityGroupId);
+ }
+
+ public abstract static class Builder {
+ // Keep track of the builder's state.
+ protected Rule rule;
+
+ private Builder() {
+ rule = new Rule();
+ }
+
+ protected abstract ParameterizedBuilderType self();
+
+ /**
+ * The tenant id for this rule. Usually can only be specified by administrators.
+ *
+ * @return the Builder.
+ * @see Rule#getTenantId()
+ */
+ public ParameterizedBuilderType tenantId(String tenantId) {
+ rule.tenantId = tenantId;
+ return self();
+ }
+
+ /**
+ * The direction in which the security group rule is applied.
+ *
+ * @return the Builder.
+ * @see Rule#getDirection()
+ */
+ public ParameterizedBuilderType direction(RuleDirection direction) {
+ rule.direction = direction;
+ return self();
+ }
+
+ /**
+ * The security group ID to associate with this security group rule.
+ *
+ * @return the Builder.
+ * @see Rule#getSecurityGroupId()
+ */
+ public ParameterizedBuilderType securityGroupId(String securityGroupId) {
+ rule.securityGroupId = securityGroupId;
+ return self();
+ }
+
+ /**
+ * The internet protocol version for this rule.
+ *
+ * @return the Builder.
+ * @see Rule#getEthertype()
+ */
+ public ParameterizedBuilderType ethertype(RuleEthertype ethertype) {
+ rule.ethertype = ethertype;
+ return self();
+ }
+
+ /**
+ * The minimum port number in the range that is matched by the security group rule.
+ *
+ * @return the Builder.
+ * @see Rule#getPortRangeMin()
+ */
+ public ParameterizedBuilderType portRangeMin(Integer portRangeMin) {
+ rule.portRangeMin = portRangeMin;
+ return self();
+ }
+
+ /**
+ * The maximum port number in the range that is matched by the security group rule.
+ *
+ * @return the Builder.
+ * @see Rule#getPortRangeMax()
+ */
+ public ParameterizedBuilderType portRangeMax(Integer portRangeMax) {
+ rule.portRangeMax = portRangeMax;
+ return self();
+ }
+
+ /**
+ * The protocol that is matched by the security group rule. Valid values are null, tcp, udp, and icmp.
+ *
+ * @return the Builder.
+ * @see Rule#getProtocol()
+ */
+ public ParameterizedBuilderType protocol(RuleProtocol protocol) {
+ rule.protocol = protocol;
+ return self();
+ }
+
+ /**
+ * The remote group ID to be associated with this security group rule. You can specify either remote_group_id or
+ * remote_ip_prefix in the request body.
+ *
+ * @return the Builder.
+ * @see Rule#getRemoteGroupId()
+ */
+ public ParameterizedBuilderType remoteGroupId(String remoteGroupId) {
+ rule.remoteGroupId = remoteGroupId;
+ return self();
+ }
+
+ /**
+ * The remote IP prefix to be associated with this security group rule. You can specify either remote_group_id
+ * or remote_ip_prefix in the request body. This attribute matches the specified IP prefix as the source IP
+ * address of the IP packet.
+ *
+ * @return the Builder.
+ * @see Rule#getRemoteIpPrefix()
+ */
+ public ParameterizedBuilderType remoteIpPrefix(String remoteIpPrefix) {
+ rule.remoteIpPrefix = remoteIpPrefix;
+ return self();
+ }
+ }
+
+ /**
+ * This is used to build a CreateOptions object.
+ */
+ public static class CreateBuilder extends Builder {
+ /**
+ * Supply required properties for creating a Builder
+ */
+ private CreateBuilder(RuleDirection direction, String securityGroupId) {
+ rule.direction = direction;
+ rule.securityGroupId = securityGroupId;
+ }
+
+ /**
+ * @return a CreateOptions constructed with this Builder.
+ */
+ public CreateOptions build() {
+ return new CreateOptions(rule);
+ }
+
+ protected CreateBuilder self() {
+ return this;
+ }
+ }
+
+ /**
+ * Create and Update options - extend the domain class, passed to API update and create calls.
+ * Essentially the same as the domain class. Ensure validation and safe typing.
+ */
+ public static class CreateOptions extends Rule {
+ private CreateOptions(Rule rule) {
+ super(rule);
+ checkNotNull(rule.getDirection(), "direction should not be null");
+ checkNotNull(rule.getSecurityGroupId(), "security group id should not be null");
+ checkState(rule.getPortRangeMax()>= rule.getPortRangeMin(),
+ "port range max should be greater than or equal to port range min");
+ checkState(rule.getRemoteGroupId()==null || rule.getRemoteIpPrefix()==null,
+ "You can specify either remote_group_id or remote_ip_prefix in the request body.");
+ }
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleDirection.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleDirection.java
new file mode 100644
index 0000000000..759bb8c1f9
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleDirection.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.openstack.neutron.v2.domain;
+
+/**
+ * The direction in which the security group rule is applied.
+ */
+public enum RuleDirection {
+ /**
+ * For a compute instance, an ‘ingress’ security group rule matches traffic that is incoming (ingress) for that instance.
+ */
+ INGRESS("ingress"),
+ /**
+ * An ‘egress’ rule is applied to traffic leaving the instance.
+ */
+ EGRESS("egress"),
+ /**
+ * Used by jclouds when the service returns an unknown value other than null.
+ */
+ UNRECOGNIZED("unrecognized");
+
+ private String name;
+
+ private RuleDirection(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ * */
+ public static RuleDirection fromValue(String name){
+ if (name != null) {
+ for (RuleDirection value : RuleDirection.values()) {
+ if (name.equalsIgnoreCase(value.name)) {
+ return value;
+ }
+ }
+ return UNRECOGNIZED;
+ }
+ return null;
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleEthertype.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleEthertype.java
new file mode 100644
index 0000000000..150807001d
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleEthertype.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.openstack.neutron.v2.domain;
+
+/**
+ * The direction in which the security group rule is applied.
+ */
+public enum RuleEthertype {
+ /**
+ * Internet Protocol version 4
+ */
+ IPV4("IPv4"),
+ /**
+ * Internet Protocol version 6
+ */
+ IPV6("IPv6"),
+ /**
+ * Used by jclouds when the service returns an unknown value other than null.
+ */
+ UNRECOGNIZED("unrecognized");
+
+ private String name;
+
+ private RuleEthertype(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ * */
+ public static RuleEthertype fromValue(String name){
+ if (name != null) {
+ for (RuleEthertype value : RuleEthertype.values()) {
+ if (name.equalsIgnoreCase(value.name)) {
+ return value;
+ }
+ }
+ return UNRECOGNIZED;
+ }
+ return null;
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleProtocol.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleProtocol.java
new file mode 100644
index 0000000000..9ad105f3a7
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RuleProtocol.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.openstack.neutron.v2.domain;
+
+/**
+ * The protocol that is matched by the security group rule. Valid values are null, tcp, udp, and icmp.
+ */
+public enum RuleProtocol {
+ /**
+ * Transmission Control Protocol
+ */
+ TCP("tcp"),
+ /**
+ * User Datagram Protocol
+ */
+ UDP("udp"),
+ /**
+ * Internet Control Message Protocol
+ */
+ ICMP("icmp"),
+ /**
+ * Used by jclouds when the service returns an unknown value other than null.
+ */
+ UNRECOGNIZED("unrecognized");
+
+ private String name;
+
+ private RuleProtocol(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ * */
+ public static RuleProtocol fromValue(String name){
+ if (name != null) {
+ for (RuleProtocol value : RuleProtocol.values()) {
+ if (name.equalsIgnoreCase(value.name)) {
+ return value;
+ }
+ }
+ return UNRECOGNIZED;
+ }
+ return null;
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Rules.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Rules.java
new file mode 100644
index 0000000000..4794a189ed
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Rules.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.domain;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A collection of Networks
+ */
+public class Rules extends PaginatedCollection {
+ public static final Rules EMPTY = new Rules(ImmutableSet. of(), ImmutableSet. of());
+
+ @ConstructorProperties({"security_group_rules", "security_group_rules_links"})
+ protected Rules(Iterable securityGroups, Iterable securityGroupRulesLinks) {
+ super(securityGroups, securityGroupRulesLinks);
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/SecurityGroup.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/SecurityGroup.java
new file mode 100644
index 0000000000..604776eef0
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/SecurityGroup.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.domain;
+
+import java.beans.ConstructorProperties;
+
+import javax.inject.Named;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Contains a mapping between a MAC address and an IP address.
+ */
+public class SecurityGroup {
+
+ private String id;
+ @Named("tenant_id")
+ private String tenantId;
+ private String name;
+ private String description;
+ @Named("security_group_rules")
+ private ImmutableList rules;
+
+ @ConstructorProperties({"id", "tenant_id", "name", "description", "security_group_rules"})
+ protected SecurityGroup(String id, String tenantId, String name, String description,
+ ImmutableList rules) {
+ this.id = id;
+ this.tenantId = tenantId;
+ this.name = name;
+ this.description = description;
+ this.rules = rules;
+ }
+
+ private SecurityGroup(SecurityGroup securityGroup) {
+ this(securityGroup.id,
+ securityGroup.tenantId,
+ securityGroup.name,
+ securityGroup.description,
+ securityGroup.rules
+ );
+ }
+
+ private SecurityGroup() {}
+
+ /**
+ * @return The identifier for this Security Group.
+ */
+ @Nullable
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @return The identifier of the tenant for this Security Group.
+ */
+ @Nullable
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ /**
+ * @return The name of the Security Group.
+ */
+ @Nullable
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return The description of the Security Group.
+ */
+ @Nullable
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return The collection of rules for this Security Group.
+ */
+ public ImmutableList getRules() {
+ return rules!=null ? rules : ImmutableList.of();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ SecurityGroup that = (SecurityGroup) o;
+
+ return Objects.equal(this.id, that.id) &&
+ Objects.equal(this.tenantId, that.tenantId) &&
+ Objects.equal(this.name, that.name) &&
+ Objects.equal(this.description, that.description) &&
+ Objects.equal(this.rules, that.rules);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, tenantId, name, description, rules);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id)
+ .add("tenantId", tenantId)
+ .add("name", name)
+ .add("description", description)
+ .add("securityGroupRules", rules)
+ .toString();
+ }
+
+ /*
+ * Methods to get the Create and Update builders follow
+ */
+
+ /**
+ * @return the Builder for creating a new SecurityGroup
+ */
+ public static CreateBuilder createOptions() {
+ return new CreateBuilder();
+ }
+
+ private abstract static class Builder {
+ // Keep track of the builder's state.
+ protected SecurityGroup securityGroup;
+
+ private Builder() {
+ securityGroup = new SecurityGroup();
+ }
+
+ protected abstract ParameterizedBuilderType self();
+
+ /**
+ * The tenant id for this Security Group. Usually can only be specified by administrators.
+ *
+ * @return the Builder.
+ * @see SecurityGroup#getTenantId()
+ */
+ public ParameterizedBuilderType tenantId(String tenantId) {
+ securityGroup.tenantId = tenantId;
+ return self();
+ }
+
+ /**
+ * The name for this Security Group.
+ *
+ * @return the Builder.
+ * @see SecurityGroup#getName()
+ */
+ public ParameterizedBuilderType name(String name) {
+ securityGroup.name = name;
+ return self();
+ }
+
+ /**
+ * The description for this Security Group.
+ *
+ * @return the Builder.
+ * @see SecurityGroup#getDescription()
+ */
+ public ParameterizedBuilderType description(String description) {
+ securityGroup.description = description;
+ return self();
+ }
+ }
+
+ /**
+ * Create and Update builders (inheriting from Builder)
+ */
+ public static class CreateBuilder extends Builder {
+ /**
+ * Supply required properties for creating a Builder
+ */
+ private CreateBuilder() {
+ }
+
+ /**
+ * @return a CreateOptions constructed with this Builder.
+ */
+ public CreateOptions build() {
+ return new CreateOptions(securityGroup);
+ }
+
+ protected CreateBuilder self() {
+ return this;
+ }
+ }
+
+ /**
+ * Create and Update options - extend the domain class, passed to API update and create calls.
+ * Essentially the same as the domain class. Ensure validation and safe typing.
+ */
+ public static class CreateOptions extends SecurityGroup {
+ private CreateOptions(SecurityGroup securityGroup) {
+ super(securityGroup);
+ }
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/SecurityGroups.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/SecurityGroups.java
new file mode 100644
index 0000000000..044ce1c783
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/SecurityGroups.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.domain;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A collection of Networks
+ */
+public class SecurityGroups extends PaginatedCollection {
+ public static final SecurityGroups EMPTY = new SecurityGroups(ImmutableSet. of(), ImmutableSet. of());
+
+ @ConstructorProperties({"security_groups", "security_groups_links"})
+ protected SecurityGroups(Iterable securityGroups, Iterable securityGroupsLinks) {
+ super(securityGroups, securityGroupsLinks);
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/SecurityGroupApi.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/SecurityGroupApi.java
new file mode 100644
index 0000000000..4c0b4da4b9
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/SecurityGroupApi.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.extensions;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.neutron.v2.domain.Rule;
+import org.jclouds.openstack.neutron.v2.domain.Rules;
+import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
+import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
+import org.jclouds.openstack.neutron.v2.fallbacks.EmptyRulesFallback;
+import org.jclouds.openstack.neutron.v2.fallbacks.EmptySecurityGroupsFallback;
+import org.jclouds.openstack.neutron.v2.functions.ParseRules;
+import org.jclouds.openstack.neutron.v2.functions.ParseSecurityGroups;
+import org.jclouds.openstack.neutron.v2.functions.RulesToPagedIterable;
+import org.jclouds.openstack.neutron.v2.functions.SecurityGroupsToPagedIterable;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides access to Security Group extension operations for the OpenStack Networking (Neutron) v2 API.
+ *
+ * Security groups and security group rules allows administrators and tenants the ability to specify the type of
+ * traffic and direction (ingress/egress) that is allowed to pass through a port. A security group is a container for
+ * security group rules.
+ */
+@Beta
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface SecurityGroupApi {
+ /**
+ * Groups
+ */
+
+ /**
+ * @return all security groups currently defined in Neutron for the current tenant.
+ */
+ @Path("/security-groups")
+ @Named("security-group:list")
+ @GET
+ @ResponseParser(ParseSecurityGroups.class)
+ @Transform(SecurityGroupsToPagedIterable.class)
+ @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable listSecurityGroups();
+
+ /**
+ * @return all security groups currently defined in Neutron for the current tenant.
+ */
+ @Path("/security-groups")
+ @Named("security-group:list")
+ @GET
+ @ResponseParser(ParseSecurityGroups.class)
+ @Fallback(EmptySecurityGroupsFallback.class)
+ SecurityGroups listSecurityGroups(PaginationOptions options);
+
+ /**
+ * @param id the id of the security group to return
+ * @return SecurityGroup or null if not found.
+ */
+ @Path("/security-groups/{id}")
+ @Named("security-group:get")
+ @GET
+ @SelectJson("security_group")
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+ @Nullable
+ SecurityGroup getSecurityGroup(@PathParam("id") String id);
+
+ /**
+ * Create a new SecurityGroup.
+ *
+ * @param securityGroup Describes the security group to be created.
+ * @return a reference of the newly-created security group
+ */
+ @Path("/security-groups")
+ @Named("secuity-group:create")
+ @POST
+ @SelectJson("security_group")
+ SecurityGroup create(@WrapWith("security_group") SecurityGroup.CreateOptions securityGroup);
+
+ /**
+ * Deletes the specified Security Group.
+ *
+ * @param id the id of the security group to delete
+ * @return true if delete was successful, false if not
+ */
+ @Path("/security-groups/{id}")
+ @Named("security-group:delete")
+ @DELETE
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean deleteSecurityGroup(@PathParam("id") String id);
+
+ /**
+ * Rules
+ */
+
+ /**
+ * @return all security groups rules currently defined in Neutron for the current tenant.
+ */
+ @Path("/security-group-rules")
+ @Named("security-group-rule:list")
+ @GET
+ @ResponseParser(ParseRules.class)
+ @Transform(RulesToPagedIterable.class)
+ @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable listRules();
+
+ /**
+ * @return all security groups rules currently defined in Neutron for the current tenant.
+ */
+ @Path("/security-group-rules")
+ @Named("security-group-rule:list")
+ @GET
+ @ResponseParser(ParseRules.class)
+ @Fallback(EmptyRulesFallback.class)
+ Rules listRules(PaginationOptions options);
+
+ /**
+ * @param id the id of the security group rule to return.
+ * @return SecurityGroupRule or null if not found.
+ */
+ @Path("/security-group-rules/{id}")
+ @Named("security-group-rule:get")
+ @GET
+ @SelectJson("security_group_rule")
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+ @Nullable
+ Rule get(@PathParam("id") String id);
+
+ /**
+ * Create a new Security Group Rule.
+ *
+ * @param securityGroupRule Describes the security group rule to be created.
+ * @return a reference of the newly-created security group rule.
+ */
+ @Path("/security-group-rules")
+ @Named("security-group-rule:create")
+ @POST
+ @SelectJson("security_group_rule")
+ Rule create(@WrapWith("security_group_rule") Rule.CreateOptions securityGroupRule);
+
+ /**
+ * Deletes the specified Security Group Rule.
+ *
+ * @param id the id of the security group rule to delete.
+ * @return true if delete was successful, false if not.
+ */
+ @Path("/security-group-rules/{id}")
+ @Named("security-group-rule:delete")
+ @DELETE
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean deleteRule(@PathParam("id") String id);
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRulesFallback.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRulesFallback.java
new file mode 100644
index 0000000000..a559f4fe99
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRulesFallback.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.openstack.neutron.v2.fallbacks;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static org.jclouds.http.HttpUtils.contains404;
+import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
+
+import org.jclouds.Fallback;
+import org.jclouds.openstack.neutron.v2.domain.Rules;
+import org.jclouds.rest.ResourceNotFoundException;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class EmptyRulesFallback implements Fallback {
+
+ public ListenableFuture create(Throwable t) throws Exception {
+ return immediateFuture(createOrPropagate(t));
+ }
+
+ @Override
+ public Rules createOrPropagate(Throwable t) throws Exception {
+ if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+ || contains404(t)) {
+ return Rules.EMPTY;
+ }
+ throw propagate(t);
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySecurityGroupsFallback.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySecurityGroupsFallback.java
new file mode 100644
index 0000000000..5343c3fdea
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySecurityGroupsFallback.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.openstack.neutron.v2.fallbacks;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.jclouds.Fallback;
+import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
+import org.jclouds.rest.ResourceNotFoundException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static org.jclouds.http.HttpUtils.contains404;
+import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
+
+public class EmptySecurityGroupsFallback implements Fallback {
+
+ public ListenableFuture create(Throwable t) throws Exception {
+ return immediateFuture(createOrPropagate(t));
+ }
+
+ @Override
+ public SecurityGroups createOrPropagate(Throwable t) throws Exception {
+ if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+ || contains404(t)) {
+ return SecurityGroups.EMPTY;
+ }
+ throw propagate(t);
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseRules.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseRules.java
new file mode 100644
index 0000000000..954180b7e5
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseRules.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.functions;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.openstack.neutron.v2.domain.Rules;
+
+import com.google.inject.TypeLiteral;
+
+/**
+ * Used by jclouds to provide more specific collections and fallbacks.
+ */
+@Singleton
+public class ParseRules extends ParseJson {
+
+ @Inject
+ public ParseRules(Json json) {
+ super(json, TypeLiteral.get(Rules.class));
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseSecurityGroups.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseSecurityGroups.java
new file mode 100644
index 0000000000..fbc3fd49fb
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseSecurityGroups.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.functions;
+
+import com.google.inject.TypeLiteral;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
+import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Used by jclouds to provide more specific collections and fallbacks.
+ */
+@Singleton
+public class ParseSecurityGroups extends ParseJson {
+
+ @Inject
+ public ParseSecurityGroups(Json json) {
+ super(json, TypeLiteral.get(SecurityGroups.class));
+ }
+}
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RulesToPagedIterable.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RulesToPagedIterable.java
new file mode 100644
index 0000000000..d664cd6893
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RulesToPagedIterable.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.neutron.v2.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.Rule;
+import org.jclouds.openstack.neutron.v2.extensions.SecurityGroupApi;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+
+/**
+ * Ensures Routers works as PagedIterable.
+ */
+public class RulesToPagedIterable extends
+ Arg0ToPagedIterable.FromCaller {
+
+ private final NeutronApi api;
+
+ @Inject
+ protected RulesToPagedIterable(NeutronApi api) {
+ this.api = checkNotNull(api, "api");
+ }
+
+ @Override
+ protected Function