You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/06/16 00:38:03 UTC

[50/51] [abbrv] git commit: AssociateIpAddress to VPC - the ip gets associated to the network only when the first rule for the ip gets created. When the last rule is removed for vpc ip, networkId is set to null

AssociateIpAddress to VPC - the ip gets associated to the network only when the first rule for the ip gets created.
When the last rule is removed for vpc ip, networkId is set to null

Conflicts:

	api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
	api/src/com/cloud/api/commands/EnableStaticNatCmd.java
	api/src/com/cloud/network/NetworkService.java
	api/src/com/cloud/network/rules/RulesService.java
	server/src/com/cloud/network/NetworkManagerImpl.java
	server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
	server/src/com/cloud/network/rules/RulesManagerImpl.java
	server/test/com/cloud/network/MockNetworkManagerImpl.java


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/929997f5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/929997f5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/929997f5

Branch: refs/heads/vpc
Commit: 929997f54e66fb2641a69b9d725107119d7d020c
Parents: c56998e
Author: Alena Prokharchyk <al...@citrix.com>
Authored: Wed May 30 19:38:25 2012 -0700
Committer: Alena Prokharchyk <al...@citrix.com>
Committed: Fri Jun 15 14:18:24 2012 -0700

----------------------------------------------------------------------
 .../com/cloud/api/commands/AssociateIPAddrCmd.java |   68 +++-
 .../cloud/api/commands/CreateFirewallRuleCmd.java  |   19 +-
 .../api/commands/CreateLoadBalancerRuleCmd.java    |    7 +-
 .../api/commands/CreatePortForwardingRuleCmd.java  |   47 ++-
 .../api/commands/CreateRemoteAccessVpnCmd.java     |   23 +-
 .../cloud/api/commands/DisassociateIPAddrCmd.java  |    7 +-
 .../com/cloud/api/commands/EnableStaticNatCmd.java |   31 ++-
 api/src/com/cloud/network/NetworkService.java      |   33 +-
 api/src/com/cloud/network/rules/RulesService.java  |    2 +-
 .../cloud/network/vpn/RemoteAccessVpnService.java  |    2 +-
 .../configuration/ConfigurationManagerImpl.java    |    2 +-
 .../ExternalLoadBalancerDeviceManagerImpl.java     |    4 +-
 server/src/com/cloud/network/NetworkManager.java   |   26 +-
 .../src/com/cloud/network/NetworkManagerImpl.java  |  325 +++++++++------
 .../network/firewall/FirewallManagerImpl.java      |   69 +++-
 .../network/lb/ElasticLoadBalancerManagerImpl.java |    2 +-
 .../network/lb/LoadBalancingRulesManagerImpl.java  |   18 +-
 .../com/cloud/network/rules/FirewallManager.java   |    4 +-
 .../com/cloud/network/rules/RulesManagerImpl.java  |  106 ++++--
 .../src/com/cloud/network/vpc/VpcManagerImpl.java  |    2 +-
 .../network/vpn/RemoteAccessVpnManagerImpl.java    |   21 +-
 server/src/com/cloud/user/AccountManagerImpl.java  |    2 +-
 .../com/cloud/network/MockNetworkManagerImpl.java  |  285 ++++++++-----
 wscript                                            |    2 +-
 24 files changed, 758 insertions(+), 349 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
index 415f78e..b749ab3 100644
--- a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
+++ b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
@@ -41,6 +41,7 @@ import com.cloud.exception.ResourceAllocationException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.network.IpAddress;
 import com.cloud.network.Network;
+import com.cloud.network.vpc.Vpc;
 import com.cloud.user.Account;
 import com.cloud.user.UserContext;
 
@@ -53,24 +54,34 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
     //////////////// API parameters /////////////////////
     /////////////////////////////////////////////////////
 
-    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account to associate with this IP address")
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, 
+            description="the account to associate with this IP address")
     private String accountName;
 
     @IdentityMapper(entityTableName="domain")
-    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the domain to associate with this IP address")
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, 
+        description="the ID of the domain to associate with this IP address")
     private Long domainId;
 
     @IdentityMapper(entityTableName="data_center")
-    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, description="the ID of the availability zone you want to acquire an public IP address from")
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 
+        description="the ID of the availability zone you want to acquire an public IP address from")
     private Long zoneId;
     
     @IdentityMapper(entityTableName="networks")
-    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="The network this ip address should be associated to.")
+    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, 
+        description="The network this ip address should be associated to.")
     private Long networkId;
     
     @IdentityMapper(entityTableName="projects")
-    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="Deploy vm for the project")
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, 
+        description="Deploy vm for the project")
     private Long projectId;
+    
+    @IdentityMapper(entityTableName="vpc")
+    @Parameter(name=ApiConstants.VPC_ID, type=CommandType.LONG, description="the VPC you want the ip address to " +
+    		"be associated with")
+    private Long vpcId;
 
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
@@ -94,18 +105,40 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
         return UserContext.current().getCaller().getDomainId();
     }
 
