From 4e090796408152af5c06ce72f346ee9ea5d4d404 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Fri, 17 May 2013 13:02:33 +0200 Subject: [PATCH] Update the Logical Router NatRules to be compatible with the NVP 3.x.x platform Use the Gson adapters to serialize/deserialize the NatRules Switch the NiciraNvpApi to a single gson Object with the proper adapters Fix missing order setting for static nat rules and portforwarding rules Return an error when a port range is passed in a portforwarding rule The serializer is not required Fix a bug where an ip address could be released even if it was still in use for SourceNat Throw a json parse exception when the type is unknown to the adapter --- .../network/nicira/DestinationNatRule.java | 89 +++++ .../src/com/cloud/network/nicira/Match.java | 148 +------ .../src/com/cloud/network/nicira/NatRule.java | 363 +++++------------- .../cloud/network/nicira/NiciraNvpApi.java | 67 +++- .../cloud/network/nicira/SourceNatRule.java | 107 ++++++ .../network/resource/NiciraNvpResource.java | 57 ++- .../com/cloud/network/nicira/NatRuleTest.java | 43 ++- .../resource/NiciraNvpResourceTest.java | 111 +++--- .../com/cloud/network/NetworkModelImpl.java | 8 +- 9 files changed, 493 insertions(+), 500 deletions(-) create mode 100644 plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java create mode 100644 plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java new file mode 100644 index 00000000000..48310417b72 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/DestinationNatRule.java @@ -0,0 +1,89 @@ +package com.cloud.network.nicira; + +public class DestinationNatRule extends NatRule { + private String toDestinationIpAddress; + private Integer toDestinationPort; + + public DestinationNatRule() { + setType("DestinationNatRule"); + } + + public String getToDestinationIpAddress() { + return toDestinationIpAddress; + } + + + public void setToDestinationIpAddress(String toDestinationIpAddress) { + this.toDestinationIpAddress = toDestinationIpAddress; + } + + + public Integer getToDestinationPort() { + return toDestinationPort; + } + + + public void setToDestinationPort(Integer toDestinationPort) { + this.toDestinationPort = toDestinationPort; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime + * result + + ((toDestinationIpAddress == null) ? 0 + : toDestinationIpAddress.hashCode()); + result = prime + * result + + ((toDestinationPort == null) ? 0 : toDestinationPort + .hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DestinationNatRule other = (DestinationNatRule) obj; + if (toDestinationIpAddress == null) { + if (other.toDestinationIpAddress != null) + return false; + } else if (!toDestinationIpAddress.equals(other.toDestinationIpAddress)) + return false; + if (toDestinationPort == null) { + if (other.toDestinationPort != null) + return false; + } else if (!toDestinationPort.equals(other.toDestinationPort)) + return false; + return true; + } + + @Override + public boolean equalsIgnoreUuid(Object obj) { + if (this == obj) + return true; + if (!super.equalsIgnoreUuid(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DestinationNatRule other = (DestinationNatRule) obj; + if (toDestinationIpAddress == null) { + if (other.toDestinationIpAddress != null) + return false; + } else if (!toDestinationIpAddress.equals(other.toDestinationIpAddress)) + return false; + if (toDestinationPort == null) { + if (other.toDestinationPort != null) + return false; + } else if (!toDestinationPort.equals(other.toDestinationPort)) + return false; + return true; + } + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java index 0c4e677536c..f7777822a06 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Match.java @@ -22,15 +22,9 @@ package com.cloud.network.nicira; public class Match { private Integer protocol; private String source_ip_addresses; - private Boolean source_ip_addresses_not; private String destination_ip_addresses; - private Boolean destination_ip_addresses_not; - private Integer source_port_min; - private Integer source_port_max; - private Boolean source_port_not; - private Integer destination_port_min; - private Integer destination_port_max; - private Boolean destination_port_not; + private Integer source_port; + private Integer destination_port; private String ethertype = "IPv4"; public Integer getProtocol() { @@ -41,54 +35,22 @@ public class Match { this.protocol = protocol; } - public Integer getSourcePortMin() { - return source_port_min; + public Integer getSourcePort() { + return source_port; } - public void setSourcePortMin(Integer source_port_min) { - this.source_port_min = source_port_min; + public void setSourcePort(Integer source_port) { + this.source_port = source_port; + } + + public Integer getDestinationPort() { + return destination_port; } - public Integer getSourcePortMax() { - return source_port_max; + public void setDestinationPort(Integer destination_port) { + this.destination_port = destination_port; } - - public void setSourcePortMax(Integer source_port_max) { - this.source_port_max = source_port_max; - } - - public Boolean isSourcePortNot() { - return source_port_not; - } - - public void setSourcePortNot(Boolean source_port_not) { - this.source_port_not = source_port_not; - } - - public Integer getDestinationPortMin() { - return destination_port_min; - } - - public void setDestinationPortMin(Integer destination_port_min) { - this.destination_port_min = destination_port_min; - } - - public Integer getDestinationPortMax() { - return destination_port_max; - } - - public void setDestinationPortMax(Integer destination_port_max) { - this.destination_port_max = destination_port_max; - } - - public Boolean isDestinationPortNot() { - return destination_port_not; - } - - public void setDestinationPortNot(Boolean destination_port_not) { - this.destination_port_not = destination_port_not; - } - + public String getEthertype() { return ethertype; } @@ -105,14 +67,6 @@ public class Match { this.source_ip_addresses = source_ip_addresses; } - public boolean isSourceIpAddressesNot() { - return source_ip_addresses_not; - } - - public void setSourceIpAddresses_not(boolean source_ip_addresses_not) { - this.source_ip_addresses_not = source_ip_addresses_not; - } - public String getDestinationIpAddresses() { return destination_ip_addresses; } @@ -121,14 +75,6 @@ public class Match { this.destination_ip_addresses = destination_ip_addresses; } - public Boolean isDestinationIpAddressesNot() { - return destination_ip_addresses_not; - } - - public void setDestinationIpAddressesNot(Boolean destination_ip_addresses_not) { - this.destination_ip_addresses_not = destination_ip_addresses_not; - } - @Override public int hashCode() { final int prime = 31; @@ -139,19 +85,7 @@ public class Match { : destination_ip_addresses.hashCode()); result = prime * result - + ((destination_ip_addresses_not == null) ? 0 - : destination_ip_addresses_not.hashCode()); - result = prime - * result - + ((destination_port_max == null) ? 0 : destination_port_max - .hashCode()); - result = prime - * result - + ((destination_port_min == null) ? 0 : destination_port_min - .hashCode()); - result = prime - * result - + ((destination_port_not == null) ? 0 : destination_port_not + + ((destination_port == null) ? 0 : destination_port .hashCode()); result = prime * result + ((ethertype == null) ? 0 : ethertype.hashCode()); @@ -161,16 +95,8 @@ public class Match { * result + ((source_ip_addresses == null) ? 0 : source_ip_addresses .hashCode()); - result = prime - * result - + ((source_ip_addresses_not == null) ? 0 - : source_ip_addresses_not.hashCode()); result = prime * result - + ((source_port_max == null) ? 0 : source_port_max.hashCode()); - result = prime * result - + ((source_port_min == null) ? 0 : source_port_min.hashCode()); - result = prime * result - + ((source_port_not == null) ? 0 : source_port_not.hashCode()); + + ((source_port == null) ? 0 : source_port.hashCode()); return result; } @@ -189,26 +115,10 @@ public class Match { } else if (!destination_ip_addresses .equals(other.destination_ip_addresses)) return false; - if (destination_ip_addresses_not == null) { - if (other.destination_ip_addresses_not != null) + if (destination_port == null) { + if (other.destination_port != null) return false; - } else if (!destination_ip_addresses_not - .equals(other.destination_ip_addresses_not)) - return false; - if (destination_port_max == null) { - if (other.destination_port_max != null) - return false; - } else if (!destination_port_max.equals(other.destination_port_max)) - return false; - if (destination_port_min == null) { - if (other.destination_port_min != null) - return false; - } else if (!destination_port_min.equals(other.destination_port_min)) - return false; - if (destination_port_not == null) { - if (other.destination_port_not != null) - return false; - } else if (!destination_port_not.equals(other.destination_port_not)) + } else if (!destination_port.equals(other.destination_port)) return false; if (ethertype == null) { if (other.ethertype != null) @@ -225,26 +135,10 @@ public class Match { return false; } else if (!source_ip_addresses.equals(other.source_ip_addresses)) return false; - if (source_ip_addresses_not == null) { - if (other.source_ip_addresses_not != null) + if (source_port == null) { + if (other.source_port != null) return false; - } else if (!source_ip_addresses_not - .equals(other.source_ip_addresses_not)) - return false; - if (source_port_max == null) { - if (other.source_port_max != null) - return false; - } else if (!source_port_max.equals(other.source_port_max)) - return false; - if (source_port_min == null) { - if (other.source_port_min != null) - return false; - } else if (!source_port_min.equals(other.source_port_min)) - return false; - if (source_port_not == null) { - if (other.source_port_not != null) - return false; - } else if (!source_port_not.equals(other.source_port_not)) + } else if (!source_port.equals(other.source_port)) return false; return true; } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java index b66ffa89b77..93de51e45ac 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NatRule.java @@ -16,267 +16,114 @@ // under the License. package com.cloud.network.nicira; +import java.util.UUID; + /** * */ -public class NatRule { - protected Match match; - protected String to_source_ip_address_min; - protected String to_source_ip_address_max; - protected Integer to_source_port_min; - protected Integer to_source_port_max; - protected String uuid; - protected String type; - protected String to_destination_ip_address_min; - protected String to_destination_ip_address_max; - protected Integer to_destination_port; - - public NatRule() {} - - public Match getMatch() { - return match; - } - - public void setMatch(Match match) { - this.match = match; - } - - public String getToSourceIpAddressMin() { - return to_source_ip_address_min; - } - - public void setToSourceIpAddressMin(String to_source_ip_address_min) { - this.to_source_ip_address_min = to_source_ip_address_min; - } - - public String getToSourceIpAddressMax() { - return to_source_ip_address_max; - } - - public void setToSourceIpAddressMax(String to_source_ip_address_max) { - this.to_source_ip_address_max = to_source_ip_address_max; - } - - public Integer getToSourcePortMin() { - return to_source_port_min; - } - - public void setToSourcePortMin(Integer to_source_port_min) { - this.to_source_port_min = to_source_port_min; - } - - public Integer getToSourcePortMax() { - return to_source_port_max; - } - - public void setToSourcePortMax(Integer to_source_port_max) { - this.to_source_port_max = to_source_port_max; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getToDestinationIpAddressMin() { - return to_destination_ip_address_min; - } - - public void setToDestinationIpAddressMin( - String to_destination_ip_address_min) { - this.to_destination_ip_address_min = to_destination_ip_address_min; - } - - public String getToDestinationIpAddressMax() { - return to_destination_ip_address_max; - } - - public void setToDestinationIpAddressMax( - String to_destination_ip_address_max) { - this.to_destination_ip_address_max = to_destination_ip_address_max; - } - - public Integer getToDestinationPort() { - return to_destination_port; - } - - public void setToDestinationPort(Integer to_destination_port) { - this.to_destination_port = to_destination_port; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } +public abstract class NatRule { + protected Match match; + protected UUID uuid; + protected String type; + protected int order; - @Override - public int hashCode() { - final int prime = 42; - int result = 1; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime - * result - + ((to_destination_ip_address_max == null) ? 0 - : to_destination_ip_address_max.hashCode()); - result = prime - * result - + ((to_destination_ip_address_min == null) ? 0 - : to_destination_ip_address_min.hashCode()); - result = prime - * result - + ((to_destination_port == null) ? 0 : to_destination_port - .hashCode()); - result = prime - * result - + ((to_source_ip_address_max == null) ? 0 - : to_source_ip_address_max.hashCode()); - result = prime - * result - + ((to_source_ip_address_min == null) ? 0 - : to_source_ip_address_min.hashCode()); - result = prime - * result - + ((to_source_port_max == null) ? 0 : to_source_port_max - .hashCode()); - result = prime - * result - + ((to_source_port_min == null) ? 0 : to_source_port_min - .hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); - return result; - } + public NatRule() { + } + + public Match getMatch() { + return match; + } + + public void setMatch(Match match) { + this.match = match; + } + + public UUID getUuid() { + return uuid; + } + + public void setUuid(UUID uuid) { + this.uuid = uuid; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((match == null) ? 0 : match.hashCode()); + result = prime * result + order; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((uuid == null) ? 0 : uuid.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; + NatRule other = (NatRule) obj; + if (match == null) { + if (other.match != null) + return false; + } else if (!match.equals(other.match)) + return false; + if (order != other.order) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (uuid == null) { + if (other.uuid != null) + return false; + } else if (!uuid.equals(other.uuid)) + return false; + return true; + } + + public boolean equalsIgnoreUuid(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NatRule other = (NatRule) obj; + if (match == null) { + if (other.match != null) + return false; + } else if (!match.equals(other.match)) + return false; + if (order != other.order) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NatRule other = (NatRule) obj; - if (match == null) { - if (other.match != null) - return false; - } else if (!match.equals(other.match)) - return false; - if (to_destination_ip_address_max == null) { - if (other.to_destination_ip_address_max != null) - return false; - } else if (!to_destination_ip_address_max - .equals(other.to_destination_ip_address_max)) - return false; - if (to_destination_ip_address_min == null) { - if (other.to_destination_ip_address_min != null) - return false; - } else if (!to_destination_ip_address_min - .equals(other.to_destination_ip_address_min)) - return false; - if (to_destination_port == null) { - if (other.to_destination_port != null) - return false; - } else if (!to_destination_port.equals(other.to_destination_port)) - return false; - if (to_source_ip_address_max == null) { - if (other.to_source_ip_address_max != null) - return false; - } else if (!to_source_ip_address_max - .equals(other.to_source_ip_address_max)) - return false; - if (to_source_ip_address_min == null) { - if (other.to_source_ip_address_min != null) - return false; - } else if (!to_source_ip_address_min - .equals(other.to_source_ip_address_min)) - return false; - if (to_source_port_max == null) { - if (other.to_source_port_max != null) - return false; - } else if (!to_source_port_max.equals(other.to_source_port_max)) - return false; - if (to_source_port_min == null) { - if (other.to_source_port_min != null) - return false; - } else if (!to_source_port_min.equals(other.to_source_port_min)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (uuid == null) { - if (other.uuid != null) - return false; - } else if (!uuid.equals(other.uuid)) - return false; - return true; - } - - public boolean equalsIgnoreUuid(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NatRule other = (NatRule) obj; - if (match == null) { - if (other.match != null) - return false; - } else if (!match.equals(other.match)) - return false; - if (to_destination_ip_address_max == null) { - if (other.to_destination_ip_address_max != null) - return false; - } else if (!to_destination_ip_address_max - .equals(other.to_destination_ip_address_max)) - return false; - if (to_destination_ip_address_min == null) { - if (other.to_destination_ip_address_min != null) - return false; - } else if (!to_destination_ip_address_min - .equals(other.to_destination_ip_address_min)) - return false; - if (to_destination_port == null) { - if (other.to_destination_port != null) - return false; - } else if (!to_destination_port.equals(other.to_destination_port)) - return false; - if (to_source_ip_address_max == null) { - if (other.to_source_ip_address_max != null) - return false; - } else if (!to_source_ip_address_max - .equals(other.to_source_ip_address_max)) - return false; - if (to_source_ip_address_min == null) { - if (other.to_source_ip_address_min != null) - return false; - } else if (!to_source_ip_address_min - .equals(other.to_source_ip_address_min)) - return false; - if (to_source_port_max == null) { - if (other.to_source_port_max != null) - return false; - } else if (!to_source_port_max.equals(other.to_source_port_max)) - return false; - if (to_source_port_min == null) { - if (other.to_source_port_min != null) - return false; - } else if (!to_source_port_min.equals(other.to_source_port_min)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - return true; - } - } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java index 039c174be2d..12fa6c0b67c 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java @@ -34,6 +34,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.UUID; + import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; @@ -41,7 +43,6 @@ import javax.net.ssl.X509TrustManager; import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpConnectionManager; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpMethodBase; @@ -59,7 +60,15 @@ import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; import org.apache.log4j.Logger; + +import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; public class NiciraNvpApi { @@ -73,6 +82,9 @@ public class NiciraNvpApi { private String _adminpass; private HttpClient _client; + private String _nvpversion; + + private Gson _gson; /* This factory method is protected so we can extend this * in the unittests. @@ -118,6 +130,11 @@ public class NiciraNvpApi { s_logger.warn("Failed to register the TrustingProtocolSocketFactory, falling back to default SSLSocketFactory", e); } + _gson = new GsonBuilder() + .registerTypeAdapter(NatRule.class, new NatRuleAdapter()) + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + } public void setControllerAddress(String address) { @@ -170,6 +187,12 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Nicira NVP API login failed " + pm.getStatusText()); } + // Extract the version for later use + if (pm.getResponseHeader("Server") != null) { + _nvpversion = pm.getResponseHeader("Server").getValue(); + s_logger.debug("NVP Controller reports version " + _nvpversion); + } + // Success; the cookie required for login is kept in _client } @@ -290,8 +313,8 @@ public class NiciraNvpApi { executeUpdateObject(natRule, uri, Collections.emptyMap()); } - public void deleteLogicalRouterNatRule(String logicalRouterUuid, String natRuleUuid) throws NiciraNvpApiException { - String uri = "/ws.v1/lrouter/" + logicalRouterUuid + "/nat/" + natRuleUuid; + public void deleteLogicalRouterNatRule(String logicalRouterUuid, UUID natRuleUuid) throws NiciraNvpApiException { + String uri = "/ws.v1/lrouter/" + logicalRouterUuid + "/nat/" + natRuleUuid.toString(); executeDeleteObject(uri); } @@ -342,13 +365,11 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } - Gson gson = new Gson(); - PutMethod pm = (PutMethod) createMethod("put", uri); pm.setRequestHeader("Content-Type", "application/json"); try { pm.setRequestEntity(new StringRequestEntity( - gson.toJson(newObject),"application/json", null)); + _gson.toJson(newObject),"application/json", null)); } catch (UnsupportedEncodingException e) { throw new NiciraNvpApiException("Failed to encode json request body", e); } @@ -371,13 +392,11 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Hostname/credentials are null or empty"); } - Gson gson = new Gson(); - PostMethod pm = (PostMethod) createMethod("post", uri); pm.setRequestHeader("Content-Type", "application/json"); try { pm.setRequestEntity(new StringRequestEntity( - gson.toJson(newObject),"application/json", null)); + _gson.toJson(newObject),"application/json", null)); } catch (UnsupportedEncodingException e) { throw new NiciraNvpApiException("Failed to encode json request body", e); } @@ -393,7 +412,7 @@ public class NiciraNvpApi { T result; try { - result = (T)gson.fromJson(pm.getResponseBodyAsString(), TypeToken.get(newObject.getClass()).getType()); + result = (T)_gson.fromJson(pm.getResponseBodyAsString(), TypeToken.get(newObject.getClass()).getType()); } catch (IOException e) { throw new NiciraNvpApiException("Failed to decode json response body", e); } finally { @@ -450,10 +469,9 @@ public class NiciraNvpApi { throw new NiciraNvpApiException("Failed to retrieve object : " + errorMessage); } - Gson gson = new Gson(); T returnValue; try { - returnValue = (T)gson.fromJson(gm.getResponseBodyAsString(), returnObjectType); + returnValue = (T)_gson.fromJson(gm.getResponseBodyAsString(), returnObjectType); } catch (IOException e) { s_logger.error("IOException while retrieving response body",e); throw new NiciraNvpApiException(e); @@ -577,5 +595,28 @@ public class NiciraNvpApi { } - + public static class NatRuleAdapter implements JsonDeserializer { + + @Override + public NatRule deserialize(JsonElement jsonElement, Type type, + JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + NatRule natRule = null; + + if (!jsonObject.has("type")) { + throw new JsonParseException("Deserializing as a NatRule, but no type present in the json object"); + } + + String natRuleType = jsonObject.get("type").getAsString(); + if ("SourceNatRule".equals(natRuleType)) { + return context.deserialize(jsonElement, SourceNatRule.class); + } + else if ("DestinationNatRule".equals(natRuleType)) { + return context.deserialize(jsonElement, DestinationNatRule.class); + } + + throw new JsonParseException("Failed to deserialize type \"" + natRuleType + "\""); + } + + } } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java new file mode 100644 index 00000000000..5f85ccbc579 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/SourceNatRule.java @@ -0,0 +1,107 @@ +package com.cloud.network.nicira; + +public class SourceNatRule extends NatRule { + private String toSourceIpAddressMax; + private String toSourceIpAddressMin; + private Integer toSourcePort; + + public SourceNatRule() { + setType("SourceNatRule"); + } + + public String getToSourceIpAddressMax() { + return toSourceIpAddressMax; + } + + public void setToSourceIpAddressMax(String toSourceIpAddressMax) { + this.toSourceIpAddressMax = toSourceIpAddressMax; + } + + public String getToSourceIpAddressMin() { + return toSourceIpAddressMin; + } + + public void setToSourceIpAddressMin(String toSourceIpAddressMin) { + this.toSourceIpAddressMin = toSourceIpAddressMin; + } + + public Integer getToSourcePort() { + return toSourcePort; + } + + public void setToSourcePort(Integer toSourcePort) { + this.toSourcePort = toSourcePort; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime + * result + + ((toSourceIpAddressMax == null) ? 0 : toSourceIpAddressMax + .hashCode()); + result = prime + * result + + ((toSourceIpAddressMin == null) ? 0 : toSourceIpAddressMin + .hashCode()); + result = prime * result + + ((toSourcePort == null) ? 0 : toSourcePort.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + SourceNatRule other = (SourceNatRule) obj; + if (toSourceIpAddressMax == null) { + if (other.toSourceIpAddressMax != null) + return false; + } else if (!toSourceIpAddressMax.equals(other.toSourceIpAddressMax)) + return false; + if (toSourceIpAddressMin == null) { + if (other.toSourceIpAddressMin != null) + return false; + } else if (!toSourceIpAddressMin.equals(other.toSourceIpAddressMin)) + return false; + if (toSourcePort == null) { + if (other.toSourcePort != null) + return false; + } else if (!toSourcePort.equals(other.toSourcePort)) + return false; + return true; + } + + @Override + public boolean equalsIgnoreUuid(Object obj) { + if (this == obj) + return true; + if (!super.equalsIgnoreUuid(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + SourceNatRule other = (SourceNatRule) obj; + if (toSourceIpAddressMax == null) { + if (other.toSourceIpAddressMax != null) + return false; + } else if (!toSourceIpAddressMax.equals(other.toSourceIpAddressMax)) + return false; + if (toSourceIpAddressMin == null) { + if (other.toSourceIpAddressMin != null) + return false; + } else if (!toSourceIpAddressMin.equals(other.toSourceIpAddressMin)) + return false; + if (toSourcePort == null) { + if (other.toSourcePort != null) + return false; + } else if (!toSourcePort.equals(other.toSourcePort)) + return false; + return true; + } + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java index 6a9a0060387..114c9395d15 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java @@ -61,6 +61,7 @@ import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.network.nicira.ControlClusterStatus; +import com.cloud.network.nicira.DestinationNatRule; import com.cloud.network.nicira.L3GatewayAttachment; import com.cloud.network.nicira.LogicalRouterConfig; import com.cloud.network.nicira.LogicalRouterPort; @@ -75,6 +76,7 @@ import com.cloud.network.nicira.NiciraNvpTag; import com.cloud.network.nicira.PatchAttachment; import com.cloud.network.nicira.RouterNextHop; import com.cloud.network.nicira.SingleDefaultRouteImplictRoutingConfig; +import com.cloud.network.nicira.SourceNatRule; import com.cloud.network.nicira.TransportZoneBinding; import com.cloud.network.nicira.VifAttachment; import com.cloud.resource.ServerResource; @@ -449,13 +451,13 @@ public class NiciraNvpResource implements ServerResource { new PatchAttachment(lrpi.getUuid())); // Setup the source nat rule - NatRule snr = new NatRule(); - snr.setType("SourceNatRule"); + SourceNatRule snr = new SourceNatRule(); snr.setToSourceIpAddressMin(publicNetworkIpAddress.split("/")[0]); snr.setToSourceIpAddressMax(publicNetworkIpAddress.split("/")[0]); Match match = new Match(); match.setSourceIpAddresses(internalNetworkAddress); snr.setMatch(match); + snr.setOrder(200); _niciraNvpApi.createLogicalRouterNatRule(lrc.getUuid(), snr); } catch (NiciraNvpApiException e) { // We need to destroy the router if we already created it @@ -604,7 +606,8 @@ public class NiciraNvpResource implements ServerResource { continue; } - if (rule.getDstPortRange()[0] != rule.getDstPortRange()[1]) { + if (rule.getDstPortRange()[0] != rule.getDstPortRange()[1] || + rule.getSrcPortRange()[0] != rule.getSrcPortRange()[1] ) { return new ConfigurePortForwardingRulesOnLogicalRouterAnswer(cmd, false, "Nicira NVP doesn't support port ranges for port forwarding"); } @@ -700,32 +703,24 @@ public class NiciraNvpResource implements ServerResource { natRuleStr.append(" "); natRuleStr.append(m.getSourceIpAddresses()); natRuleStr.append(" ["); - natRuleStr.append(m.getSourcePortMin()); - natRuleStr.append("-"); - natRuleStr.append(m.getSourcePortMax()); + natRuleStr.append(m.getSourcePort()); natRuleStr.append(" ] -> "); natRuleStr.append(m.getDestinationIpAddresses()); natRuleStr.append(" ["); - natRuleStr.append(m.getDestinationPortMin()); - natRuleStr.append("-"); - natRuleStr.append(m.getDestinationPortMax()); + natRuleStr.append(m.getDestinationPort()); natRuleStr.append(" ]) -->"); if ("SourceNatRule".equals(rule.getType())) { - natRuleStr.append(rule.getToSourceIpAddressMin()); + natRuleStr.append(((SourceNatRule)rule).getToSourceIpAddressMin()); natRuleStr.append("-"); - natRuleStr.append(rule.getToSourceIpAddressMax()); + natRuleStr.append(((SourceNatRule)rule).getToSourceIpAddressMax()); natRuleStr.append(" ["); - natRuleStr.append(rule.getToSourcePortMin()); - natRuleStr.append("-"); - natRuleStr.append(rule.getToSourcePortMax()); + natRuleStr.append(((SourceNatRule)rule).getToSourcePort()); natRuleStr.append(" ])"); } else { - natRuleStr.append(rule.getToDestinationIpAddressMin()); - natRuleStr.append("-"); - natRuleStr.append(rule.getToDestinationIpAddressMax()); + natRuleStr.append(((DestinationNatRule)rule).getToDestinationIpAddress()); natRuleStr.append(" ["); - natRuleStr.append(rule.getToDestinationPort()); + natRuleStr.append(((DestinationNatRule)rule).getToDestinationPort()); natRuleStr.append(" ])"); } return natRuleStr.toString(); @@ -742,23 +737,24 @@ public class NiciraNvpResource implements ServerResource { protected NatRule[] generateStaticNatRulePair(String insideIp, String outsideIp) { NatRule[] rulepair = new NatRule[2]; - rulepair[0] = new NatRule(); + rulepair[0] = new DestinationNatRule(); rulepair[0].setType("DestinationNatRule"); - rulepair[1] = new NatRule(); + rulepair[0].setOrder(100); + rulepair[1] = new SourceNatRule(); rulepair[1].setType("SourceNatRule"); + rulepair[1].setOrder(100); Match m = new Match(); m.setDestinationIpAddresses(outsideIp); rulepair[0].setMatch(m); - rulepair[0].setToDestinationIpAddressMin(insideIp); - rulepair[0].setToDestinationIpAddressMax(insideIp); + ((DestinationNatRule)rulepair[0]).setToDestinationIpAddress(insideIp); // create matching snat rule m = new Match(); m.setSourceIpAddresses(insideIp); rulepair[1].setMatch(m); - rulepair[1].setToSourceIpAddressMin(outsideIp); - rulepair[1].setToSourceIpAddressMax(outsideIp); + ((SourceNatRule)rulepair[1]).setToSourceIpAddressMin(outsideIp); + ((SourceNatRule)rulepair[1]).setToSourceIpAddressMax(outsideIp); return rulepair; @@ -768,9 +764,9 @@ public class NiciraNvpResource implements ServerResource { // Start with a basic static nat rule, then add port and protocol details NatRule[] rulepair = generateStaticNatRulePair(insideIp, outsideIp); - rulepair[0].setToDestinationPort(insidePorts[0]); - rulepair[0].getMatch().setDestinationPortMin(outsidePorts[0]); - rulepair[0].getMatch().setDestinationPortMax(outsidePorts[1]); + ((DestinationNatRule)rulepair[0]).setToDestinationPort(insidePorts[0]); + rulepair[0].getMatch().setDestinationPort(outsidePorts[0]); + rulepair[0].setOrder(50); rulepair[0].getMatch().setEthertype("IPv4"); if ("tcp".equals(protocol)) { rulepair[0].getMatch().setProtocol(6); @@ -779,10 +775,9 @@ public class NiciraNvpResource implements ServerResource { rulepair[0].getMatch().setProtocol(17); } - rulepair[1].setToSourcePortMin(outsidePorts[0]); - rulepair[1].setToSourcePortMax(outsidePorts[1]); - rulepair[1].getMatch().setSourcePortMin(insidePorts[0]); - rulepair[1].getMatch().setSourcePortMax(insidePorts[1]); + ((SourceNatRule)rulepair[1]).setToSourcePort(outsidePorts[0]); + rulepair[1].getMatch().setSourcePort(insidePorts[0]); + rulepair[1].setOrder(50); rulepair[1].getMatch().setEthertype("IPv4"); if ("tcp".equals(protocol)) { rulepair[1].getMatch().setProtocol(6); diff --git a/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java index 88c5402822d..8e7245ebbdf 100644 --- a/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java +++ b/plugins/network-elements/nicira-nvp/test/com/cloud/network/nicira/NatRuleTest.java @@ -20,28 +20,33 @@ import static org.junit.Assert.*; import org.junit.Test; +import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; public class NatRuleTest { - Gson gson = new Gson(); + @Test + public void testNatRuleEncoding() { + Gson gson = new GsonBuilder() + .registerTypeAdapter(NatRule.class, new com.cloud.network.nicira.NiciraNvpApi.NatRuleAdapter()) + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + + DestinationNatRule rn1 = new DestinationNatRule(); + rn1.setToDestinationIpAddress("10.10.10.10"); + rn1.setToDestinationPort(80); + Match mr1 = new Match(); + mr1.setSourceIpAddresses("11.11.11.11/24"); + mr1.setEthertype("IPv4"); + mr1.setProtocol(6); + rn1.setMatch(mr1); + + String jsonString = gson.toJson(rn1); + NatRule dnr = gson.fromJson(jsonString, NatRule.class); + + assertTrue(dnr instanceof DestinationNatRule); + assertTrue(rn1.equals(dnr)); + } - @Test - public void testNatRuleEncoding() { - NatRule rn1 = new NatRule(); - rn1.setToDestinationIpAddressMax("10.10.10.10"); - rn1.setToDestinationIpAddressMin("10.10.10.10"); - rn1.setToDestinationPort(80); - Match mr1 = new Match(); - mr1.setSourceIpAddresses("11.11.11.11/24"); - mr1.setEthertype("IPv4"); - mr1.setProtocol(6); - rn1.setMatch(mr1); - - - String jsonString = gson.toJson(rn1); - NatRule dnr = gson.fromJson(jsonString, NatRule.class); - - assertTrue(rn1.equals(dnr)); - } } diff --git a/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java b/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java index e3789108f34..8b5af3cc12d 100644 --- a/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java +++ b/plugins/network-elements/nicira-nvp/test/com/cloud/network/resource/NiciraNvpResourceTest.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.naming.ConfigurationException; @@ -61,6 +62,7 @@ import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.host.Host; import com.cloud.network.nicira.Attachment; import com.cloud.network.nicira.ControlClusterStatus; +import com.cloud.network.nicira.DestinationNatRule; import com.cloud.network.nicira.LogicalRouterConfig; import com.cloud.network.nicira.LogicalRouterPort; import com.cloud.network.nicira.LogicalSwitch; @@ -69,6 +71,7 @@ import com.cloud.network.nicira.NatRule; import com.cloud.network.nicira.NiciraNvpApi; import com.cloud.network.nicira.NiciraNvpApiException; import com.cloud.network.nicira.NiciraNvpList; +import com.cloud.network.nicira.SourceNatRule; public class NiciraNvpResourceTest { NiciraNvpApi _nvpApi = mock(NiciraNvpApi.class); @@ -440,8 +443,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); ConfigureStaticNatRulesOnLogicalRouterAnswer a = (ConfigureStaticNatRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); @@ -452,11 +455,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -481,8 +484,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -500,11 +503,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -529,8 +532,10 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + final UUID rule0Uuid = UUID.randomUUID(); + final UUID rule1Uuid = UUID.randomUUID(); + rulepair[0].setUuid(rule0Uuid); + rulepair[1].setUuid(rule1Uuid); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -543,11 +548,11 @@ public class NiciraNvpResourceTest { ConfigureStaticNatRulesOnLogicalRouterAnswer a = (ConfigureStaticNatRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertTrue(a.getResult()); - verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { + verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override public boolean matches(Object argument) { - String uuid = (String) argument; - if ("bbbbb".equals(uuid) || "ccccc".equals(uuid)) { + UUID uuid = (UUID) argument; + if (rule0Uuid.equals(uuid) || rule1Uuid.equals(uuid)) { return true; } return false; @@ -572,8 +577,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generateStaticNatRulePair("10.10.10.10", "11.11.11.11"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenThrow(new NiciraNvpApiException()); // Mock the api find call @@ -585,7 +590,7 @@ public class NiciraNvpResourceTest { ConfigureStaticNatRulesOnLogicalRouterAnswer a = (ConfigureStaticNatRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertFalse(a.getResult()); - verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq("bbbbb")); + verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq(rulepair[0].getUuid())); } @Test @@ -611,8 +616,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); @@ -623,11 +628,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -652,8 +657,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -671,11 +676,11 @@ public class NiciraNvpResourceTest { public boolean matches(Object argument) { NatRule rule = (NatRule) argument; if (rule.getType().equals("DestinationNatRule") && - rule.getToDestinationIpAddressMin().equals("10.10.10.10")) { + ((DestinationNatRule)rule).getToDestinationIpAddress().equals("10.10.10.10")) { return true; } if (rule.getType().equals("SourceNatRule") && - rule.getToSourceIpAddressMin().equals("11.11.11.11")) { + ((SourceNatRule)rule).getToSourceIpAddressMin().equals("11.11.11.11")) { return true; } return false; @@ -700,8 +705,10 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + final UUID rule0Uuid = UUID.randomUUID(); + final UUID rule1Uuid = UUID.randomUUID(); + rulepair[0].setUuid(rule0Uuid); + rulepair[1].setUuid(rule1Uuid); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); // Mock the api find call @@ -714,11 +721,11 @@ public class NiciraNvpResourceTest { ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertTrue(a.getResult()); - verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { + verify(_nvpApi, atLeast(2)).deleteLogicalRouterNatRule(eq("aaaaa"), argThat(new ArgumentMatcher() { @Override public boolean matches(Object argument) { - String uuid = (String) argument; - if ("bbbbb".equals(uuid) || "ccccc".equals(uuid)) { + UUID uuid = (UUID) argument; + if (rule0Uuid.equals(uuid) || rule1Uuid.equals(uuid)) { return true; } return false; @@ -743,8 +750,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 8080, 8080 }, "11.11.11.11", new int[] { 80, 80}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenThrow(new NiciraNvpApiException()); // Mock the api find call @@ -756,7 +763,7 @@ public class NiciraNvpResourceTest { ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); assertFalse(a.getResult()); - verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq("bbbbb")); + verify(_nvpApi, atLeastOnce()).deleteLogicalRouterNatRule(eq("aaaaa"), eq(rulepair[0].getUuid())); } @Test @@ -782,8 +789,8 @@ public class NiciraNvpResourceTest { // Mock the api create calls NatRule[] rulepair = _resource.generatePortForwardingRulePair("10.10.10.10", new int[] { 80, 85 }, "11.11.11.11", new int[] { 80, 85}, "tcp"); - rulepair[0].setUuid("bbbbb"); - rulepair[1].setUuid("ccccc"); + rulepair[0].setUuid(UUID.randomUUID()); + rulepair[1].setUuid(UUID.randomUUID()); when(_nvpApi.createLogicalRouterNatRule(eq("aaaaa"), (NatRule)any())).thenReturn(rulepair[0]).thenReturn(rulepair[1]); ConfigurePortForwardingRulesOnLogicalRouterAnswer a = (ConfigurePortForwardingRulesOnLogicalRouterAnswer) _resource.executeRequest(cmd); @@ -799,13 +806,15 @@ public class NiciraNvpResourceTest { assertTrue("DestinationNatRule".equals(rules[0].getType())); assertTrue("SourceNatRule".equals(rules[1].getType())); - assertTrue(rules[0].getToDestinationIpAddressMin().equals("10.10.10.10") && rules[0].getToDestinationIpAddressMax().equals("10.10.10.10")); - assertTrue(rules[0].getToDestinationPort() == null); - assertTrue(rules[0].getMatch().getDestinationIpAddresses().equals("11.11.11.11")); + DestinationNatRule dnr = (DestinationNatRule) rules[0]; + assertTrue(dnr.getToDestinationIpAddress().equals("10.10.10.10")); + assertTrue(dnr.getToDestinationPort() == null); + assertTrue(dnr.getMatch().getDestinationIpAddresses().equals("11.11.11.11")); - assertTrue(rules[1].getToSourceIpAddressMin().equals("11.11.11.11") && rules[1].getToSourceIpAddressMax().equals("11.11.11.11")); - assertTrue(rules[1].getToSourcePortMin() == null && rules[1].getToSourcePortMax() == null); - assertTrue(rules[1].getMatch().getSourceIpAddresses().equals("10.10.10.10")); + SourceNatRule snr = (SourceNatRule) rules[1]; + assertTrue(snr.getToSourceIpAddressMin().equals("11.11.11.11") && snr.getToSourceIpAddressMax().equals("11.11.11.11")); + assertTrue(snr.getToSourcePort() == null); + assertTrue(snr.getMatch().getSourceIpAddresses().equals("10.10.10.10")); } @Test @@ -814,17 +823,19 @@ public class NiciraNvpResourceTest { assertTrue("DestinationNatRule".equals(rules[0].getType())); assertTrue("SourceNatRule".equals(rules[1].getType())); - assertTrue(rules[0].getToDestinationIpAddressMin().equals("10.10.10.10") && rules[0].getToDestinationIpAddressMax().equals("10.10.10.10")); - assertTrue(rules[0].getToDestinationPort() == 8080); - assertTrue(rules[0].getMatch().getDestinationIpAddresses().equals("11.11.11.11")); - assertTrue(rules[0].getMatch().getDestinationPortMin() == 80 && rules[0].getMatch().getDestinationPortMax() == 80); - assertTrue(rules[0].getMatch().getEthertype().equals("IPv4") && rules[0].getMatch().getProtocol() == 6); + DestinationNatRule dnr = (DestinationNatRule) rules[0]; + assertTrue(dnr.getToDestinationIpAddress().equals("10.10.10.10")); + assertTrue(dnr.getToDestinationPort() == 8080); + assertTrue(dnr.getMatch().getDestinationIpAddresses().equals("11.11.11.11")); + assertTrue(dnr.getMatch().getDestinationPort() == 80 ); + assertTrue(dnr.getMatch().getEthertype().equals("IPv4") && dnr.getMatch().getProtocol() == 6); - assertTrue(rules[1].getToSourceIpAddressMin().equals("11.11.11.11") && rules[1].getToSourceIpAddressMax().equals("11.11.11.11")); - assertTrue(rules[1].getToSourcePortMin() == 80 && rules[1].getToSourcePortMax() == 80); - assertTrue(rules[1].getMatch().getSourceIpAddresses().equals("10.10.10.10")); - assertTrue(rules[1].getMatch().getSourcePortMin() == 8080 && rules[1].getMatch().getSourcePortMax() == 8080); - assertTrue(rules[1].getMatch().getEthertype().equals("IPv4") && rules[1].getMatch().getProtocol() == 6); + SourceNatRule snr = (SourceNatRule) rules[1]; + assertTrue(snr.getToSourceIpAddressMin().equals("11.11.11.11") && snr.getToSourceIpAddressMax().equals("11.11.11.11")); + assertTrue(snr.getToSourcePort() == 80); + assertTrue(snr.getMatch().getSourceIpAddresses().equals("10.10.10.10")); + assertTrue(snr.getMatch().getSourcePort() == 8080); + assertTrue(snr.getMatch().getEthertype().equals("IPv4") && rules[1].getMatch().getProtocol() == 6); } } diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 135fd290535..8971f8c163b 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -320,8 +320,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { } else { if (rulesRevoked) { // no active rules/revoked rules are associated with this public IP, so remove the - // association with the provider - ip.setState(State.Releasing); + // association with the provider + if (ip.isSourceNat()) { + s_logger.debug("Not releasing ip " + ip.getAddress().addr() + " as it is in use for SourceNat"); + } else { + ip.setState(State.Releasing); + } } else { if (ip.getState() == State.Releasing) { // rules are not revoked yet, so don't let the network service provider revoke the IP