mass merge 2.2.10

This commit is contained in:
Chiradeep Vittal 2011-08-11 16:41:52 -07:00
commit 51af0db682
38 changed files with 982 additions and 109 deletions

View File

@ -25,7 +25,7 @@ import com.cloud.agent.api.to.LoadBalancerTO;
*/
public class LoadBalancerConfigCommand extends NetworkElementCommand {
LoadBalancerTO[] loadBalancers;
public String lbStatsVisibility;
public String lbStatsVisibility = "guest-network";
public String lbStatsIp; /* load balancer listen on this ip for stats */
public String lbStatsPort = "8081"; /*load balancer listen on this port for stats */
public String lbStatsSrcCidrs = "0/0" ; /* TODO : currently there is no filtering based on the source ip */

View File

@ -25,9 +25,8 @@ public class SetFirewallRulesAnswer extends Answer {
protected SetFirewallRulesAnswer() {
}
public SetFirewallRulesAnswer(SetFirewallRulesCommand cmd, String[] results) {
super(cmd, true, null);
public SetFirewallRulesAnswer(SetFirewallRulesCommand cmd, Boolean success, String[] results) {
super(cmd, success, null);
assert (cmd.getRules().length == results.length) : "rules and their results should be the same length don't you think?";
this.results = results;
}

View File

@ -17,9 +17,13 @@
*/
package com.cloud.agent.api.routing;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.utils.StringUtils;
/**
* SetFirewallRulesCommand is the transport for firewall rules.
@ -40,4 +44,59 @@ public class SetFirewallRulesCommand extends NetworkElementCommand {
public FirewallRuleTO[] getRules() {
return rules;
}
public String[][] generateFwRules() {
String [][] result = new String [2][];
Set<String> toAdd = new HashSet<String>();
for (FirewallRuleTO fwTO: rules) {
/* example : 172.16.92.44:tcp:80:80:0.0.0.0/0:,200.16.92.44:tcp:220:220:0.0.0.0/0:,
* each entry format <ip>:protocol:srcport:destport:scidr:
* reverted entry format <ip>:reverted:0:0:0:
*/
if (fwTO.revoked() == true)
{
StringBuilder sb = new StringBuilder();
/* This entry is added just to make sure atleast there will one entry in the list to get the ipaddress */
sb.append(fwTO.getSrcIp()).append(":reverted:0:0:0:");
String fwRuleEntry = sb.toString();
toAdd.add(fwRuleEntry);
continue;
}
List<String> cidr;
StringBuilder sb = new StringBuilder();
sb.append(fwTO.getSrcIp()).append(":").append(fwTO.getProtocol()).append(":");
if ("icmp".compareTo(fwTO.getProtocol()) == 0)
{
sb.append(fwTO.getIcmpType()).append(":").append(fwTO.getIcmpCode()).append(":");
}else if (fwTO.getStringSrcPortRange() == null)
sb.append("0:0").append(":");
else
sb.append(fwTO.getStringSrcPortRange()).append(":");
cidr = fwTO.getSourceCidrList();
if (cidr == null || cidr.isEmpty())
{
sb.append("0.0.0.0/0");
}else{
Boolean firstEntry = true;
for (String tag : cidr) {
if (!firstEntry) sb.append("-");
sb.append(tag);
firstEntry = false;
}
}
sb.append(":");
String fwRuleEntry = sb.toString();
toAdd.add(fwRuleEntry);
}
result[0] = toAdd.toArray(new String[toAdd.size()]);
return result;
}
}

View File

@ -25,8 +25,8 @@ public class SetStaticNatRulesAnswer extends Answer {
super();
}
public SetStaticNatRulesAnswer(SetStaticNatRulesCommand cmd, String[] results) {
super(cmd, true, null);
public SetStaticNatRulesAnswer(SetStaticNatRulesCommand cmd, String[] results, Boolean success) {
super(cmd, success, null);
assert(cmd.getRules().length == results.length) : "Shouldn't the results match the commands?";
this.results = results;

View File

@ -51,12 +51,16 @@ public class FirewallRuleTO {
int[] srcPortRange;
boolean revoked;
boolean alreadyAdded;
private List<String> sourceCidrList;
FirewallRule.Purpose purpose;
private Integer icmpType;
private Integer icmpCode;
protected FirewallRuleTO() {
}
public FirewallRuleTO(long id, String srcIp, String protocol, Integer srcPortStart, Integer srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose) {
public FirewallRuleTO(long id, String srcIp, String protocol, Integer srcPortStart, Integer srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose, List<String> sourceCidr,Integer icmpType,Integer icmpCode) {
this.srcIp = srcIp;
this.protocol = protocol;
@ -78,10 +82,13 @@ public class FirewallRuleTO {
this.revoked = revoked;
this.alreadyAdded = alreadyAdded;
this.purpose = purpose;
this.sourceCidrList = sourceCidr;
this.icmpType = icmpType;
this.icmpCode = icmpCode;
}
public FirewallRuleTO(FirewallRule rule, String srcIp) {
this(rule.getId(), srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose());
this(rule.getId(), srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public long getId() {
@ -100,14 +107,29 @@ public class FirewallRuleTO {
return srcPortRange;
}
public Integer getIcmpType(){
return icmpType;
}
public Integer getIcmpCode(){
return icmpCode;
}
public String getStringSrcPortRange() {
return NetUtils.portRangeToString(srcPortRange);
if (srcPortRange == null || srcPortRange.length < 2)
return "0:0";
else
return NetUtils.portRangeToString(srcPortRange);
}
public boolean revoked() {
return revoked;
}
public List<String> getSourceCidrList() {
return sourceCidrList;
}
public boolean isAlreadyAdded() {
return alreadyAdded;
}

View File

@ -45,7 +45,7 @@ public class PortForwardingRuleTO extends FirewallRuleTO {
}
protected PortForwardingRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) {
super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.PortForwarding);
super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.PortForwarding, null,0,0);
this.dstIp = dstIp;
this.dstPortRange = new int[] { dstPortStart, dstPortEnd };
}

View File

@ -36,13 +36,13 @@ public class StaticNatRuleTO extends FirewallRuleTO{
}
public StaticNatRuleTO(StaticNatRule rule, String scrIp, String dstIp) {
super(rule.getId(), scrIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(),rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose());
super(rule.getId(), scrIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(),rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(), null,0,0);
this.dstIp = dstIp;
}
protected StaticNatRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) {
super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.StaticNat);
public StaticNatRuleTO(long id, String srcIp, Integer srcPortStart, Integer srcPortEnd, String dstIp, Integer dstPortStart, Integer dstPortEnd, String protocol, boolean revoked, boolean alreadyAdded) {
super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, alreadyAdded, FirewallRule.Purpose.StaticNat, null,0,0);
this.dstIp = dstIp;
}

View File

@ -66,6 +66,9 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
@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;
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
private List<String> cidrlist;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -102,13 +105,14 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
@Override
public void execute() throws ResourceUnavailableException{
boolean result = true;
FirewallRule rule = null;
try {
UserContext.current().setEventDetails("Rule Id: "+ getEntityId());
if (getOpenFirewall()) {
result = result && _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), UserContext.current().getCaller());
result = result && _firewallService.applyFirewallRules(ipAddressId, UserContext.current().getCaller());
}
result = result && _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller());
@ -127,15 +131,19 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
@Override
public void create() {
StaticNatRule rule;
//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");
}
try {
rule = _rulesService.createStaticNatRule(this, getOpenFirewall());
StaticNatRule rule = _rulesService.createStaticNatRule(this, getOpenFirewall());
this.setEntityId(rule.getId());
} catch (NetworkRuleConflictException e) {
s_logger.info("Unable to create Static Nat Rule due to " + e.getMessage());
s_logger.info("Unable to create Static Nat Rule due to ", e);
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
}
this.setEntityId(rule.getId());
}
@Override
@ -269,4 +277,8 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
return null;
}
public List<String> getSourceCidrList() {
return null;
}
}