-    private Long getZoneId() {
-        return zoneId;
+    private long getZoneId() {
+        if (zoneId != null) {
+            return zoneId;
+        } else if (vpcId != null) {
+            Vpc vpc = _entityMgr.findById(Vpc.class, vpcId);
+            if (vpc != null) {
+                return vpc.getZoneId();
+            }
+        } else if (networkId != null) {
+            Network ntwk = _entityMgr.findById(Network.class, networkId);
+            if (ntwk != null) {
+                return ntwk.getDataCenterId();
+            }
+        }
+        
+        throw new InvalidParameterValueException("Unable to figure out zone to assign ip to");
+    }
+    
+    public Long getVpcId() {
+        return vpcId;
     }
     
     public Long getNetworkId() {
+        if (vpcId != null) {
+            return null;
+        }
+        
         if (networkId != null) {
             return networkId;
         } 
         Long zoneId = getZoneId();
         
         if (zoneId == null) {
-        	throw new InvalidParameterValueException("Either networkId or zoneId has to be specified");
+            return null;
         }
         
         DataCenter zone = _configService.getZone(zoneId);
@@ -114,7 +147,8 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
                     _accountService.getAccount(getEntityOwnerId()));
             if (networks.size() == 0) {
                 String domain = _domainService.getDomain(getDomainId()).getName();
-                throw new InvalidParameterValueException("Account name=" + getAccountName() + " domain=" + domain + " doesn't have virtual networks in zone=" + zone.getName());
+                throw new InvalidParameterValueException("Account name=" + getAccountName() + " domain=" + domain + 
+                        " doesn't have virtual networks in zone=" + zone.getName());
             }
             
             if (networks.size() < 1) {
@@ -127,7 +161,8 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
         } else {
             Network defaultGuestNetwork = _networkService.getExclusiveGuestNetwork(zoneId);
             if (defaultGuestNetwork == null) {
-                throw new InvalidParameterValueException("Unable to find a default Guest network for account " + getAccountName() + " in domain id=" + getDomainId());
+                throw new InvalidParameterValueException("Unable to find a default Guest network for account " + 
+                        getAccountName() + " in domain id=" + getDomainId());
             } else {
                 return defaultGuestNetwork.getId();
             }
@@ -173,7 +208,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
     @Override
     public void create() throws ResourceAllocationException{
         try {
-            IpAddress ip = _networkService.allocateIP(getNetworkId(), _accountService.getAccount(getEntityOwnerId()));
+            IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), false, getZoneId());
             if (ip != null) {
                 this.setEntityId(ip.getId());
             } else {
@@ -190,9 +225,16 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
     }
     
     @Override
-    public void execute() throws ResourceUnavailableException, ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException {
+    public void execute() throws ResourceUnavailableException, ResourceAllocationException, 
+                                    ConcurrentOperationException, InsufficientCapacityException {
         UserContext.current().setEventDetails("Ip Id: " + getEntityId());
-        IpAddress result = _networkService.associateIP(getEntityId());
+
+        IpAddress result = null;
+        
+        if (getVpcId() != null) {
+            result = _networkService.associateIP(getEntityId(), getNetworkId(), getVpcId());
+        }
+
         if (result != null) {
             IPAddressResponse ipResponse = _responseGenerator.createIPAddressResponse(result);
             ipResponse.setResponseName(getCommandName());

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/CreateFirewallRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/CreateFirewallRuleCmd.java b/api/src/com/cloud/api/commands/CreateFirewallRuleCmd.java
index 81817dc..800dac8 100644
--- a/api/src/com/cloud/api/commands/CreateFirewallRuleCmd.java
+++ b/api/src/com/cloud/api/commands/CreateFirewallRuleCmd.java
@@ -76,6 +76,11 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
     @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "type of firewallrule: system/user")
     private String type;
     
+    @IdentityMapper(entityTableName="networks")
+    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, 
+        description="The network of the vm the Firewall rule will be created for")
+    private Long networkId;
+    
     // ///////////////////////////////////////////////////
     // ///////////////// Accessors ///////////////////////
     // ///////////////////////////////////////////////////
@@ -191,7 +196,19 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
 
     @Override
     public long getNetworkId() {
-        throw new UnsupportedOperationException("Not yet implemented");
+        IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
+        Long ntwkId = null;
+        
+        if (ip.getAssociatedWithNetworkId() != null) {
+            ntwkId = ip.getAssociatedWithNetworkId();
+        } else {
+            ntwkId = networkId;
+        }
+        if (ntwkId == null) {
+            throw new InvalidParameterValueException("Unable to create firewall rule for the ipAddress id=" + ipAddressId + 
+                    " as ip is not associated with any network and no networkId is passed in");
+        }
+        return ntwkId;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
index 455d458..8ad84d7 100644
--- a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
+++ b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
@@ -171,9 +171,12 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd  /*implements
             }
         } else {
         	IpAddress ipAddr = _networkService.getIp(publicIpId);
-        	return ipAddr.getAssociatedWithNetworkId();
+        	if (ipAddr.getAssociatedWithNetworkId() != null) {
+                return ipAddr.getAssociatedWithNetworkId();
+        	} else {
+        	    throw new InvalidParameterValueException("Ip address id=" + publicIpId + " is not associated with any network");
+        	}
         }
-        
     }
 
     public Integer getPublicPort() {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
index 57e15f9..b17b6e1 100644
--- a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
+++ b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java
@@ -51,27 +51,40 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
     // ///////////////////////////////////////////////////
 
     @IdentityMapper(entityTableName = "user_ip_address")
-    @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.LONG, required = true, description = "the IP address id of the port forwarding rule")
+    @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.LONG, required = true, 
+    description = "the IP address id of the port forwarding rule")
     private Long ipAddressId;
 
-    @Parameter(name = ApiConstants.PRIVATE_START_PORT, type = CommandType.INTEGER, required = true, description = "the starting port of port forwarding rule's private port range")
+    @Parameter(name = ApiConstants.PRIVATE_START_PORT, type = CommandType.INTEGER, required = true, 
+            description = "the starting port of port forwarding rule's private port range")
     private Integer privateStartPort;
 
-    @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the port fowarding rule. Valid values are TCP or UDP.")
+    @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, 
+            description = "the protocol for the port fowarding rule. Valid values are TCP or UDP.")
     private String protocol;
 
-    @Parameter(name = ApiConstants.PUBLIC_START_PORT, type = CommandType.INTEGER, required = true, description = "the starting port of port forwarding rule's public port range")
+    @Parameter(name = ApiConstants.PUBLIC_START_PORT, type = CommandType.INTEGER, required = true, 
+            description = "the starting port of port forwarding rule's public port range")
     private Integer publicStartPort;
 
     @IdentityMapper(entityTableName = "vm_instance")
-    @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.LONG, required = true, description = "the ID of the virtual machine for the port forwarding rule")
+    @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.LONG, required = true, 
+                description = "the ID of the virtual machine for the port forwarding rule")
     private Long virtualMachineId;
 
-    @Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
+    @Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING,
+            description = "the cidr list to forward traffic from")
     private List<String> cidrlist;
 
-    @Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, description = "if true, firewall rule for source/end pubic port is automatically created; if false - firewall rule has to be created explicitely. Has value true by default")
+    @Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, 
+            description = "if true, firewall rule for source/end pubic port is automatically created; " +
+            		"if false - firewall rule has to be created explicitely. Has value true by default")
     private Boolean openFirewall;
+    
+    @IdentityMapper(entityTableName="networks")
+    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, 
+        description="The network of the vm the Port Forwarding rule will be created for")
+    private Long networkId;
 
     // ///////////////////////////////////////////////////
     // ///////////////// Accessors ///////////////////////
@@ -97,7 +110,8 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
 
     public List<String> getSourceCidrList() {
         if (cidrlist != null) {
-            throw new InvalidParameterValueException("Parameter cidrList is deprecated; if you need to open firewall rule for the specific cidr, please refer to createFirewallRule command");
+            throw new InvalidParameterValueException("Parameter cidrList is deprecated; if you need to open firewall " +
+            		"rule for the specific cidr, please refer to createFirewallRule command");
         }
         return null;
     }
@@ -193,7 +207,19 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
 
     @Override
     public long getNetworkId() {
-        throw new UnsupportedOperationException("Not yet implemented");
+        IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
+        Long ntwkId = null;
+        
+        if (ip.getAssociatedWithNetworkId() != null) {
+            ntwkId = ip.getAssociatedWithNetworkId();
+        } else {
+            ntwkId = networkId;
+        }
+        if (ntwkId == null) {
+            throw new InvalidParameterValueException("Unable to create port forwarding rule for the ipAddress id=" + ipAddressId + 
+                    " as ip is not associated with any network and no networkId is passed in");
+        }
+        return ntwkId;
     }
 
     @Override
@@ -205,7 +231,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
         }
 
         return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are
-// tracked
+        // tracked
     }
 
     @Override
@@ -236,7 +262,6 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
 
     @Override
     public void create() {
-
         // cidr list parameter is deprecated
         if (cidrlist != null) {
             throw new InvalidParameterValueException("Parameter cidrList is deprecated; if you need to open firewall rule for the specific cidr, please refer to createFirewallRule command");

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/CreateRemoteAccessVpnCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/CreateRemoteAccessVpnCmd.java b/api/src/com/cloud/api/commands/CreateRemoteAccessVpnCmd.java
index f7b9c72..77f49b0 100644
--- a/api/src/com/cloud/api/commands/CreateRemoteAccessVpnCmd.java
+++ b/api/src/com/cloud/api/commands/CreateRemoteAccessVpnCmd.java
@@ -62,6 +62,11 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
     @Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN, description = "if true, firewall rule for source/end pubic port is automatically created; if false - firewall rule has to be created explicitely. Has value true by default")
     private Boolean openFirewall;
     
+    @IdentityMapper(entityTableName="networks")
+    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, 
+        description="The network of the ip the VPN be created for")
+    private Long networkId;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -129,10 +134,26 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
 		return EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE;
 	}
 	
+    public long getNetworkId() {
+        IpAddress ip = _entityMgr.findById(IpAddress.class, getPublicIpId());
+        Long ntwkId = null;
+        
+        if (ip.getAssociatedWithNetworkId() != null) {
+            ntwkId = ip.getAssociatedWithNetworkId();
+        } else {
+            ntwkId = networkId;
+        }
+        if (ntwkId == null) {
+            throw new InvalidParameterValueException("Unable to create remote access vpn for the ipAddress id=" + getPublicIpId() + 
+                    " as ip is not associated with any network and no networkId is passed in");
+        }
+        return ntwkId;
+    }
+	
     @Override
     public void create() {
         try {
-            RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall());
+            RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall(), getNetworkId());
             if (vpn != null) {
                 this.setEntityId(vpn.getServerAddressId());
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/DisassociateIPAddrCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/DisassociateIPAddrCmd.java b/api/src/com/cloud/api/commands/DisassociateIPAddrCmd.java
index c74270e..2f2addb 100644
--- a/api/src/com/cloud/api/commands/DisassociateIPAddrCmd.java
+++ b/api/src/com/cloud/api/commands/DisassociateIPAddrCmd.java
@@ -45,7 +45,8 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd {
     /////////////////////////////////////////////////////
 
     @IdentityMapper(entityTableName="user_ip_address")
-    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the id of the public ip address to disassociate")
+    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the id of the public ip address" +
+    		" to disassociate")
     private Long id;
 
     // unexposed parameter needed for events logging
@@ -71,8 +72,8 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd {
 
     @Override
     public void execute() throws InsufficientAddressCapacityException{
-        UserContext.current().setEventDetails("Ip Id: "+getIpAddressId());
-        boolean result = _networkService.disassociateIpAddress(id);
+        UserContext.current().setEventDetails("Ip Id: " + getIpAddressId());
+        boolean result = _networkService.releaseIpAddress(getIpAddressId());
         if (result) {
             SuccessResponse response = new SuccessResponse(getCommandName());
             this.setResponseObject(response);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/EnableStaticNatCmd.java b/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
index 75d7e3b..fdd0ee5 100644
--- a/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
+++ b/api/src/com/cloud/api/commands/EnableStaticNatCmd.java
@@ -25,8 +25,10 @@ import com.cloud.api.Implementation;
 import com.cloud.api.Parameter;
 import com.cloud.api.ServerApiException;
 import com.cloud.api.response.SuccessResponse;
+import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.NetworkRuleConflictException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
 import com.cloud.user.Account;
 import com.cloud.uservm.UserVm;
 
@@ -41,12 +43,19 @@ public class EnableStaticNatCmd extends BaseCmd{
     /////////////////////////////////////////////////////
 
     @IdentityMapper(entityTableName="user_ip_address")
-    @Parameter(name=ApiConstants.IP_ADDRESS_ID, type=CommandType.LONG, required=true, description="the public IP address id for which static nat feature is being enabled")
+    @Parameter(name=ApiConstants.IP_ADDRESS_ID, type=CommandType.LONG, required=true, description="the public IP " +
+    		"address id for which static nat feature is being enabled")
     private Long ipAddressId;
 
     @IdentityMapper(entityTableName="vm_instance")
-    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, required=true, description="the ID of the virtual machine for enabling static nat feature")
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, required=true, description="the ID of " +
+    		"the virtual machine for enabling static nat feature")
     private Long virtualMachineId;
+    
+    @IdentityMapper(entityTableName="networks")
+    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, 
+        description="The network of the vm the static nat will be enabled for.")
+    private Long networkId;
 
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
@@ -59,6 +68,22 @@ public class EnableStaticNatCmd extends BaseCmd{
     public Long getVirtualMachineId() {
         return virtualMachineId;
     }
+    
+    public long getNetworkId() {
+        IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
+        Long ntwkId = null;
+        
+        if (ip.getAssociatedWithNetworkId() != null) {
+            ntwkId = ip.getAssociatedWithNetworkId();
+        } else {
+            ntwkId = networkId;
+        }
+        if (ntwkId == null) {
+            throw new InvalidParameterValueException("Unable to enable static nat for the ipAddress id=" + ipAddressId + 
+                    " as ip is not associated with any network and no networkId is passed in");
+        }
+        return ntwkId;
+    }
 
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
@@ -82,7 +107,7 @@ public class EnableStaticNatCmd extends BaseCmd{
     @Override
     public void execute() throws ResourceUnavailableException{ 
         try {
-            boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, false);
+            boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), false);
             if (result) {
                 SuccessResponse response = new SuccessResponse(getCommandName());
                 this.setResponseObject(response);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/network/NetworkService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java
index dea1fc8..dacd6ff 100755
--- a/api/src/com/cloud/network/NetworkService.java
+++ b/api/src/com/cloud/network/NetworkService.java
@@ -41,23 +41,10 @@ public interface NetworkService {
 
     List<? extends Network> getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner);
 
-    IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException;
-    IpAddress allocateIP(long networkId, Account ipOwner, boolean isSystem) throws ResourceAllocationException, 
-    InsufficientAddressCapacityException, ConcurrentOperationException;
+    IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, 
+        InsufficientAddressCapacityException, ConcurrentOperationException;
 
-    /**
-     * Associates a public IP address for a router.
-     * 
-     * @param ipId
-     *            - the command specifying ipAddress
-     * @return ip address object
-     * @throws ResourceAllocationException
-     *             , InsufficientCapacityException
-     */
-    IpAddress associateIP(long ipId) throws ResourceAllocationException, InsufficientAddressCapacityException, 
-    ConcurrentOperationException, ResourceUnavailableException;
-
-    boolean disassociateIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;
+    boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;
 
     Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException,
     ResourceAllocationException;
@@ -149,4 +136,18 @@ public interface NetworkService {
     List<? extends Network> listNetworksByVpc(long vpcId);
     
     boolean isVmPartOfNetwork(long vmId, long ntwkId);
+
+    /**
+     * @param entityId
+     * @param networkId
+     * @param vpcId
+     * @return
+     * @throws ConcurrentOperationException 
+     * @throws ResourceUnavailableException 
+     * @throws ResourceAllocationException 
+     * @throws InsufficientAddressCapacityException 
+     */
+    IpAddress associateIP(long ipId, Long networkId, Long vpcId) throws InsufficientAddressCapacityException,
+        ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException;
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/network/rules/RulesService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/rules/RulesService.java b/api/src/com/cloud/network/rules/RulesService.java
index e1ae3c7..9dd602b 100644
--- a/api/src/com/cloud/network/rules/RulesService.java
+++ b/api/src/com/cloud/network/rules/RulesService.java
@@ -64,7 +64,7 @@ public interface RulesService {
 
     boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
 
-    boolean enableStaticNat(long ipAddressId, long vmId, boolean isSystemVm) throws NetworkRuleConflictException, ResourceUnavailableException;
+    boolean enableStaticNat(long ipAddressId, long vmId, long networkId, boolean isSystemVm) throws NetworkRuleConflictException, ResourceUnavailableException;
 
     PortForwardingRule getPortForwardigRule(long ruleId);
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java
index f4ddf6f..3a5b47b 100644
--- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java
+++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java
@@ -27,7 +27,7 @@ import com.cloud.network.VpnUser;
 
 public interface RemoteAccessVpnService {
 
-    RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall) throws NetworkRuleConflictException;
+    RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, long networkId) throws NetworkRuleConflictException;
     void destroyRemoteAccessVpn(long vpnServerAddressId) throws ResourceUnavailableException;
     RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException;
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 815d3ae..4bc9a1c 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -2477,7 +2477,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
                                     " as ip " + ip + " belonging to the range has firewall rules applied. Cleanup the rules first");
                         }
                         //release public ip address here
-                        success = success && _networkMgr.releasePublicIpAddress(ip.getId(), userId, caller);
+                        success = success && _networkMgr.disassociatePublicIpAddress(ip.getId(), userId, caller);
                     }
                     if (!success) {
                         s_logger.warn("Some ip addresses failed to be released as a part of vlan " + vlanDbId + " removal");

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
index 3ad8c33..1acba8b 100644
--- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
+++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java
@@ -512,7 +512,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
                                         // release the public & private IP back to dc pool, as the load balancer
 // appliance is now destroyed
                                         _dcDao.releasePrivateIpAddress(lbIP, guestConfig.getDataCenterId(), null);
-                                        _networkMgr.releasePublicIpAddress(publicIp.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
+                                        _networkMgr.disassociatePublicIpAddress(publicIp.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
                                     }
                                 } catch (Exception e) {
                                     s_logger.warn("Failed to destroy load balancer appliance created for the network" + guestConfig.getId() + " due to " + e.getMessage());
@@ -664,7 +664,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
                     // release the public IP allocated for this LB appliance
                     DetailVO publicIpDetail = _hostDetailDao.findDetail(lbHost.getId(), "publicip");
                     IPAddressVO ipVo = _ipAddressDao.findByIpAndDcId(guestConfig.getDataCenterId(), publicIpDetail.toString());
-                    _networkMgr.releasePublicIpAddress(ipVo.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
+                    _networkMgr.disassociatePublicIpAddress(ipVo.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
                 } else {
                     deviceMapLock.unlock();
                 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/NetworkManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java
index cdfa9aa..ac3503f 100755
--- a/server/src/com/cloud/network/NetworkManager.java
+++ b/server/src/com/cloud/network/NetworkManager.java
@@ -49,7 +49,6 @@ import com.cloud.user.Account;
 import com.cloud.utils.Pair;
 import com.cloud.vm.Nic;
 import com.cloud.vm.NicProfile;
-import com.cloud.vm.NicVO;
 import com.cloud.vm.ReservationContext;
 import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
@@ -77,7 +76,8 @@ public interface NetworkManager extends NetworkService {
      * @throws InsufficientAddressCapacityException
      */
 
-    PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException;
+    PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, 
+            boolean isSystem) throws InsufficientAddressCapacityException;
 
 
     /**
@@ -89,7 +89,7 @@ public interface NetworkManager extends NetworkService {
      * @param ipAddress
      * @return true if it did; false if it didn't
      */
-    public boolean releasePublicIpAddress(long id, long userId, Account caller);
+    public boolean disassociatePublicIpAddress(long id, long userId, Account caller);
 
     /**
      * Lists IP addresses that belong to VirtualNetwork VLANs
@@ -369,7 +369,8 @@ public interface NetworkManager extends NetworkService {
      * @throws InsufficientCapacityException
      * @throws ResourceUnavailableException
      */
-    NicProfile prepareNic(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, DeployDestination dest, ReservationContext context, long nicId, NetworkVO network) throws InsufficientVirtualNetworkCapcityException,
+    NicProfile prepareNic(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, DeployDestination dest, 
+            ReservationContext context, long nicId, NetworkVO network) throws InsufficientVirtualNetworkCapcityException,
             InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException;
 
 
@@ -380,7 +381,8 @@ public interface NetworkManager extends NetworkService {
      * @throws ConcurrentOperationException
      * @throws ResourceUnavailableException
      */
-    NicProfile releaseNic(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, NetworkVO network) throws ConcurrentOperationException, ResourceUnavailableException;
+    NicProfile releaseNic(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, NetworkVO network) 
+            throws ConcurrentOperationException, ResourceUnavailableException;
 
 
     /**
@@ -398,4 +400,18 @@ public interface NetworkManager extends NetworkService {
      */
     List<IPAddressVO> listPublicIpsAssignedToAccount(long accountId, long dcId, Boolean sourceNat);
 
+
+    /**
+     * @param ipAddrId
+     * @param networkId
+     */
+    IpAddress associateIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, 
+        InsufficientAddressCapacityException, ConcurrentOperationException;
+
+
+    /**
+     * @param ipId
+     */
+    void unassignIPFromVpcNetwork(long ipId);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index cc248fd..5c3ec9f 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -55,12 +55,10 @@ import com.cloud.api.commands.CreateNetworkCmd;
 import com.cloud.api.commands.ListNetworksCmd;
 import com.cloud.api.commands.ListTrafficTypeImplementorsCmd;
 import com.cloud.api.commands.RestartNetworkCmd;
-import com.cloud.capacity.dao.CapacityDao;
 import com.cloud.configuration.Config;
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.Resource.ResourceType;
 import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.configuration.dao.ResourceLimitDao;
 import com.cloud.dc.AccountVlanMapVO;
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenter.NetworkType;
@@ -233,10 +231,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
     @Inject
     UserVmDao _userVmDao = null;
     @Inject
-    ResourceLimitDao _limitDao = null;
-    @Inject
-    CapacityDao _capacityDao = null;
-    @Inject
     AlertManager _alertMgr;
     @Inject
     AccountManager _accountMgr;
@@ -405,10 +399,17 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
         if (addrs.size() == 0) {
             if (podId != null) {
-                throw new InsufficientAddressCapacityException("Insufficient address capacity", Pod.class, podId);
+                InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
+                        ("Insufficient address capacity", Pod.class, podId);
+            	// for now, we hardcode the table names, but we should ideally do a lookup for the tablename from the VO object.
+            	ex.addProxyObject("Pod", podId, "podId");            	
+            	throw ex;
             }
             s_logger.warn(errorMessage.toString());
-            throw new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId);
+            InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
+                    ("Insufficient address capacity", DataCenter.class, dcId);
+            ex.addProxyObject("data_center", dcId, "dcId");
+        	throw ex;
         }
 
         assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
@@ -428,9 +429,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating);
 
         if (vlanUse != VlanType.DirectAttached || zone.getNetworkType() == NetworkType.Basic) {
-            Network guestNtwk = getNetwork(guestNetworkId);
             addr.setAssociatedWithNetworkId(guestNetworkId);
-            addr.setVpcId(guestNtwk.getVpcId());
             addr.setVpcId(vpcId);
         }
 
@@ -450,7 +449,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
     @DB
     protected void markPublicIpAsAllocated(IPAddressVO addr) {
 
-        assert (addr.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) : 
+        assert (addr.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) :
             "Unable to transition from state " + addr.getState() + " to " + IpAddress.State.Allocated;
 
         Transaction txn = Transaction.currentTxn();
@@ -467,7 +466,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
             String guestType = vlan.getVlanType().toString();
             
-            UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(), addr.isSourceNat(), guestType, addr.getSystem());
+            UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), 
+                    addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(), addr.isSourceNat(), guestType, 
+                    addr.getSystem());
             _usageEventDao.persist(usageEvent);
             // don't increment resource count for direct ip addresses
             if (addr.getAssociatedWithNetworkId() != null) {
@@ -625,7 +626,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         List<PublicIp> publicIps = new ArrayList<PublicIp>();
         if (userIps != null && !userIps.isEmpty()) {
             for (IPAddressVO userIp : userIps) {
-                PublicIp publicIp = new PublicIp(userIp, _vlanDao.findById(userIp.getVlanId()), NetUtils.createSequenceBasedMacAddress(userIp.getMacAddress()));
+                PublicIp publicIp = new PublicIp(userIp, _vlanDao.findById(userIp.getVlanId()), 
+                        NetUtils.createSequenceBasedMacAddress(userIp.getMacAddress()));
                 publicIps.add(publicIp);
             }
         }
@@ -634,17 +636,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
         if (success) {
             for (IPAddressVO addr : userIps) {
-
                 if (addr.getState() == IpAddress.State.Allocating) {
-
-                    addr.setAssociatedWithNetworkId(network.getId());
                     markPublicIpAsAllocated(addr);
-
                 } else if (addr.getState() == IpAddress.State.Releasing) {
                     // Cleanup all the resources for ip address if there are any, and only then un-assign ip in the
                     // system
                     if (cleanupIpResources(addr.getId(), Account.ACCOUNT_ID_SYSTEM, _accountMgr.getSystemAccount())) {
-                        _ipAddressDao.unassignIpAddress(addr.getId());
+                        s_logger.debug("Unassiging ip address " + addr);
+                        _ipAddressDao.unassignIpAddress(addr.getId());  
                     } else {
                         success = false;
                         s_logger.warn("Failed to release resources for ip address id=" + addr.getId());
@@ -904,7 +903,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         return providerToIpList;
     }
 
-    protected boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean continueOnError, List<PublicIp> publicIps) throws ResourceUnavailableException {
+    protected boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean continueOnError, 
+            List<PublicIp> publicIps) throws ResourceUnavailableException {
         boolean success = true;
 
         Map<PublicIp, Set<Service>> ipToServices = getIpToServices(publicIps, rulesRevoked, false);
@@ -1001,55 +1001,32 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true)
-    public IpAddress allocateIP(long networkId, Account ipOwner)  throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
-        return allocateIP(networkId, ipOwner, false);
-    }
 
-    @DB
-    public IpAddress allocateIP(long networkId, Account ipOwner, boolean isSystem) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
+    public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) 
+            throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
         Account caller = UserContext.current().getCaller();
-        long userId = UserContext.current().getCallerUserId();
-
-        long ownerId = ipOwner.getId();
-        Network network = _networksDao.findById(networkId);
-        if (network == null) {
-            InvalidParameterValueException ex = new InvalidParameterValueException("Network id is invalid");
-            ex.addProxyObject(network, networkId, "networkId");            
-            throw ex;
-        }
-
+        long callerUserId = UserContext.current().getCallerUserId();
         // check permissions
         _accountMgr.checkAccess(caller, null, false, ipOwner);
-        _accountMgr.checkAccess(ipOwner, AccessType.UseNetwork, false, network);
-
-        DataCenter zone = _configMgr.getZone(network.getDataCenterId());
-
-        // allow associating IP addresses to guest network only
-        if (network.getTrafficType() != TrafficType.Guest) {
-            throw new InvalidParameterValueException("Ip address can be associated to the network with trafficType " + TrafficType.Guest);
-        }
-
-        // In Advance zone only allow to do IP assoc for Isolated networks with source nat service enabled
-        if (zone.getNetworkType() == NetworkType.Advanced && 
-                !(network.getGuestType() == GuestType.Isolated && areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) {
-            throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + 
-                    " ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the "
-                    + Service.SourceNat.getName() + " enabled");
-        }
-
-        // Check that network belongs to IP owner - skip this check for Basic zone as there is just one guest network,
-        // and it belongs to the system
-        if (zone.getNetworkType() != NetworkType.Basic && network.getAccountId() != ipOwner.getId()) {
-            throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
-        }
+        
+        DataCenter zone = _configMgr.getZone(zoneId);
+        
+        return allocateIp(ipOwner, isSystem, caller, callerUserId, zone);
+    }
 
+    @DB
+    public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerUserId, DataCenter zone) 
+            throws ConcurrentOperationException, ResourceAllocationException,
+            InsufficientAddressCapacityException {
+        
         VlanType vlanType = VlanType.VirtualNetwork;
         boolean assign = false;
 
         if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
             // zone is of type DataCenter. See DataCenterVO.java.
-            PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, zone with specified id is currently disabled");
-            ex.addProxyObject(zone, zone.getId(), "zoneId");
+            PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, " +
+            		"Zone is currently disabled");
+            ex.addProxyObject("data_center", zone.getId(), "zoneId");
             throw ex;
         }
 
@@ -1059,11 +1036,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         Account accountToLock = null;
         try {
             if (s_logger.isDebugEnabled()) {
-                s_logger.debug("Associate IP address called for user " + userId + " account " + ownerId);
+                s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
             }
-            accountToLock = _accountDao.acquireInLockTable(ownerId);
+            accountToLock = _accountDao.acquireInLockTable(ipOwner.getId());
             if (accountToLock == null) {
-                s_logger.warn("Unable to lock account: " + ownerId);
+                s_logger.warn("Unable to lock account: " + ipOwner.getId());
                 throw new ConcurrentOperationException("Unable to acquire account lock");
             }
 
@@ -1075,40 +1052,30 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
             // accountId will not be exceeded
             _resourceLimitMgr.checkResourceLimit(accountToLock, ResourceType.public_ip);
 
-            boolean isSourceNat = false;
-
             txn.start();
 
-            NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
-            boolean sharedSourceNat = offering.getSharedSourceNat();
-
-            if (!sharedSourceNat) {
-                if (getExistingSourceNat(ownerId, network.getId(), network.getVpcId()) == null) {
-                    if (network.getGuestType() == GuestType.Isolated) {
-                        isSourceNat = true;
-                    }
-                }
-            }
-
-            ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, network.getId(), 
-                    isSourceNat, assign, null, isSystem, network.getVpcId());
+            ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, 
+                    false, assign, null, isSystem, null);
 
             if (ip == null) {
-            	InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone.getId());
+
+            	InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
+            	        ("Unable to find available public IP addresses", DataCenter.class, zone.getId());
+            	ex.addProxyObject("data_center", zone.getId(), "zoneId");
+            	throw ex;
             }
             UserContext.current().setEventDetails("Ip Id: " + ip.getId());
             Ip ipAddress = ip.getAddress();
 
