From 699fa417c8889d2f2606715063c3569ca26453f2 Mon Sep 17 00:00:00 2001 From: Jeremy Daggett Date: Tue, 28 Feb 2012 09:06:08 -0800 Subject: [PATCH] SecurityGroup support --- .../nova/v1_1/domain/SecurityGroup.java | 181 +++++++++++++ .../nova/v1_1/domain/SecurityGroupRule.java | 251 ++++++++++++++++++ .../features/SecurityGroupAsyncClient.java | 86 ++++++ .../v1_1/features/SecurityGroupClient.java | 70 +++++ .../test/resources/securitygroup_details.json | 34 +++ .../test/resources/securitygroup_list.json | 51 ++++ 6 files changed, 673 insertions(+) create mode 100644 labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroup.java create mode 100644 labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroupRule.java create mode 100644 labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupAsyncClient.java create mode 100644 labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupClient.java create mode 100644 labs/openstack-nova/src/test/resources/securitygroup_details.json create mode 100644 labs/openstack-nova/src/test/resources/securitygroup_list.json diff --git a/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroup.java b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroup.java new file mode 100644 index 0000000000..ff0ed5ccff --- /dev/null +++ b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroup.java @@ -0,0 +1,181 @@ +/** + * 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.toStringHelper; + +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.gson.annotations.SerializedName; + + +/** + * Defines a security group + * + */ +public class SecurityGroup { + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromSecurityGroup(this); + } + + public static class Builder { + + private String id; + private String tenantId; + private String name; + private String description; + private Set rules; + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder tenantId(String tenantId) { + this.tenantId = tenantId; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder rules(Set rules) { + this.rules = rules; + return this; + } + + public SecurityGroup build() { + return new SecurityGroup(id, tenantId, name, description, rules); + } + + + public Builder fromSecurityGroup(SecurityGroup in) { + return id(in.getId()).tenantId(in.getTenantId()).name(in.getName()) + .description(in.getDescription()).rules(in.getRules()); + } + + } + + protected String id; + @SerializedName("tenant_id") + protected String tenantId; + protected String name; + protected String description; + protected Set rules; + + protected SecurityGroup(String id, String tenantId, @Nullable String name, + @Nullable String description, Set rules) { + this.id = id; + this.tenantId = tenantId; + this.name = name; + this.description = description; + } + + public String getId() { + return this.id; + } + + public String getTenantId() { + return this.tenantId; + } + + public String getName() { + return this.name; + } + + public String getDescription() { + return this.description; + } + + public Set getRules() { + return this.rules; + } + + + @Override + public int hashCode() { + final int prime = 31; + 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 + public String toString() { + return toStringHelper("").add("id", id).add("name", name) + .add("tenantId", tenantId).add("description", description).add("rules", rules) + .toString(); + } + +} \ No newline at end of file diff --git a/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroupRule.java b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroupRule.java new file mode 100644 index 0000000000..c976611e67 --- /dev/null +++ b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SecurityGroupRule.java @@ -0,0 +1,251 @@ +/** + * 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.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import com.google.gson.annotations.SerializedName; + +/** + * Defines a security group rule + * + */ +public class SecurityGroupRule implements Comparable { + + public static enum IpProtocol { + TCP, UDP, ICMP, UNRECOGNIZED; + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static IpProtocol fromValue(String protocol) { + try { + return valueOf(checkNotNull(protocol, "protocol").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromSecurityGroupRule(this); + } + + public static class Builder { + private String id; + private int fromPort; + private Map group; + // tcp/udp/icmp - move to enum + private IpProtocol ipProtocol; + + private int toPort; + private String parentGroupId; + + private Map ipRange; + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder fromPort(int fromPort) { + this.fromPort = fromPort; + return this; + } + + public Builder group(Map group) { + this.group = group; + 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) { + this.parentGroupId = parentGroupId; + return this; + } + + public Builder ipRange(Map ipRange) { + this.ipRange = ipRange; + return this; + } + + public SecurityGroupRule build() { + return new SecurityGroupRule(id, fromPort, group, ipProtocol, toPort, + parentGroupId, ipRange); + } + + public Builder fromSecurityGroupRule(SecurityGroupRule in) { + return id(in.getId()).fromPort(in.getFromPort()).group(in.getGroup()) + .ipProtocol(in.getIpProtocol()).toPort(in.getToPort()).parentGroupId(in.getParentGroupId()) + .ipRange(in.getIpRange()); + } + } + + + protected String id; + + @SerializedName(value = "from_port") + protected int fromPort; + + protected Map 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") + protected Map ipRange; + + + protected SecurityGroupRule(String id, int fromPort, Map group, + IpProtocol ipProtocol, int toPort, String parentGroupId, Map ipRange) { + this.id = id; + this.fromPort = fromPort; + this.group = group; + this.ipProtocol = ipProtocol; + this.toPort = toPort; + this.parentGroupId = parentGroupId; + this.ipRange = ipRange; + } + + public String getId() { + return this.id; + } + + public int getFromPort() { + return this.fromPort; + } + + public Map getGroup() { + return this.group; + } + + public IpProtocol getIpProtocol() { + return this.ipProtocol; + } + + public int getToPort() { + return this.toPort; + } + + public String getParentGroupId() { + return this.parentGroupId; + } + + public Map getIpRange() { + return this.ipRange; + } + + @Override + public int compareTo(SecurityGroupRule o) { + return this.id.compareTo(o.getId()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + fromPort; + result = prime * result + ((group == null) ? 0 : group.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + + ((ipProtocol == null) ? 0 : ipProtocol.hashCode()); + result = prime * result + ((ipRange == null) ? 0 : ipRange.hashCode()); + result = prime * result + + ((parentGroupId == null) ? 0 : parentGroupId.hashCode()); + result = prime * result + toPort; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SecurityGroupRule other = (SecurityGroupRule) obj; + if (fromPort != other.fromPort) + return false; + if (group == null) { + if (other.group != null) + return false; + } else if (!group.equals(other.group)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (ipProtocol != other.ipProtocol) + return false; + if (ipRange == null) { + if (other.ipRange != null) + return false; + } else if (!ipRange.equals(other.ipRange)) + return false; + if (parentGroupId == null) { + if (other.parentGroupId != null) + return false; + } else if (!parentGroupId.equals(other.parentGroupId)) + return false; + if (toPort != other.toPort) + return false; + return true; + } + + @Override + public String toString() { + return toStringHelper("").add("id", id).add("fromPort", fromPort) + .add("group", group).add("ipProtocol", ipProtocol) + .add("toPort", toPort).add("parentGroupId", parentGroupId) + .add("ipRange", ipRange).toString(); + } + + +} \ No newline at end of file diff --git a/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupAsyncClient.java b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupAsyncClient.java new file mode 100644 index 0000000000..2bd3ab2174 --- /dev/null +++ b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupAsyncClient.java @@ -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.features; + +import java.util.Set; + +import javax.ws.rs.Consumes; +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.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.Payload; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Security Groups via the REST API. + *

+ * + * @see SecurityGroupClient + * @author Jeremy Daggett + */ +@SkipEncoding({ '/', '=' }) +@RequestFilters(AuthenticateRequest.class) +public interface SecurityGroupAsyncClient { + + /** + * @see SecurityGroupClient#listSecurityGroups + */ + @GET + @SelectJson("security_groups") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/os-security-groups") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listSecurityGroups(); + + /** + * @see SecurityGroupClient#getSecurityGroup + */ + @GET + @Path("/os-security-groups/{id}") + @SelectJson("security_group") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getSecurityGroup(@PathParam("id") String id); + + + /** + * @see SecurityGroupClient#createSecurityGroup + */ + @POST + @Path("/os-security-groups") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @Payload("name {name}\n") + @Produces(MediaType.TEXT_PLAIN) + ListenableFuture createSecurityGroup(@PayloadParam("name") String name); + +} diff --git a/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupClient.java b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupClient.java new file mode 100644 index 0000000000..e4fa5ee454 --- /dev/null +++ b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/features/SecurityGroupClient.java @@ -0,0 +1,70 @@ +/** + * 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.features; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.nova.v1_1.domain.FloatingIP; +import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.Payload; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides synchronous access to Security Groups. + *

+ * + * @see SecurityGroupAsyncClient + * @author Jeremy Daggett + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface SecurityGroupClient { + + /** + * List all Security Groups. + * + * @return all Floating IPs + */ + Set listSecurityGroups(); + + /** + * Get a specific Security Group + * + * @return a specific Security Group + */ + SecurityGroup getSecurityGroup(String id); + + /** + * Create a Security Group + * + * @return a new Security Group + */ + SecurityGroup createSecurityGroup(String name); + +} diff --git a/labs/openstack-nova/src/test/resources/securitygroup_details.json b/labs/openstack-nova/src/test/resources/securitygroup_details.json new file mode 100644 index 0000000000..840de6ce54 --- /dev/null +++ b/labs/openstack-nova/src/test/resources/securitygroup_details.json @@ -0,0 +1,34 @@ +{ + "security_group": + { + "rules": [ + { + "from_port": 22, + "group": {}, + "ip_protocol": "tcp", + "to_port": 22, + "parent_group_id": 28, + "ip_range": { + "cidr": "10.2.6.0/24" + }, + "id": 108 + }, + { + "from_port": 22, + "group": { + "tenant_id": "admin", + "name": "11111" + }, + "ip_protocol": "tcp", + "to_port": 22, + "parent_group_id": 28, + "ip_range": {}, + "id": 109 + } + ], + "tenant_id": "tenant0", + "id": 0, + "name": "name0", + "description": "description0" + } +} \ No newline at end of file diff --git a/labs/openstack-nova/src/test/resources/securitygroup_list.json b/labs/openstack-nova/src/test/resources/securitygroup_list.json new file mode 100644 index 0000000000..b5a1ed1bfc --- /dev/null +++ b/labs/openstack-nova/src/test/resources/securitygroup_list.json @@ -0,0 +1,51 @@ +{ + "security_groups":[ + { + "rules":[ + { + "from_port":22, + "group":{ + + }, + "ip_protocol":"tcp", + "to_port":22, + "parent_group_id":3, + "ip_range":{ + "cidr":"0.0.0.0/0" + }, + "id":107 + }, + { + "from_port":7600, + "group":{ + + }, + "ip_protocol":"tcp", + "to_port":7600, + "parent_group_id":3, + "ip_range":{ + "cidr":"0.0.0.0/0" + }, + "id":118 + }, + { + "from_port":8084, + "group":{ + + }, + "ip_protocol":"tcp", + "to_port":8084, + "parent_group_id":3, + "ip_range":{ + "cidr":"0.0.0.0/0" + }, + "id":119 + } + ], + "tenant_id":"tenant1", + "id":1, + "name":"name1", + "description":"description1" + } + ] +} \ No newline at end of file