View File

@ -81,6 +81,9 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCmd /*implements LoadBa
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the domain ID associated with the load balancer")
private Long domainId;
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
private List<String> cidrlist;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -125,6 +128,14 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCmd /*implements LoadBa
return true;
}
}
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");
}
return null;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
@ -137,9 +148,17 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCmd /*implements LoadBa
@Override
public void execute() throws ResourceAllocationException, ResourceUnavailableException {
LoadBalancer result = null;
//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");
}
try {
result = _lbService.createLoadBalancerRule(this, getOpenFirewall());
LoadBalancer result = _lbService.createLoadBalancerRule(this, getOpenFirewall());
LoadBalancerResponse response = _responseGenerator.createLoadBalancerResponse(result);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (NetworkRuleConflictException e) {
s_logger.warn("Exception: ", e);
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
@ -147,9 +166,6 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCmd /*implements LoadBa
s_logger.warn("Exception: ", e);
throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, e.getMessage());
}
LoadBalancerResponse response = _responseGenerator.createLoadBalancerResponse(result);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}

View File

@ -98,7 +98,10 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
}
public List<String> getSourceCidrList() {
return cidrlist;
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");
}
return null;
}
public Boolean getOpenFirewall() {
@ -117,24 +120,20 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
public String getCommandName() {
return s_name;
}
public void setSourceCidrList(List<String> cidrs){
cidrlist = cidrs;
}
@Override
public void execute() throws ResourceUnavailableException {
UserContext callerContext = UserContext.current();
boolean success = true;
PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, getEntityId());
PortForwardingRule rule = null;
try {
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
if (getOpenFirewall()) {
success = success && _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
success = success && _firewallService.applyFirewallRules(ipAddressId, callerContext.getCaller());
}
success = success && _rulesService.applyPortForwardingRules(rule.getSourceIpAddressId(), callerContext.getCaller());
success = success && _rulesService.applyPortForwardingRules(ipAddressId, callerContext.getCaller());
// State is different after the rule is applied, so get new object here
rule = _entityMgr.findById(PortForwardingRule.class, getEntityId());
@ -227,17 +226,17 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
@Override
public void create() {
if (cidrlist != null)
for (String cidr: cidrlist){
if (!NetUtils.isValidCIDR(cidr)){
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Source cidrs formatting error " + cidr);
}
}
//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");
}
try {
PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, getOpenFirewall());
setEntityId(result.getId());
} catch (NetworkRuleConflictException ex) {
s_logger.info("Network rule conflict: " + ex.getMessage());
s_logger.info("Network rule conflict: " , ex);
s_logger.trace("Network Rule Conflict: ", ex);
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
}

View File

@ -76,7 +76,7 @@ public class DisableStaticNatCmd extends BaseAsyncCmd {
@Override
public void execute() throws ResourceUnavailableException {
boolean result = _rulesService.disableOneToOneNat(ipAddressId);
boolean result = _rulesService.disableStaticNat(ipAddressId);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());

View File

@ -80,7 +80,7 @@ public class EnableStaticNatCmd extends BaseCmd{
@Override
public void execute(){
try {
boolean result = _rulesService.enableOneToOneNat(ipAddressId, virtualMachineId);
boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -38,6 +38,9 @@ public class CapabilitiesResponse extends BaseResponse {
@SerializedName("supportELB") @Param(description="true if region supports elastic load balancer on basic zones")
private String supportELB;
@SerializedName("firewallRuleUiEnabled") @Param(description="true if the firewall rule UI is enabled")
private boolean firewallRuleUiEnabled;
public boolean getSecurityGroupsEnabled() {
return securityGroupsEnabled;
}

View File

@ -35,6 +35,7 @@ import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.NicProfile;
@ -132,5 +133,14 @@ public interface NetworkElement extends Adapter {
* @throws ResourceUnavailableException
*/
boolean applyRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException;
/**
* Creates static nat rule (public IP to private IP mapping) on the network element
* @param config
* @param rules
* @return
* @throws ResourceUnavailableException
*/
boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException;
}

View File