-            s_logger.debug("Got " + ipAddress + " to assign for account " + ipOwner.getId() + " in zone " + network.getDataCenterId());
+            s_logger.debug("Got " + ipAddress + " to assign for account " + ipOwner.getId() + " in zone " + zone.getId());
 
             txn.commit();
         } finally {
             if (accountToLock != null) {
-                _accountDao.releaseFromLockTable(ownerId);
+                _accountDao.releaseFromLockTable(ipOwner.getId());
                 s_logger.debug("Associate IP address lock released");
             }
         }
-
         return ip;
     }
 
@@ -1140,14 +1107,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         return sourceNatIp;
     }
 
-    @Override
-    @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true)
-    public IpAddress associateIP(long ipId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException {
-        return associateIP(ipId, false);
-    }
-
     @DB
-    private IpAddress associateIP(long ipId, boolean isSystem) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException {
+    @Override
+    public IpAddress associateIPToGuestNetwork(long ipId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, 
+        InsufficientAddressCapacityException, ConcurrentOperationException {
         Account caller = UserContext.current().getCaller();
         Account owner = null;
 
@@ -1159,17 +1122,69 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
             s_logger.debug("Unable to find ip address by id: " + ipId);
             return null;
         }
+        
+        if (ipToAssoc.getAssociatedWithNetworkId() != null) {
+            s_logger.debug("IP " + ipToAssoc + " is already assocaited with network id" + networkId);
+            return ipToAssoc;
+        }
+        
+        Network network = _networksDao.findById(networkId);
+        if (network != null) {
+            _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network);
+        } else {
+            s_logger.debug("Unable to find ip address by id: " + ipId);
+            return null;
+        }
+        
+        DataCenter zone = _configMgr.getZone(network.getDataCenterId());
 
-        Network network = _networksDao.findById(ipToAssoc.getAssociatedWithNetworkId());
+        // allow associating IP addresses to guest network only
+        if (network.getTrafficType() != TrafficType.Guest) {
+            throw new InvalidParameterValueException("Ip address can be associated to the network with trafficType " + 
+                                                    TrafficType.Guest);
+        }
 
+        // Check that network belongs to IP owner - skip this check for Basic zone as there is just one guest network,
+        // and it belongs to the system
+        if (zone.getNetworkType() != NetworkType.Basic && network.getAccountId() != owner.getId()) {
+            throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
+        }
+        
+        // In Advance zone only allow to do IP assoc for Isolated networks with source nat service enabled
+        if (zone.getNetworkType() == NetworkType.Advanced && 
+                !(network.getGuestType() == GuestType.Isolated && areServicesSupportedInNetwork(network.getId(), 
+                        Service.SourceNat))) {
+            throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + 
+                    " ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the "
+                    + Service.SourceNat.getName() + " enabled");
+        }
+        
+        NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
+        boolean sharedSourceNat = offering.getSharedSourceNat();
+        boolean isSourceNat = false;
+        if (!sharedSourceNat) {
+            if (getExistingSourceNat(owner.getId(), networkId, null) == null) {
+                if (network.getGuestType() == GuestType.Isolated) {
+                    isSourceNat = true;
+                }
+            }
+        }
+        
+        s_logger.debug("Associating ip " + ipToAssoc + " to network " + network);
+        
         IPAddressVO ip = _ipAddressDao.findById(ipId);
+        //update ip address with networkId
+        ip.setAssociatedWithNetworkId(networkId);
+        ip.setSourceNat(isSourceNat);
+        _ipAddressDao.update(ipId, ip);
+        
         boolean success = false;
         try {
             success = applyIpAssociations(network, false);
             if (success) {
-                s_logger.debug("Successfully associated ip address " + ip.getAddress().addr() + " for account " + owner.getId() + " in zone " + network.getDataCenterId());
+                s_logger.debug("Successfully associated ip address " + ip.getAddress().addr() + " to network " + network);
             } else {
-                s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " for account " + owner.getId() + " in zone " + network.getDataCenterId());
+                s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " to network " + network);
             }
             return ip;
         } catch (ResourceUnavailableException e) {
@@ -1193,10 +1208,56 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
             }
         }
     }
