From d520f0af5beaf45be94a78fb15eddead20142827 Mon Sep 17 00:00:00 2001 From: abhishek Date: Mon, 15 Nov 2010 12:37:47 -0800 Subject: [PATCH] adding a column in user_ip_address table called one_to_one_nat; which is a boolean to tell us if the ip is a nat ip. This is false by default, and is set to true when we nat the ip. Also, this value is returned in the list public ip addrsses api call. finally, the value is set to false when we delete the ip forwarding rule. --- core/src/com/cloud/network/IPAddressVO.java | 13 ++- .../src/com/cloud/api/ApiResponseHelper.java | 3 +- .../cloud/api/response/IPAddressResponse.java | 11 +++ .../com/cloud/network/NetworkManagerImpl.java | 97 ++++++++++++------- setup/db/create-schema.sql | 1 + setup/db/schema-21to22.sql | 1 + 6 files changed, 89 insertions(+), 37 deletions(-) diff --git a/core/src/com/cloud/network/IPAddressVO.java b/core/src/com/cloud/network/IPAddressVO.java index 39527f6e5b8..c55764a2a0c 100644 --- a/core/src/com/cloud/network/IPAddressVO.java +++ b/core/src/com/cloud/network/IPAddressVO.java @@ -58,7 +58,10 @@ public class IPAddressVO { @Column(name="vlan_db_id") private long vlanDbId; - + + @Column(name="one_to_one_nat") + private boolean oneToOneNat; + protected IPAddressVO() { } @@ -115,6 +118,14 @@ public class IPAddressVO { public void setVlanDbId(long vlanDbId) { this.vlanDbId = vlanDbId; + } + + public boolean isOneToOneNat() { + return oneToOneNat; + } + + public void setOneToOneNat(boolean oneToOneNat) { + this.oneToOneNat = oneToOneNat; } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index e1ec0773218..dfd6962e7d3 100644 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -736,7 +736,8 @@ public class ApiResponseHelper { } ipResponse.setForVirtualNetwork(forVirtualNetworks); - + ipResponse.setOneToOneNat(ipAddress.isOneToOneNat()); + //show this info to admin only Account account = UserContext.current().getAccount(); if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) { diff --git a/server/src/com/cloud/api/response/IPAddressResponse.java b/server/src/com/cloud/api/response/IPAddressResponse.java index dc780f89559..92fdc714530 100644 --- a/server/src/com/cloud/api/response/IPAddressResponse.java +++ b/server/src/com/cloud/api/response/IPAddressResponse.java @@ -56,6 +56,9 @@ public class IPAddressResponse extends BaseResponse { @SerializedName("vlanname") @Param(description="the VLAN associated with the IP address") private String vlanName; + @SerializedName("onetoonenat") @Param(description="whether this ip is for one-to-one nat") + private Boolean oneToOneNat; + public String getIpAddress() { return ipAddress; } @@ -143,4 +146,12 @@ public class IPAddressResponse extends BaseResponse { public void setVlanName(String vlanName) { this.vlanName = vlanName; } + + public Boolean getOneToOneNat() { + return oneToOneNat; + } + + public void setOneToOneNat(Boolean oneToOneNat) { + this.oneToOneNat = oneToOneNat; + } } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index df00b541e6b..fcc4d0e5b28 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2934,53 +2934,76 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return mac; } - @Override + @Override @DB public NetworkConfiguration getNetworkConfiguration(long id) { return _networkConfigDao.findById(id); } - @Override + @Override @DB public FirewallRuleVO createIpForwardingRuleOnDomr(Long ruleId) throws ServerApiException{ + Transaction txn = Transaction.currentTxn(); + txn.start(); boolean success = false; - //get the rule - FirewallRuleVO rule = _rulesDao.findById(ruleId); + FirewallRuleVO rule = null; + IPAddressVO ipAddress = null; + boolean locked = false; + try { + //get the rule + rule = _rulesDao.findById(ruleId); + + if(rule == null){ + throw new PermissionDeniedException("Cannot create ip forwarding rule in db"); + } + + //get ip address + ipAddress = _ipAddressDao.findById(rule.getPublicIpAddress()); + if (ipAddress == null) { + throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified."); + } + + //sync point + ipAddress = _ipAddressDao.acquireInLockTable(ipAddress.getAddress()); + + if(ipAddress == null){ + s_logger.warn("Unable to acquire lock on ipAddress for creating 1-1 NAT rule"); + return rule; + }else{ + locked = true; + } - if(rule == null){ - throw new PermissionDeniedException("Cannot create ip forwarding rule in db"); - } - - //get ip address - IPAddressVO ipAddress = _ipAddressDao.findById(rule.getPublicIpAddress()); - if (ipAddress == null) { - throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified."); - } - - //get the domain router object - DomainRouterVO router = _routerMgr.getRouter(ipAddress.getAccountId(), ipAddress.getDataCenterId()); - success = createOrDeleteIpForwardingRuleOnDomr(rule,router,rule.getPrivateIpAddress(),true); //true +> create - - if(!success){ - //corner case; delete record from db as domR rule creation failed - try { + //get the domain router object + DomainRouterVO router = _routerMgr.getRouter(ipAddress.getAccountId(), ipAddress.getDataCenterId()); + success = createOrDeleteIpForwardingRuleOnDomr(rule,router,rule.getPrivateIpAddress(),true); //true +> create + + if(!success){ + //corner case; delete record from db as domR rule creation failed _rulesDao.remove(ruleId); throw new PermissionDeniedException("Cannot create ip forwarding rule on domr, hence deleting created record in db"); - } catch (Exception e) { - throw new ServerApiException(BaseCmd.NET_CREATE_IPFW_RULE_ERROR, e.getMessage()); + } + + //update the user_ip_address record + ipAddress.setOneToOneNat(true); + _ipAddressDao.update(ipAddress.getAddress(),ipAddress); + + // Save and create the event + String description; + String ruleName = "ip forwarding"; + String level = EventVO.LEVEL_INFO; + + description = "created new " + ruleName + " rule [" + rule.getPublicIpAddress() + "]->[" + + rule.getPrivateIpAddress() + "]" + ":" + rule.getProtocol(); + + EventUtils.saveEvent(UserContext.current().getUserId(), ipAddress.getAccountId(), level, EventTypes.EVENT_NET_RULE_ADD, description); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + throw new ServerApiException(BaseCmd.NET_CREATE_IPFW_RULE_ERROR, e.getMessage()); + }finally{ + if(locked){ + _ipAddressDao.releaseFromLockTable(ipAddress.getAddress()); } } - - // Save and create the event - String description; - String ruleName = "ip forwarding"; - String level = EventVO.LEVEL_INFO; - - description = "created new " + ruleName + " rule [" + rule.getPublicIpAddress() + "]->[" - + rule.getPrivateIpAddress() + "]" + ":" + rule.getProtocol(); - - EventUtils.saveEvent(UserContext.current().getUserId(), ipAddress.getAccountId(), level, EventTypes.EVENT_NET_RULE_ADD, description); - return rule; - } @Override @DB @@ -3124,6 +3147,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag success = createOrDeleteIpForwardingRuleOnDomr(rule, router, rule.getPrivateIpAddress(), false); _firewallRulesDao.remove(ruleId); + //update the ip_address record + ipAddress.setOneToOneNat(false); + _ipAddressDao.persist(ipAddress); + String description; String type = EventTypes.EVENT_NET_RULE_DELETE; String level = EventVO.LEVEL_INFO; diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index fed523c8d63..4602ff830f4 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -555,6 +555,7 @@ CREATE TABLE `cloud`.`user_ip_address` ( `source_nat` int(1) unsigned NOT NULL default '0', `allocated` datetime NULL COMMENT 'Date this ip was allocated to someone', `vlan_db_id` bigint unsigned NOT NULL, + `one_to_one_nat` int(1) unsigned NOT NULL default '0', PRIMARY KEY (`public_ip_address`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/setup/db/schema-21to22.sql b/setup/db/schema-21to22.sql index 6a7dad582b7..8b2a9b3467d 100644 --- a/setup/db/schema-21to22.sql +++ b/setup/db/schema-21to22.sql @@ -53,6 +53,7 @@ ALTER TABLE `cloud`.`volumes` ADD COLUMN `source_id` bigint unsigned; -- id for ALTER TABLE `cloud`.`volumes` ADD COLUMN `source_type` varchar(32); --source from which the volume is created i.e. snapshot, diskoffering, template, blank ALTER TABLE `cloud`.`volumes` ADD COLUMN 'attached' datetime; --date and time the volume was attached ALTER TABLE `cloud`.`disk_offering` ADD COLUMN `customized` tinyint(1) unsigned NOT NULL DEFAULT 0;-- 0 implies not customized by default +ALTER TABLE `cloud`.`user_ip_address` ADD COLUMN `one_to_one_nat` int(1) unsigned NOT NULL default '0'; -- new column for NAT ip