@ -54,9 +54,9 @@ public interface RulesService {
boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
boolean enableOneToOneNat(long ipAddressId, long vmId) throws NetworkRuleConflictException;
boolean enableStaticNat(long ipAddressId, long vmId) throws NetworkRuleConflictException;
boolean disableOneToOneNat(long ipAddressId) throws ResourceUnavailableException;
boolean disableStaticNat(long ipAddressId) throws ResourceUnavailableException;
PortForwardingRule getPortForwardigRule(long ruleId);
FirewallRule getFirewallRule(long ruleId);

View File

@ -0,0 +1,35 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.rules;
public interface StaticNat{
long getAccountId();
long getDomainId();
long getNetworkId();
long getSourceIpAddressId();
String getDestIpAddress();
boolean isForRevoke();
}

View File

@ -52,6 +52,8 @@ import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRulesAnswer;
import com.cloud.agent.api.routing.SetFirewallRulesCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesAnswer;
@ -121,6 +123,8 @@ public class VirtualRoutingResource implements Manager {
return execute ((VmDataCommand)cmd);
} else if (cmd instanceof CheckRouterCommand) {
return execute ((CheckRouterCommand)cmd);
} else if (cmd instanceof SetFirewallRulesCommand) {
return execute((SetFirewallRulesCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -129,6 +133,40 @@ public class VirtualRoutingResource implements Manager {
}
}
private Answer execute(SetFirewallRulesCommand cmd) {
String[] results = new String[cmd.getRules().length];
for (int i =0; i < cmd.getRules().length; i++) {
results[i] = "Failed";
}
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
if (routerIp == null) {
return new SetFirewallRulesAnswer(cmd, false, results);
}
String[][] rules = cmd.generateFwRules();
final Script command = new Script(_firewallPath, _timeout, s_logger);
command.add(routerIp);
command.add("-F");
StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0];
if (fwRules.length > 0) {
for (int i = 0; i < fwRules.length; i++) {
sb.append(fwRules[i]).append(',');
}
command.add("-a", sb.toString());
}
String result = command.execute();
if (result != null) {
return new SetFirewallRulesAnswer(cmd, false, results);
}
return new SetFirewallRulesAnswer(cmd, true, null);
}
private Answer execute(SetPortForwardingRulesCommand cmd) {
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
String[] results = new String[cmd.getRules().length];
@ -155,6 +193,7 @@ public class VirtualRoutingResource implements Manager {
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
String[] results = new String[cmd.getRules().length];
int i = 0;
boolean endResult = true;
for (StaticNatRuleTO rule : cmd.getRules()) {
String result = null;
final Script command = new Script(_firewallPath, _timeout, s_logger);
@ -169,10 +208,15 @@ public class VirtualRoutingResource implements Manager {
command.add(" -G ") ;
result = command.execute();
results[i++] = (!(result == null || result.isEmpty())) ? "Failed" : null;
if (result == null || result.isEmpty()) {
results[i++] = "Failed";
endResult = false;
} else {
results[i++] = null;
}
}
return new SetStaticNatRulesAnswer(cmd, results);
return new SetStaticNatRulesAnswer(cmd, results, endResult);
}

View File

@ -156,7 +156,6 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
@ -1270,6 +1269,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
//String args = routerIp;
String[] results = new String[cmd.getRules().length];
int i = 0;
boolean endResult = true;
for (StaticNatRuleTO rule : cmd.getRules()) {
//1:1 NAT needs instanceip;publicip;domrip;op
StringBuilder args = new StringBuilder();
@ -1277,15 +1277,23 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
args.append(rule.revoked() ? " -D " : " -A ");
args.append(" -l ").append(rule.getSrcIp());
args.append(" -r ").append(rule.getDstIp());
if (rule.getProtocol() != null) {
args.append(" -P ").append(rule.getProtocol().toLowerCase());
}
args.append(" -d ").append(rule.getStringSrcPortRange());
args.append(" -G ");
String result = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args.toString());
results[i++] = (result == null || result.isEmpty()) ? "Failed" : null;
if (result == null || result.isEmpty()) {
results[i++] = "Failed";
endResult = false;
} else {
results[i++] = null;
}
}
return new SetStaticNatRulesAnswer(cmd, results);
return new SetStaticNatRulesAnswer(cmd, results, endResult);
}
protected Answer execute(final LoadBalancerConfigCommand cmd) {
@ -6456,16 +6464,36 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) {
String[] results = new String[cmd.getRules().length];
String callResult;
Connection conn = getConnection();
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
String[] results = new String[cmd.getRules().length];
int i = 0;
for (FirewallRuleTO rule : cmd.getRules()) {
//FIXME - Jana, add implementation here
if (routerIp == null) {
return new SetFirewallRulesAnswer(cmd, false, results);
}
return new SetFirewallRulesAnswer(cmd, results);
String[][] rules = cmd.generateFwRules();
String args = "";
args += routerIp + " -F ";
StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0];
if (fwRules.length > 0) {
for (int i = 0; i < fwRules.length; i++) {
sb.append(fwRules[i]).append(',');
}
args += " -a " + sb.toString();
}
callResult = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args);
if (callResult == null || callResult.isEmpty()) {
//FIXME - in the future we have to process each rule separately; now we temporarily set every rule to be false if single rule fails
for (int i=0; i < results.length; i++) {
results[i] = "Failed";
}
return new SetFirewallRulesAnswer(cmd, false, results);
}
return new SetFirewallRulesAnswer(cmd, true, results);
}
}

View File

@ -138,6 +138,56 @@ one_to_one_fw_entry() {
return $result
}
fw_chain_for_ip() {
local pubIp=$1
if iptables -t mangle -N FIREWALL_$pubIp &> /dev/null
then
logger -t cloud "created a fw chain for $pubIp to DROP by default"
(sudo iptables -t mangle -A FIREWALL_$pubIp -j DROP) &&
(sudo iptables -t mangle -I FIREWALL_$pubIp -m state --state RELATED,ESTABLISHED -j ACCEPT ) &&
(sudo iptables -t mangle -I PREROUTING -d $pubIp -j FIREWALL_$pubIp)
return $?
fi
logger -t cloud "fw chain for $pubIp already exists"
return 0
}
static_nat() {
local publicIp=$1
local instIp=$2
local op=$3
local op2="-D"
local rulenum=
logger -t cloud "$(basename $0): static nat: public ip=$publicIp \
instance ip=$instIp op=$op"
#TODO check error below
fw_chain_for_ip $publicIp
#if adding, this might be a duplicate, so delete the old one first
[ "$op" == "-A" ] && static_nat $publicIp $instIp "-D"
# the delete operation may have errored out but the only possible reason is
# that the rules didn't exist in the first place
[ "$op" == "-A" ] && rulenum=1
[ "$op" == "-A" ] && op2="-I"
local dev=$(ip_to_dev $publicIp)
[ $? -ne 0 ] && echo "Could not find device associated with $publicIp" && return 1
# shortcircuit the process if error and it is an append operation
# continue if it is delete
(sudo iptables -t nat $op PREROUTING -i $dev -d $publicIp -j DNAT \
--to-destination $instIp &>> $OUTFILE || [ "$op" == "-D" ]) &&
(sudo iptables $op FORWARD -i $dev -o eth0 -d $instIp -m state \
--state NEW -j ACCEPT &>> $OUTFILE || [ "$op" == "-D" ]) &&
(sudo iptables -t nat $op2 POSTROUTING $rulenum -s $instIp -j SNAT \
--to-source $publicIp &>> $OUTFILE || [ "$op" == "-D" ])
result=$?
logger -t cloud "$(basename $0): done static nat entry public ip=$publicIp op=$op result=$result"
return $result
}
rflag=
@ -192,7 +242,12 @@ OUTFILE=$(mktemp)
#Firewall ports for one-to-one/static NAT
if [ "$Gflag" == "1" ]
then
one_to_one_fw_entry $publicIp $instanceIp $protocol $dport $op
if [ "$protocol" == "" ]
then
static_nat $publicIp $instanceIp $op
else
one_to_one_fw_entry $publicIp $instanceIp $protocol $dport $op
fi
result=$?
[ "$result" -ne 0 ] && cat $OUTFILE >&2
rm -f $OUTFILE

View File