+    
+    
+    @DB
+    protected IpAddress associateIPToVpc(long ipId, long vpcId) throws ResourceAllocationException, ResourceUnavailableException, 
+    InsufficientAddressCapacityException, ConcurrentOperationException {
+        Account caller = UserContext.current().getCaller();
+        Account owner = null;
+
+        IpAddress ipToAssoc = getIp(ipId);
+        if (ipToAssoc != null) {
+            _accountMgr.checkAccess(caller, null, true, ipToAssoc);
+            owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId());
+        } else {
+            s_logger.debug("Unable to find ip address by id: " + ipId);
+            return null;
+        }
+        
+        Vpc vpc = _vpcMgr.getVpc(vpcId);
+        if (vpc == null) {
+            throw new InvalidParameterValueException("Invalid VPC id " + vpcId);
+        }
+        
+        // check permissions
+        _accountMgr.checkAccess(caller, null, true, owner, vpc);
+                
+        boolean isSourceNat = false;
+        if (getExistingSourceNat(owner.getId(), null, vpcId) == null) {
+            isSourceNat = true;
+        }
+        
+        s_logger.debug("Associating ip " + ipToAssoc + " to vpc " + vpc);
+        
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        IPAddressVO ip = _ipAddressDao.findById(ipId);
+        //update ip address with networkId
+        ip.setVpcId(vpcId);
+        ip.setSourceNat(isSourceNat);
+        _ipAddressDao.update(ipId, ip);
+        txn.commit();
+                
+        s_logger.debug("Successfully assigned ip " + ipToAssoc + " to vpc " + vpc);
+
+        return _ipAddressDao.findById(ipId);
+    }
+    
 
     @Override
     @DB
-    public boolean releasePublicIpAddress(long addrId, long userId, Account caller) {
+    public boolean disassociatePublicIpAddress(long addrId, long userId, Account caller) {
 
         boolean success = true;
         // Cleanup all ip address resources - PF/LB/Static nat rules
@@ -2210,7 +2271,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
     @Override
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_NET_IP_RELEASE, eventDescription = "disassociating Ip", async = true)
-    public boolean disassociateIpAddress(long ipAddressId) throws InsufficientAddressCapacityException {
+    public boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException {
         Long userId = UserContext.current().getCallerUserId();
         Account caller = UserContext.current().getCaller();
 
@@ -2229,16 +2290,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         if (ipVO.getAllocatedToAccountId() != null) {
             _accountMgr.checkAccess(caller, null, true, ipVO);
         }
-        
-        //if ip address is a source nat ip in vpc, fail to disassociate
-        if (ipVO.getVpcId() != null && ipVO.isSourceNat()) {
-            throw new InvalidParameterValueException("IP address id=" + ipAddressId + " is a source nat for VPC id=" +
-                    ipVO.getVpcId() + " and can't be released");
-        }
 
-        Network associatedNetwork = getNetwork(ipVO.getAssociatedWithNetworkId());
-
-        if (ipVO.isSourceNat() && areServicesSupportedInNetwork(associatedNetwork.getId(), Service.SourceNat)) {
+        if (ipVO.isSourceNat()) {
             throw new IllegalArgumentException("ip address is used for source nat purposes and can not be disassociated.");
         }
 
@@ -2250,9 +2303,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         // Check for account wide pool. It will have an entry for account_vlan_map.
         if (_accountVlanMapDao.findAccountVlanMap(ipVO.getAllocatedToAccountId(), ipVO.getVlanId()) != null) {        	
         	//see IPaddressVO.java
-        	InvalidParameterValueException ex = new InvalidParameterValueException("Sepcified IP address uuid belongs to Account wide IP pool and cannot be disassociated");
-        	ex.addProxyObject(ipVO, ipVO.getId(), "systemIpAddrId");        	
-            throw ex;        	
+        	InvalidParameterValueException ex = new InvalidParameterValueException("Sepcified IP address uuid belongs to" +
+        			" Account wide IP pool and cannot be disassociated");
+        	ex.addProxyObject("user_ip_address", ipAddressId, "ipAddressId");
+        	throw ex;
         }
 
         // don't allow releasing system ip address
@@ -2262,9 +2316,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
             throw ex;
         }
 
-        boolean success = releasePublicIpAddress(ipAddressId, userId, caller);
-        if (success) {
-            Network guestNetwork = getNetwork(ipVO.getAssociatedWithNetworkId());
+        boolean success = disassociatePublicIpAddress(ipAddressId, userId, caller);
+        
+        Long networkId = ipVO.getAssociatedWithNetworkId();
+        if (success && networkId != null) {
+            Network guestNetwork = getNetwork(networkId);
             NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
             Long vmId = ipVO.getAssociatedWithVmId();
             if (offering.getElasticIp() && vmId != null) {
@@ -4299,7 +4355,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
                 String guestType = vlan.getVlanType().toString();
 
-                UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_RELEASE, ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(), ip.isSourceNat(), guestType, ip.getSystem());
+                UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_RELEASE,
+                        ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(), 
+                        ip.isSourceNat(), guestType, ip.getSystem());
                 _usageEventDao.persist(usageEvent);
             }
 
@@ -4725,8 +4783,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         }
 
         // static NAT rules can not programmed unless IP is associated with network service provider, so run IP
-// association for
-        // the network so as to ensure IP is associated before applying rules (in add state)
+        // association for the network so as to ensure IP is associated before applying rules (in add state)
         applyIpAssociations(network, false, continueOnError, publicIps);
 
         // get provider
@@ -5770,8 +5827,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         // release all ip addresses
         List<IPAddressVO> ipsToRelease = _ipAddressDao.listByAssociatedNetwork(networkId, null);
         for (IPAddressVO ipToRelease : ipsToRelease) {
-            IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId());
-            assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable.";
+            if (ipToRelease.getVpcId() != null) {
+                IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId());
+                assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable.";
+            }
         }
 
         try {
@@ -6442,7 +6501,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
     protected PhysicalNetworkServiceProvider addDefaultSecurityGroupProviderToPhysicalNetwork(long physicalNetworkId) {
 
-        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.SecurityGroupProvider.getName(), null, null);
+        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, 
+                Network.Provider.SecurityGroupProvider.getName(), null, null);
 
         return nsp;
     }