@ -0,0 +1,186 @@
#!/usr/bin/env bash
#
# Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
#
# This software is licensed under the GNU General Public License v3 or later.
#
# It is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# firewall_rule.sh -- allow some ports / protocols to vm instances
#
#
# @VERSION@
usage() {
printf "Usage: %s: -a <public ip address:protocol:startport:endport:sourcecidrs> \n" $(basename $0) >&2
printf "sourcecidrs format: cidr1-cidr2-cidr3-...\n"
}
#set -x
#FIXME: eating up the error code during execution of iptables
fw_remove_backup() {
local pubIp=$1
sudo iptables -t mangle -F _FIREWALL_$pubIp 2> /dev/null
sudo iptables -t mangle -D PREROUTING -j _FIREWALL_$pubIp -d $pubIp 2> /dev/null
sudo iptables -t mangle -X _FIREWALL_$pubIp 2> /dev/null
}
fw_restore() {
local pubIp=$1
sudo iptables -t mangle -F FIREWALL_$pubIp 2> /dev/null
sudo iptables -t mangle -D PREROUTING -j FIREWALL_$pubIp -d $pubIp 2> /dev/null
sudo iptables -t mangle -X FIREWALL_$pubIp 2> /dev/null
sudo iptables -t mangle -E _FIREWALL_$pubIp FIREWALL_$pubIp 2> /dev/null
}
fw_chain_for_ip () {
local pubIp=$1
fw_remove_backup $1
sudo iptables -t mangle -E FIREWALL_$pubIp _FIREWALL_$pubIp 2> /dev/null
sudo iptables -t mangle -N FIREWALL_$pubIp 2> /dev/null
# drop if no rules match (this will be the last rule in the chain)
sudo iptables -t mangle -A FIREWALL_$pubIp -j DROP> /dev/null
# ensure outgoing connections are maintained (first rule in chain)
sudo iptables -t mangle -I FIREWALL_$pubIp -m state --state RELATED,ESTABLISHED -j ACCEPT> /dev/null
sudo iptables -t mangle -I PREROUTING -d $pubIp -j FIREWALL_$pubIp
}
fw_entry_for_public_ip() {
local rules=$1
local pubIp=$(echo $rules | cut -d: -f1)
local prot=$(echo $rules | cut -d: -f2)
local sport=$(echo $rules | cut -d: -f3)
local eport=$(echo $rules | cut -d: -f4)
local scidrs=$(echo $rules | cut -d: -f5 | sed 's/-/ /g')
logger -t cloud "$(basename $0): enter apply firewall rules for public ip $pubIp:$prot:$sport:$eport:$scidrs"
# note that rules are inserted after the RELATED,ESTABLISHED rule
# but before the DROP rule
for src in $scidrs
do
[ "$prot" == "reverted" ] && continue;
if [ "$prot" == "icmp" ]
then
typecode="$sport/$eport"
[ "$eport" == "-1" ] && typecode="$sport"
[ "$sport" == "-1" ] && typecode="any"
sudo iptables -t mangle -I FIREWALL_$pubIp 2 -s $src -p $prot \
--icmp-type $typecode -j RETURN
else
sudo iptables -t mangle -I FIREWALL_$pubIp 2 -s $src -p $prot \
--dport $sport:$eport -j RETURN
fi
result=$?
[ $result -gt 0 ] &&
logger -t cloud "Error adding iptables entry for $pubIp:$prot:$sport:$eport:$src" &&
break
done
logger -t cloud "$(basename $0): exit apply firewall rules for public ip $pubIp"
return $result
}
get_vif_list() {
local vif_list=""
for i in /sys/class/net/eth*; do
vif=$(basename $i);
if [ "$vif" != "eth0" ] && [ "$vif" != "eth1" ]
then
vif_list="$vif_list $vif";
fi
done
if [ "$vif_list" == "" ]
then
vif_list="eth0"
fi
logger -t cloud "FirewallRule public interfaces = $vif_list"
echo $vif_list
}
shift
rules=
while getopts 'a:' OPTION
do
case $OPTION in
a) aflag=1
rules="$OPTARG"
;;
?) usage
exit 2
;;
esac
done
VIF_LIST=$(get_vif_list)
if [ "$rules" == "" ]
then
rules="none"
fi
#-a 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:,172.16.92.44:tcp:222:222:192.168.10.0/24-75.57.23.0/22-88.100.33.1/32
# if any entry is reverted , entry will be in the format <ip>:reverted:0:0:0
# example : 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:,200.1.1.2:reverted:0:0:0
# The reverted entries will fix the following partially
#FIXME: rule leak: when there are multiple ip address, there will chance that entry will be left over if the ipadress does not appear in the current execution when compare to old one
# example : In the below first transaction have 2 ip's whereas in second transaction it having one ip, so after the second trasaction 200.1.2.3 ip will have rules in mangle table.
# 1) -a 172.16.92.44:tcp:80:80:0.0.0.0/0:,200.16.92.44:tcp:220:220:0.0.0.0/0:,
# 2) -a 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:,
success=0
publicIps=
rules_list=$(echo $rules | cut -d, -f1- --output-delimiter=" ")
for r in $rules_list
do
pubIp=$(echo $r | cut -d: -f1)
publicIps="$pubIp $publicIps"
done
unique_ips=$(echo $publicIps| tr " " "\n" | sort | uniq | tr "\n" " ")
for u in $unique_ips
do
fw_chain_for_ip $u
done
for r in $rules_list
do
pubIp=$(echo $r | cut -d: -f1)
fw_entry_for_public_ip $r
success=$?
if [ $success -gt 0 ]
then
logger -t cloud "$(basename $0): failure to apply fw rules for ip $pubIp"
break
else
logger -t cloud "$(basename $0): successful in applying fw rules for ip $pubIp"
fi
done
if [ $success -gt 0 ]
then
for p in $unique_ips
do
logger -t cloud "$(basename $0): restoring from backup for ip: $p"
fw_restore $p
done
fi
for p in $unique_ips
do
logger -t cloud "$(basename $0): deleting backup for ip: $p"
fw_remove_backup $p
done
exit $success

View File

@ -24,12 +24,12 @@
# firewall.sh -- allow some ports / protocols to vm instances
#
#
usage() {
printf "Usage: %s: (-A|-D) -i <domR eth1 ip> -r <target-instance-ip> -P protocol (-p port_range | -t icmp_type_code) -l <public ip address> -d <target port> [-f <firewall ip> -u <firewall user> -y <firewall password> -z <firewall enable password> ] \n" $(basename $0) >&2
printf "Usage for Firewall rule : %s: <domR eth1 ip> -F " $(basename $0) >&2
printf "Usage for other purposes : %s: <domR eth1 ip> (-A|-D) -i <domR eth1 ip> -r <target-instance-ip> -P protocol (-p port_range | -t icmp_type_code) -l <public ip address> -d <target port> [-f <firewall ip> -u <firewall user> -y <firewall password> -z <firewall enable password> ] \n" $(basename $0) >&2
}
# set -x
#set -x
# check if gateway domain is up and running
check_gw() {
@ -52,9 +52,22 @@ if [ $? -gt 0 ]
then
exit 1
fi
fflag=
while getopts ':F' OPTION
do
case $OPTION in
F) fflag=1
;;
\?) ;;
esac
done
ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/root/firewall.sh $*"
if [ -n "$fflag" ]
then
ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/root/firewall_rule.sh $*"
else
ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/root/firewall.sh $*"
fi
exit $?

View File

@ -35,6 +35,7 @@ import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpn.PasswordResetElement;
import com.cloud.network.vpn.RemoteAccessVpnElement;
import com.cloud.offerings.NetworkOfferingVO;
@ -210,4 +211,8 @@ public interface NetworkManager extends NetworkService {
String getGlobalGuestDomainSuffix();
String getStartIpAddress(long networkId);
boolean applyStaticNats(List<? extends StaticNat> staticNats, boolean continueOnError) throws ResourceUnavailableException;
String getIpInNetwork(long vmId, long networkId);
}

View File

@ -102,6 +102,7 @@ import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.RulesManager;
@ -2431,6 +2432,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
success = false;
}
// apply static nat
if (!_rulesMgr.applyStaticNatsForNetwork(networkId, false, caller)) {
s_logger.warn("Failed to apply static nats a part of network id" + networkId + " restart");
success = false;
}
// apply firewall rules
List<FirewallRuleVO> firewallRulesToApply = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.Firewall);
if (!_firewallMgr.applyFirewallRules(firewallRulesToApply, false, caller)) {
@ -2631,6 +2638,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return _nicDao.findByInstanceIdAndNetworkId(networkId, vmId);
}
@Override
public String getIpInNetwork(long vmId, long networkId) {
Nic guestNic = getNicInNetwork(vmId, networkId);
assert (guestNic != null && guestNic.getIp4Address() != null) : "Vm doesn't belong to network associated with ipAddress or ip4 address is null...how is it possible?";
return guestNic.getIp4Address();
}
@Override
public Nic getNicInNetworkIncludingRemoved(long vmId, long networkId) {
return _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(networkId, vmId);
@ -3190,4 +3204,29 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return startIP;
}
@Override
public boolean applyStaticNats(List<? extends StaticNat> staticNats, boolean continueOnError) throws ResourceUnavailableException {
if (staticNats == null || staticNats.size() == 0) {
s_logger.debug("There are no static nat rules for the network elements");
return true;
}
boolean success = true;
Network network = _networksDao.findById(staticNats.get(0).getNetworkId());
for (NetworkElement ne : _networkElements) {
try {
boolean handled = ne.applyStaticNats(network, staticNats);
s_logger.debug("Static Nat for network " + network.getId() + " were " + (handled ? "" : " not") + " handled by " + ne.getName());
} catch (ResourceUnavailableException e) {
if (!continueOnError) {
throw e;
}
s_logger.warn("Problems with " + ne.getName() + " but pushing on", e);
success = false;
}
}
return success;
}
}

View File

@ -45,6 +45,7 @@ import com.cloud.network.dao.NetworkDao;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpn.PasswordResetElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.AccountManager;
@ -120,7 +121,17 @@ public class DhcpElement extends AdapterBase implements NetworkElement, Password
VirtualMachineProfile<UserVm> uservm = (VirtualMachineProfile<UserVm>)vm;
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>(1);
params.put(VirtualMachineProfile.Param.RestartNetwork, true);
List<DomainRouterVO> routers = _routerMgr.deployDhcp(network, dest, _accountMgr.getAccount(network.getAccountId()), uservm.getParameters());
List<DomainRouterVO> routers = _routerMgr.deployDhcp(network, dest, _accountMgr.getAccount(network.getAccountId()), uservm.getParameters());
//for Basic zone, add all Running routers - we have to send Dhcp/vmData/password info to them when network.dns.basiczone.updates is set to "all"
Long podId = dest.getPod().getId();
DataCenter dc = dest.getDataCenter();
boolean isPodBased = (dc.getNetworkType() == NetworkType.Basic || network.isSecurityGroupEnabled()) && network.getTrafficType() == TrafficType.Guest;
if (isPodBased && _routerMgr.getDnsBasicZoneUpdate().equalsIgnoreCase("all")) {
List<DomainRouterVO> allRunningRoutersOutsideThePod = _routerDao.findByNetworkOutsideThePod(network.getId(), podId, State.Running);
routers.addAll(allRunningRoutersOutsideThePod);
}
List<VirtualRouter> rets = _routerMgr.addVirtualMachineIntoNetwork(network, nic, uservm, dest, context, routers);
return (rets != null) && (!rets.isEmpty());
} else {
@ -235,4 +246,9 @@ public class DhcpElement extends AdapterBase implements NetworkElement, Password
return _routerMgr.savePasswordToRouter(network, nic, uservm);
}
@Override
public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
return false;
}
}

View File

@ -42,6 +42,7 @@ import com.cloud.network.PublicIpAddress;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.lb.ElasticLoadBalancerManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.utils.component.AdapterBase;
@ -166,4 +167,9 @@ public class ElasticLoadBalancerElement extends AdapterBase implements NetworkEl
}
return true;
}
@Override
public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
return false;
}
}

View File

@ -38,6 +38,7 @@ import com.cloud.network.element.NetworkElement;
import com.cloud.network.ovs.OvsNetworkManager;
import com.cloud.network.ovs.OvsTunnelManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
@ -142,5 +143,10 @@ public class OvsElement extends AdapterBase implements NetworkElement {
throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
return false;
}
}

View File

@ -49,6 +49,7 @@ import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.RulesManager;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpn.RemoteAccessVpnElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
@ -284,4 +285,21 @@ public class VirtualRouterElement extends DhcpElement implements NetworkElement,
return capabilities;
}
@Override
public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
DataCenter dc = _configMgr.getZone(config.getDataCenterId());
if (canHandle(config.getGuestType(),dc)) {
long networkId = config.getId();
List<DomainRouterVO> routers = _routerDao.findByNetwork(networkId);
if (routers == null || routers.isEmpty()) {
s_logger.debug("Virtual router elemnt doesn't need to apply static nat on the backend; virtual router doesn't exist in the network " + config.getId());
return true;
}
return _routerMgr.applyStaticNats(config, rules);
} else {
return true;
}
}
}

View File