@@ -6716,7 +6776,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         }
     }
 
-    public IpAddress assignSystemIp(long networkId, Account owner, boolean forElasticLb, boolean forElasticIp) throws InsufficientAddressCapacityException {
+    public IpAddress assignSystemIp(long networkId, Account owner, boolean forElasticLb, boolean forElasticIp) 
+            throws InsufficientAddressCapacityException {
         Network guestNetwork = getNetwork(networkId);
         NetworkOffering off = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
         IpAddress ip = null;
@@ -6725,9 +6786,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
             try {
                 s_logger.debug("Allocating system IP address for load balancer rule...");
                 // allocate ip
-                ip = allocateIP(networkId, owner, true);
+                ip = allocateIP(owner, true, guestNetwork.getDataCenterId());
                 // apply ip associations
-                ip = associateIP(ip.getId());
+                ip = associateIP(ip.getId(), networkId, null);
             } catch (ResourceAllocationException ex) {
                 throw new CloudRuntimeException("Failed to allocate system ip due to ", ex);
             } catch (ConcurrentOperationException ex) {
@@ -6751,7 +6812,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         if (networkId != null) {
             if (ip.getSystem()) {
                 UserContext ctx = UserContext.current();
-                if (!releasePublicIpAddress(ip.getId(), ctx.getCallerUserId(), ctx.getCaller())) {
+                if (!disassociatePublicIpAddress(ip.getId(), ctx.getCallerUserId(), ctx.getCaller())) {
                     s_logger.warn("Unable to release system ip address id=" + ip.getId());
                     success = false;
                 } else {
@@ -6899,5 +6960,35 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
         }
         return false;
     }
+    
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true)
+    public IpAddress associateIP(long ipId, Long networkId, Long vpcId) throws InsufficientAddressCapacityException,
+        ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException {
+        if (vpcId != null) {
+            return associateIPToVpc(ipId, vpcId);
+        }
+        
+        if (networkId != null) {
+            return associateIPToGuestNetwork(ipId, networkId);
+        }
+        
+        return null;
+    }
 
+    
+    @Override
+    public void unassignIPFromVpcNetwork(long ipId) {
+        IPAddressVO ip = _ipAddressDao.findById(ipId);
+        Long vpcId = ip.getVpcId();
+        
+        if (vpcId == null) {
+            return;
+        }
+        
+        ip.setAssociatedWithNetworkId(null);
+        _ipAddressDao.update(ipId, ip);
+        s_logger.debug("IP address " + ip + " is no longer associated with the network inside vpc id=" + vpcId);
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
index aef6d7c..506b615 100644
--- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
+++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
@@ -33,6 +33,7 @@ import com.cloud.event.EventTypes;
 import com.cloud.event.UsageEventVO;
 import com.cloud.event.dao.EventDao;
 import com.cloud.event.dao.UsageEventDao;
+import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.NetworkRuleConflictException;
 import com.cloud.exception.ResourceUnavailableException;
@@ -131,21 +132,38 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
     public FirewallRule createFirewallRule(FirewallRule rule) throws NetworkRuleConflictException {
         Account caller = UserContext.current().getCaller();
 
-        return createFirewallRule(rule.getSourceIpAddressId(), caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(), rule.getIcmpCode(),
-                rule.getIcmpType(), null, rule.getType());
+        return createFirewallRule(rule.getSourceIpAddressId(), caller, rule.getXid(), rule.getSourcePortStart(), 
+                rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(), rule.getIcmpCode(),
+                rule.getIcmpType(), null, rule.getType(), rule.getNetworkId());
     }
 
     @DB
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", create = true)
-    public FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart, Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType,
-            Long relatedRuleId, FirewallRule.FirewallRuleType type) throws NetworkRuleConflictException {
+    public FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart, 
+            Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType,
+            Long relatedRuleId, FirewallRule.FirewallRuleType type, long networkId) throws NetworkRuleConflictException {
+        
         IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId);
-
         // Validate ip address
         if (ipAddress == null && type == FirewallRule.FirewallRuleType.User) {
-            throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " doesn't exist in the system");
+            throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + 
+                    " doesn't exist in the system");
+        }
+        
+        //associate ip address to network (if needed)
+        if (ipAddress.getAssociatedWithNetworkId() == null) {
+            s_logger.debug("The ip is not associated with the network id="+ networkId + " so assigning");
+            try {
+                _networkMgr.associateIPToGuestNetwork(ipAddrId, networkId);
+            } catch (Exception ex) {
+                s_logger.warn("Failed to associate ip id=" + ipAddrId + " to network id=" + networkId + " as " +
+                        "a part of firewall rule creation");
+                return null;
+            }
         }
+        
+        _networkMgr.checkIpForService(ipAddress, Service.Firewall);  
 
         validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type);
 
@@ -158,17 +176,14 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
             throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP");
         }
 
-        Long networkId = null;
         Long accountId = null;
         Long domainId = null;
 
         if (ipAddress != null) {
-            networkId = ipAddress.getAssociatedWithNetworkId();
             accountId = ipAddress.getAllocatedToAccountId();
             domainId = ipAddress.getAllocatedInDomainId();
         }
 
-        _networkMgr.checkIpForService(ipAddress, Service.Firewall);
 
         Transaction txn = Transaction.currentTxn();
         txn.start();
@@ -369,7 +384,8 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
     }
 
     @Override
-    public boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB) throws ResourceUnavailableException {
+    public boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB) 
+            throws ResourceUnavailableException {
         boolean success = true;
         if (!_networkMgr.applyRules(rules, continueOnError)) {
             s_logger.warn("Rules are not completely applied");
@@ -380,10 +396,11 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
                     if (rule.getState() == FirewallRule.State.Revoke) {
                         FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(rule.getId());
                         if (relatedRule != null) {
-                            s_logger.warn("Can't remove the firewall rule id=" + rule.getId() + " as it has related firewall rule id=" + relatedRule.getId() + "; leaving it in Revoke state");
+                            s_logger.warn("Can't remove the firewall rule id=" + rule.getId() + 
+                                    " as it has related firewall rule id=" + relatedRule.getId() + "; leaving it in Revoke state");
                             success = false;
                         } else {
-                            _firewallDao.remove(rule.getId());
+                            removeRule(rule);
                         }
                     } else if (rule.getState() == FirewallRule.State.Add) {
                         FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId());
@@ -397,6 +414,23 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
         return success;
     }
 
+    @DB
+    protected void removeRule(FirewallRule rule) {
+        //Lock ip address
+        IpAddress ip = _ipAddressDao.findById(rule.getSourceIpAddressId());
+       
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        //remove the rule
+        _firewallDao.remove(rule.getId());
+        if (ip.getVpcId() != null && _firewallDao.listByIp(ip.getId()).isEmpty()) {
+          //if the rule is the last one for the ip address assigned to VPC, unassign it from the network
+            _networkMgr.unassignIPFromVpcNetwork(ip.getId());
+        }
+        
+        txn.commit();
+    }
+
     @Override
     public boolean applyFirewallRules(long ipId, Account caller) throws ResourceUnavailableException {
         List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(ipId, Purpose.Firewall);
@@ -535,18 +569,21 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
     }
 
     @Override
-    public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, Long relatedRuleId)
+    public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller,
+            Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, Long relatedRuleId, long networkId)
             throws NetworkRuleConflictException {
 
         // If firwallRule for this port range already exists, return it
-        List<FirewallRuleVO> rules = _firewallDao.listByIpPurposeAndProtocolAndNotRevoked(ipAddrId, startPort, endPort, protocol, Purpose.Firewall);
+        List<FirewallRuleVO> rules = _firewallDao.listByIpPurposeAndProtocolAndNotRevoked(ipAddrId, startPort, endPort,
+                protocol, Purpose.Firewall);
         if (!rules.isEmpty()) {
             return rules.get(0);
         }
 
         List<String> oneCidr = new ArrayList<String>();
         oneCidr.add(NetUtils.ALL_CIDRS);
-        return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, icmpCode, icmpType, relatedRuleId, FirewallRule.FirewallRuleType.User);
+        return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, icmpCode, icmpType,
+                relatedRuleId, FirewallRule.FirewallRuleType.User, networkId);
     }
 
     @Override