@ -10,6 +10,8 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.api.commands.ListFirewallRulesCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
@ -72,6 +74,10 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
NetworkManager _networkMgr;
@Inject
UsageEventDao _usageEventDao;
@Inject
ConfigurationDao _configDao;
private boolean _elbEnabled=false;
@Override
@ -92,6 +98,8 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
String elbEnabledString = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key());
_elbEnabled = Boolean.parseBoolean(elbEnabledString);
return true;
}
@ -111,16 +119,19 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
// Validate ip address
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " doesn't exist in the system");
} else if (ipAddress.isOneToOneNat()) {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " has static nat enabled");
}
validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol);
validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall);
//icmp code and icmp type can't be passed in for any other protocol rather than icmp
if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only");
}
if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) {
throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP");
}
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAccountId();
Long domainId = ipAddress.getDomainId();
@ -215,25 +226,26 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurposeAndNotRevoked(newRule.getSourceIpAddressId(), null);
assert (rules.size() >= 1) : "For network rules, we now always first persist the rule and then check for network conflicts so we should at least have one rule at this point.";
for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
continue; // Skips my own rule.
}
boolean allowFirewall = ((rule.getPurpose() == Purpose.Firewall || newRule.getPurpose() == Purpose.Firewall) && newRule.getPurpose() != rule.getPurpose());
if (!allowFirewall) {
if (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() != Purpose.StaticNat) {
throw new NetworkRuleConflictException("There is 1 to 1 Nat rule specified for the ip address id=" + newRule.getSourceIpAddressId());
} else if (rule.getPurpose() != Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat) {
throw new NetworkRuleConflictException("There is already firewall rule specified for the ip address id=" + newRule.getSourceIpAddressId());
}
}
if (rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + rule.getXid());
}
boolean allowFirewall = ((rule.getPurpose() == Purpose.Firewall || newRule.getPurpose() == Purpose.Firewall) && newRule.getPurpose() != rule.getPurpose());
boolean notNullPorts = (newRule.getSourcePortStart() != null && newRule.getSourcePortEnd() != null && rule.getSourcePortStart() != null && rule.getSourcePortEnd() != null);
if (!allowFirewall && notNullPorts && ((rule.getSourcePortStart() <= newRule.getSourcePortStart() && rule.getSourcePortEnd() >= newRule.getSourcePortStart())
|| (rule.getSourcePortStart() <= newRule.getSourcePortEnd() && rule.getSourcePortEnd() >= newRule.getSourcePortEnd())
@ -251,15 +263,12 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
}
if (newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO) && newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) {
if (newRule.getIcmpCode().longValue() == rule.getIcmpCode().longValue() || newRule.getIcmpType().longValue() == rule.getIcmpType().longValue() || newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) {
if (newRule.getIcmpCode().longValue() == rule.getIcmpCode().longValue() && newRule.getIcmpType().longValue() == rule.getIcmpType().longValue() && newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) {
throw new InvalidParameterValueException("New rule conflicts with existing rule id=" + rule.getId());
}
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("No network rule conflicts detected for " + newRule + " against " + (rules.size() - 1) + " existing rules");
}
@ -267,7 +276,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
@Override
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto) {
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose) {
// Validate ip address
_accountMgr.checkAccess(caller, ipAddress);
@ -293,10 +302,23 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
}
// Verify that the network guru supports the protocol specified
Map<Network.Capability, String> firewallCapabilities = _networkMgr.getServiceCapabilities(network.getDataCenterId(), network.getNetworkOfferingId(), Service.Firewall);
String supportedProtocols = firewallCapabilities.get(Capability.SupportedProtocols).toLowerCase();
Map<Network.Capability, String> protocolCapabilities = null;
if (purpose == Purpose.LoadBalancing) {
if (!_elbEnabled) {
protocolCapabilities = _networkMgr.getServiceCapabilities(network.getDataCenterId(), network.getNetworkOfferingId(), Service.Lb);
}
} else {
protocolCapabilities = _networkMgr.getServiceCapabilities(network.getDataCenterId(), network.getNetworkOfferingId(), Service.Firewall);
}
if (protocolCapabilities != null) {
String supportedProtocols = protocolCapabilities.get(Capability.SupportedProtocols).toLowerCase();
if (!supportedProtocols.contains(proto.toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone " + network.getDataCenterId());
} else if (proto.equalsIgnoreCase(NetUtils.ICMP_PROTO) && purpose != Purpose.Firewall) {
throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall);
}
}
}
@ -496,4 +518,5 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
return rules.size() == 0;
}
}

View File

@ -293,6 +293,13 @@ public class ElasticLoadBalancerManagerImpl implements
elbVm.getPrivateIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME,
elbVm.getInstanceName());
//FIXME: why are we setting attributes directly? Ick!! There should be accessors and
//the constructor should set defaults.
cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());
cmd.lbStatsAuth = _configDao.getValue(Config.NetworkLBHaproxyStatsAuth.key());
cmd.lbStatsPort = _configDao.getValue(Config.NetworkLBHaproxyStatsPort.key());
cmd.lbStatsIp = elbVm.getGuestIpAddress();
cmds.addCommand(cmd);
}

View File

@ -396,7 +396,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipId);
}
_firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol());
_firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), Purpose.LoadBalancing);
networkId = ipAddr.getAssociatedWithNetworkId();

View File

@ -30,6 +30,7 @@ import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.VirtualNetworkApplianceService;
import com.cloud.network.VpnUser;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.uservm.UserVm;
@ -72,7 +73,6 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
List<DomainRouterVO> deployDhcp(Network guestNetwork, DeployDestination dest, Account owner, Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException;
List<VirtualRouter> addVirtualMachineIntoNetwork(Network config, NicProfile nic, VirtualMachineProfile<UserVm> vm, DeployDestination dest, ReservationContext context, List<DomainRouterVO> routers) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException;
boolean startRemoteAccessVpn(Network network, RemoteAccessVpn vpn) throws ResourceUnavailableException;
@ -88,4 +88,9 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
String[] applyVpnUsers(Network network, List<? extends VpnUser> users) throws ResourceUnavailableException;
VirtualRouter stop(VirtualRouter router, boolean forced, User callingUser, Account callingAccount) throws ConcurrentOperationException, ResourceUnavailableException;
String getDnsBasicZoneUpdate();
boolean applyStaticNats(Network network, List<? extends StaticNat> rules) throws ResourceUnavailableException;
}

View File

@ -78,7 +78,6 @@ import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DcDetailsDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DataCenterDeployment;
@ -136,6 +135,8 @@ import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.RulesManager;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.StaticNatImpl;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering;
@ -1076,11 +1077,6 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
}
if (!routers.isEmpty()) {
//for Basic zone, add all Running routers - we have to send Dhcp/vmData/password info to them when network.dns.basiczone.updates is set to "all"
if (isPodBased) {
List<DomainRouterVO> allRunningRoutersOutsideThePod = _routerDao.findByNetworkOutsideThePod(guestNetwork.getId(), podId, State.Running);
routers.addAll(allRunningRoutersOutsideThePod);
}
return routers;
}
@ -1136,6 +1132,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
_networkDao.releaseFromLockTable(network.getId());
}
}
return routers;
}
@ -1397,7 +1394,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
List<RemoteAccessVpn> vpns = new ArrayList<RemoteAccessVpn>();
List<PortForwardingRule> pfRules = new ArrayList<PortForwardingRule>();
List<FirewallRule> staticNatFirewallRules = new ArrayList<FirewallRule>();
List<StaticNat> staticNats = new ArrayList<StaticNat>();
//Get information about all the rules (StaticNats and StaticNatRules; PFVPN to reapply on domR start)
for (PublicIpAddress ip : publicIps) {
pfRules.addAll(_pfRulesDao.listForApplication(ip.getId()));
staticNatFirewallRules.addAll(_rulesDao.listByIpAndPurpose(ip.getId(), Purpose.StaticNat));
@ -1406,6 +1405,18 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
if (vpn != null) {
vpns.add(vpn);
}
if (ip.isOneToOneNat()) {
String dstIp = _networkMgr.getIpInNetwork(ip.getAssociatedWithVmId(), networkId);
StaticNatImpl staticNat = new StaticNatImpl(ip.getAccountId(), ip.getDomainId(), networkId, ip.getId(), dstIp, false);
staticNats.add(staticNat);
}
}
//Re-apply static nats
s_logger.debug("Found " + staticNats.size() + " static nat(s) to apply as a part of domR " + router + " start.");
if (!staticNats.isEmpty()) {
createApplyStaticNatCommands(staticNats, router, cmds);
}
// Re-apply port forwarding rules
@ -1596,20 +1607,26 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
List<VirtualRouter> rets = new ArrayList<VirtualRouter>(routers.size());
boolean sendPasswordAndVmData = true;
boolean sendDnsDhcpData = true;
_userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine());
DataCenter dc = dest.getDataCenter();
String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(profile.getServiceOfferingId()).getDisplayText();
String zoneName = _dcDao.findById(network.getDataCenterId()).getName();
boolean isZoneBasic = (dc.getNetworkType() == NetworkType.Basic);
for (DomainRouterVO router : routers) {
if (router.getState() != State.Running) {
s_logger.warn("Unable to add virtual machine " + profile.getVirtualMachine() + " to the router " + router + " as the router is not in Running state");
continue;
}
boolean sendPasswordAndVmData = true;
boolean sendDnsDhcpData = true;
_userVmDao.loadDetails((UserVmVO) profile.getVirtualMachine());
//for basic zone:
//1) send vm data/password information only to the dhcp in the same pod
//2) send dhcp/dns information to all routers in the cloudstack only when _dnsBasicZoneUpdates is set to "all" value
DataCenter dc = dest.getDataCenter();
if (dc.getNetworkType() == NetworkType.Basic) {
if (isZoneBasic) {
Long podId = dest.getPod().getId();
if (router.getPodIdToDeployIn().longValue() != podId.longValue()) {
sendPasswordAndVmData = false;
@ -1658,8 +1675,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
cmds.addCommand("password", cmd);
}
String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(profile.getServiceOfferingId()).getDisplayText();
String zoneName = _dcDao.findById(network.getDataCenterId()).getName();
cmds.addCommand(
"vmdata",
@ -2074,6 +2090,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
s_logger.warn("Unable to associate ip addresses, virtual router is not in the right state " + router.getState());
throw new ResourceUnavailableException("Unable to assign ip addresses, domR is not in right state " + router.getState(), DataCenter.class, network.getDataCenterId());
}
//If rules fail to apply on one domR, no need to proceed with the rest
if (!result) {
throw new ResourceUnavailableException("Unable to apply firewall rules on router ", VirtualRouter.class, router.getId());
}
}
return result;
}
@ -2082,8 +2104,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
public boolean applyFirewallRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException {
List<DomainRouterVO> routers = _routerDao.findByNetwork(network.getId());
if (routers == null || routers.isEmpty()) {
s_logger.warn("Unable to apply lb rules, virtual router doesn't exist in the network " + network.getId());
throw new ResourceUnavailableException("Unable to apply lb rules", DataCenter.class, network.getDataCenterId());
s_logger.warn("Unable to apply firewall rules, virtual router doesn't exist in the network " + network.getId());
throw new ResourceUnavailableException("Unable to apply firewall rules", DataCenter.class, network.getDataCenterId());
}
boolean result = true;
@ -2111,6 +2133,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
result = false;
}
}
//If rules fail to apply on one domR, no need to proceed with the rest
if (!result) {
throw new ResourceUnavailableException("Unable to apply firewall rules on router ", VirtualRouter.class, router.getId());
}
} else if (router.getState() == State.Stopped || router.getState() == State.Stopping) {
s_logger.debug("Router is in " + router.getState() + ", so not sending apply firewall rules commands to the backend");
} else {
@ -2118,6 +2146,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
throw new ResourceUnavailableException("Unable to apply firewall rules, virtual router is not in the right state", VirtualRouter.class, router.getId());
}
}
return result;
}
@ -2179,4 +2208,68 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
// Send commands to router
return sendCommandsToRouter(router, cmds);
}
@Override
public String getDnsBasicZoneUpdate() {
return _dnsBasicZoneUpdates;
}
@Override
public boolean applyStaticNats(Network network, List<? extends StaticNat> rules) throws ResourceUnavailableException {
List<DomainRouterVO> routers = _routerDao.findByNetwork(network.getId());
if (routers == null || routers.isEmpty()) {
s_logger.warn("Unable to create static nat, virtual router doesn't exist in the network " + network.getId());
throw new ResourceUnavailableException("Unable to create static nat", DataCenter.class, network.getDataCenterId());
}
boolean result = true;
for (DomainRouterVO router : routers) {
if (router.getState() == State.Running) {
s_logger.debug("Applying " + rules.size() + " static nat in network " + network);
result = applyStaticNat(router, rules);
//If rules fail to apply on one domR, no need to proceed with the rest
if (!result) {
throw new ResourceUnavailableException("Unable to apply static nat on router ", VirtualRouter.class, router.getId());
}
} else if (router.getState() == State.Stopped || router.getState() == State.Stopping) {
s_logger.debug("Router is in " + router.getState() + ", so not sending apply firewall rules commands to the backend");
} else {
s_logger.warn("Unable to apply static nat, virtual router is not in the right state " + router.getState());
throw new ResourceUnavailableException("Unable to apply static nat, virtual router is not in the right state", VirtualRouter.class, router.getId());
}
}
return result;
}
protected boolean applyStaticNat(DomainRouterVO router, List<? extends StaticNat> rules) throws ResourceUnavailableException {
Commands cmds = new Commands(OnError.Continue);
createApplyStaticNatCommands(rules, router, cmds);
// Send commands to router
return sendCommandsToRouter(router, cmds);
}
private void createApplyStaticNatCommands(List<? extends StaticNat> rules, DomainRouterVO router, Commands cmds) {
List<StaticNatRuleTO> rulesTO = null;
if (rules != null) {
rulesTO = new ArrayList<StaticNatRuleTO>();
for (StaticNat rule : rules) {
IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId());
StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
rulesTO.add(ruleTO);
}
}
SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO);
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getGuestIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn());
cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString());
cmds.addCommand(cmd);
}
}

View File

@ -7,6 +7,7 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.firewall.FirewallService;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.user.Account;
public interface FirewallManager extends FirewallService{
@ -29,7 +30,7 @@ public interface FirewallManager extends FirewallService{
*/
void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException;
void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto);
void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose);
boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError) throws ResourceUnavailableException;

View File

@ -66,6 +66,9 @@ public interface RulesManager extends RulesService {
boolean releasePorts(long ipId, String protocol, FirewallRule.Purpose purpose, int... ports);
List<PortForwardingRuleVO> listByNetworkId(long networkId);
boolean applyStaticNatForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke);
boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError, Account caller);
}

View File

@ -165,7 +165,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " has static nat enabled");
}
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol());
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), Purpose.PortForwarding);
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAccountId();
@ -225,7 +225,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
if (e instanceof NetworkRuleConflictException) {
throw (NetworkRuleConflictException) e;
}
throw new CloudRuntimeException("Unable to add rule for the ip id=" + newRule.getSourceIpAddressId(), e);
throw new CloudRuntimeException("Unable to add rule for the ip id=" + ipAddrId, e);
}
}
@ -245,16 +245,13 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new NetworkRuleConflictException("Can't do static nat on ip address: " + ipAddress.getAddress());
}
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol());
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), Purpose.StaticNat);
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAccountId();
Long domainId = ipAddress.getDomainId();
// Get nic IP4 address
Nic guestNic = _networkMgr.getNicInNetwork(ipAddress.getAssociatedWithVmId(), networkId);
assert (guestNic != null && guestNic.getIp4Address() != null) : "Vm doesn't belong to network associated with ipAddress or ip4 address is null...how is it possible?";
String dstIp = guestNic.getIp4Address();
String dstIp = _networkMgr.getIpInNetwork(ipAddress.getAssociatedWithVmId(), networkId);
Transaction txn = Transaction.currentTxn();
txn.start();
@ -291,7 +288,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
public boolean enableOneToOneNat(long ipId, long vmId) throws NetworkRuleConflictException {
public boolean enableStaticNat(long ipId, long vmId) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
@ -351,7 +348,22 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
ipAddress.setOneToOneNat(true);
ipAddress.setAssociatedWithVmId(vmId);
return _ipAddressDao.update(ipAddress.getId(), ipAddress);
if (_ipAddressDao.update(ipAddress.getId(), ipAddress)) {
//enable static nat on the backend
s_logger.trace("Enabling static nat for ip address " + ipAddress + " and vm id=" + vmId + " on the backend");
if (applyStaticNatForIp(ipId, false, caller, false)) {
return true;
} else {
ipAddress.setOneToOneNat(false);
ipAddress.setAssociatedWithVmId(null);
_ipAddressDao.update(ipAddress.getId(), ipAddress);
s_logger.warn("Failed to enable static nat rule for ip address " + ipId + " on the backend");
return false;
}
} else {
s_logger.warn("Failed to update ip address " + ipAddress + " in the DB as a part of enableStaticNat");
return false;
}
}
@ -692,6 +704,38 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return true;
}
@Override
public boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError, Account caller) {
List<IPAddressVO> ips = _ipAddressDao.listStaticNatPublicIps(networkId);
if (ips.isEmpty()) {
s_logger.debug("There are no static nat to apply for network id=" + networkId);
return true;
}
if (caller != null) {
_accountMgr.checkAccess(caller, ips.toArray(new IPAddressVO[ips.size()]));
}
List<StaticNat> staticNats = new ArrayList<StaticNat>();
for (IPAddressVO ip : ips) {
// Get nic IP4 address
String dstIp = _networkMgr.getIpInNetwork(ip.getAssociatedWithVmId(), networkId);
StaticNatImpl staticNat = new StaticNatImpl(ip.getAccountId(), ip.getDomainId(), networkId, ip.getId(), dstIp, false);
staticNats.add(staticNat);
}
try {
if (!_networkMgr.applyStaticNats(staticNats, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to create static nat rule due to ", ex);
return false;
}
return true;
}
@Override
public List<? extends FirewallRule> searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId) {
Account caller = UserContext.current().getCaller();
@ -797,11 +841,15 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
s_logger.debug("Releasing " + staticNatRules.size() + " static nat rules for ip id=" + ipId);
}
for (FirewallRuleVO rule : staticNatRules) {
// Mark all static nat rules as Revoke, but don't revoke them yet
revokeStaticNatRuleInternal(rule.getId(), caller, userId, false);
}
//revoke static nat for the ip address
boolean staticNatRevoked = applyStaticNatForIp(ipId, false, caller, true);
// revoke all port forwarding rules
applyPortForwardingRules(ipId, true, caller);
@ -816,7 +864,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
s_logger.debug("Successfully released rules for ip id=" + ipId + " and # of rules now = " + rules.size());
}
return rules.size() == 0;
return (rules.size() == 0 && staticNatRevoked);
}
@Override
@ -955,7 +1003,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
public boolean disableOneToOneNat(long ipId) throws ResourceUnavailableException {
public boolean disableStaticNat(long ipId) throws ResourceUnavailableException {
boolean success = true;
Account caller = UserContext.current().getCaller();
@ -1002,9 +1050,53 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new InvalidParameterValueException("Source ip address of the rule id=" + rule.getId() + " is not static nat enabled");
}
Nic guestNic = _networkMgr.getNicInNetwork(ip.getAssociatedWithVmId(), rule.getNetworkId());
String dstIp = _networkMgr.getIpInNetwork(ip.getAssociatedWithVmId(), rule.getNetworkId());
return new StaticNatRuleImpl(ruleVO, guestNic.getIp4Address());
return new StaticNatRuleImpl(ruleVO, dstIp);
}
@Override
public boolean applyStaticNatForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) {
List<StaticNat> staticNats = new ArrayList<StaticNat>();
IpAddress sourceIp = _ipAddressDao.findById(sourceIpId);
if (!sourceIp.isOneToOneNat()) {
s_logger.debug("Source ip id=" + sourceIpId + " is not one to one nat");
return true;
}
Long networkId = sourceIp.getAssociatedWithNetworkId();
if (networkId == null) {
throw new CloudRuntimeException("Ip address is not associated with any network");
}
UserVmVO vm = _vmDao.findById(sourceIp.getAssociatedWithVmId());
Network network = _networkMgr.getNetwork(networkId);
if (network == null) {
throw new CloudRuntimeException("Unable to find ip address to map to in vm id=" + vm.getId());
}
if (caller != null) {
_accountMgr.checkAccess(caller, sourceIp);
}
//create new static nat rule
// Get nic IP4 address
String dstIp = _networkMgr.getIpInNetwork(sourceIp.getAssociatedWithVmId(), networkId);
StaticNatImpl staticNat = new StaticNatImpl(sourceIp.getAccountId(), sourceIp.getDomainId(), networkId, sourceIpId, dstIp, forRevoke);
staticNats.add(staticNat);
try {
if (!_networkMgr.applyStaticNats(staticNats, continueOnError)) {
return false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to create static nat rule due to ", ex);
return false;
}
return true;
}
}

View File

@ -0,0 +1,71 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.rules;
public class StaticNatImpl implements StaticNat{
long accountId;
long domainId;
long networkId;
long sourceIpAddressId;
String destIpAddress;
boolean forRevoke;
public StaticNatImpl(long accountId, long domainId, long networkId, long sourceIpAddressId, String destIpAddress, boolean forRevoke) {
super();
this.accountId = accountId;
this.domainId = domainId;
this.networkId = networkId;
this.sourceIpAddressId = sourceIpAddressId;
this.destIpAddress = destIpAddress;
this.forRevoke = forRevoke;
}
@Override
public long getAccountId() {
return accountId;
}
@Override
public long getDomainId() {
return domainId;
}
@Override
public long getNetworkId() {
return networkId;
}
@Override
public long getSourceIpAddressId() {
return sourceIpAddressId;
}
@Override
public String getDestIpAddress() {
return destIpAddress;
}
@Override
public boolean isForRevoke() {
return forRevoke;
}
}

View File

@ -1254,7 +1254,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(vmId);
try {
if (ip != null) {
if (_rulesMgr.disableOneToOneNat(ip.getId())) {
if (_rulesMgr.disableStaticNat(ip.getId())) {
s_logger.debug("Disabled 1-1 nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");
} else {
s_logger.warn("Failed to disable static nat for ip address " + ip + " as a part of vm id=" + vmId + " expunge");

View File

@ -1557,6 +1557,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
if(trackExternalChange) {
if(serverState == State.Starting) {
if(vm.getHostId() != null && vm.getHostId() != hostId) {
s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: " + vm.getInstanceName());
return null;
}
}
if(vm.getHostId() == null || hostId != vm.getHostId()) {
try {
stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);