@@ -654,7 +691,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
         for (FirewallRuleVO rule : systemRules) {
             try {
                 this.createFirewallRule(ip.getId(), acct, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(),
-                        rule.getSourceCidrList(), rule.getIcmpCode(), rule.getIcmpType(), rule.getRelated(), FirewallRuleType.System);
+                        rule.getSourceCidrList(), rule.getIcmpCode(), rule.getIcmpType(), rule.getRelated(), FirewallRuleType.System, rule.getNetworkId());
             } catch (Exception e) {
                 s_logger.debug("Failed to add system wide firewall rule, due to:" + e.toString());
             }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
index 8c15d80..d479f76 100644
--- a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
+++ b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
@@ -611,7 +611,7 @@ public class ElasticLoadBalancerManagerImpl implements
         IPAddressVO ipvo = _ipAddressDao.findById(ipId);
         ipvo.setAssociatedWithNetworkId(null); 
         _ipAddressDao.update(ipvo.getId(), ipvo);
-       _networkMgr.releasePublicIpAddress(ipId, userId, caller);
+       _networkMgr.disassociatePublicIpAddress(ipId, userId, caller);
        _ipAddressDao.unassignIpAddress(ipId);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
index 2b5f40a..805657b 100755
--- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
+++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
@@ -714,7 +714,8 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
 
             // Validate ip address
             if (ipAddressVo == null) {
-                throw new InvalidParameterValueException("Unable to create load balance rule; ip id=" + ipAddrId + " doesn't exist in the system");
+                throw new InvalidParameterValueException("Unable to create load balance rule; ip id=" + ipAddrId + "" +
+                		" doesn't exist in the system");
             } else if (ipAddressVo.isOneToOneNat()) {
                 throw new NetworkRuleConflictException("Can't do load balance on ip address: " + ipAddressVo.getAddress());
             }
@@ -731,7 +732,14 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
                 ip = _networkMgr.assignSystemIp(lb.getNetworkId(), lbOwner, true, false);
                 lb.setSourceIpAddressId(ip.getId());
             }
+            
+            
+            
             try {
+                if (ip.getAssociatedWithNetworkId() == null) {
+                    s_logger.debug("The ip is not associated with the network id="+ lb.getNetworkId() + " so assigning");
+                    _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId());
+                }
                 result = createLoadBalancer(lb, openFirewall);
             } catch (Exception ex) {
                 s_logger.warn("Failed to create load balancer due to ", ex);
@@ -774,7 +782,8 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
             throw ex;
         }
 
-        _firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), Purpose.LoadBalancing, FirewallRuleType.User);
+        _firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), 
+                Purpose.LoadBalancing, FirewallRuleType.User);
 
         networkId = ipAddr.getAssociatedWithNetworkId();
         if (networkId == null) {
@@ -803,7 +812,8 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
         newRule = _lbDao.persist(newRule);
 
         if (openFirewall) {
-            _firewallMgr.createRuleForAllCidrs(sourceIpId, caller.getCaller(), lb.getSourcePortStart(), lb.getSourcePortEnd(), lb.getProtocol(), null, null, newRule.getId());
+            _firewallMgr.createRuleForAllCidrs(sourceIpId, caller.getCaller(), lb.getSourcePortStart(), 
+                    lb.getSourcePortEnd(), lb.getProtocol(), null, null, newRule.getId(), networkId);
         }
 
         boolean success = true;
@@ -950,7 +960,7 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
         boolean success = true;
         if (ip.getSystem()) {
             s_logger.debug("Releasing system ip address " + lb.getSourceIpAddressId() + " as a part of delete lb rule");
-            if (!_networkMgr.releasePublicIpAddress(lb.getSourceIpAddressId(), UserContext.current().getCallerUserId(), UserContext.current().getCaller())) {
+            if (!_networkMgr.disassociatePublicIpAddress(lb.getSourceIpAddressId(), UserContext.current().getCallerUserId(), UserContext.current().getCaller())) {
                 s_logger.warn("Unable to release system ip address id=" + lb.getSourceIpAddressId() + " as a part of delete lb rule");
                 success = false;
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/929997f5/server/src/com/cloud/network/rules/FirewallManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/rules/FirewallManager.java b/server/src/com/cloud/network/rules/FirewallManager.java
index 2de4d06..58e8750 100644
--- a/server/src/com/cloud/network/rules/FirewallManager.java
+++ b/server/src/com/cloud/network/rules/FirewallManager.java
@@ -67,10 +67,10 @@ public interface FirewallManager extends FirewallService {
     boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, long userId);
 
     FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart, Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType, Long relatedRuleId,
-            FirewallRule.FirewallRuleType type)
+            FirewallRule.FirewallRuleType type, long networkId)
             throws NetworkRuleConflictException;
 
-    FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, Long relatedRuleId) throws NetworkRuleConflictException;
+    FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, Long relatedRuleId, long networkId) throws NetworkRuleConflictException;
 
     boolean revokeAllFirewallRulesForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException;