1) Changed format for IpAssoc command. Instead of sending the ip addresses to assign one by one, we send a list of ip addresses to the agent.

2) Fixed createVM with multiple networks
This commit is contained in:
alena 2010-12-17 19:00:19 -08:00
parent 5e8be4a431
commit 3cd989cbef
10 changed files with 183 additions and 146 deletions

View File

@ -20,8 +20,8 @@ package com.cloud.agent.api;
import com.cloud.utils.exception.ExceptionUtil;
public class Answer extends Command {
boolean result;
String details;
protected boolean result;
protected String details;
protected Answer() {
}

View File

@ -17,67 +17,32 @@
*/
package com.cloud.agent.api.routing;
import com.cloud.agent.api.to.IpAddressTO;
/**
* @author chiradeep
* @author alena
*
*/
public class IPAssocCommand extends RoutingCommand {
private String routerName;
private String routerIp;
private String publicIp;
private boolean sourceNat;
private boolean add;
private boolean oneToOneNat;
private boolean firstIP;
private String vlanId;
private String vlanGateway;
private String vlanNetmask;
private String vifMacAddress;
private String guestIp;
IpAddressTO[] ipAddresses;
protected IPAssocCommand() {
}
public IPAssocCommand(String routerName, String privateIpAddress, String ipAddress, boolean add, boolean firstIP, boolean sourceNat, String vlanId, String vlanGateway, String vlanNetmask, String vifMacAddress, String guestIp) {
public IPAssocCommand(String routerName, String privateIpAddress, IpAddressTO[] ips) {
this.setRouterName(routerName);
this.routerIp = privateIpAddress;
this.publicIp = ipAddress;
this.add = add;
this.firstIP = firstIP;
this.sourceNat = sourceNat;
this.vlanId = vlanId;
this.vlanGateway = vlanGateway;
this.vlanNetmask = vlanNetmask;
this.vifMacAddress = vifMacAddress;
this.guestIp = guestIp;
this.ipAddresses = ips;
}
public String getGuestIp(){
return guestIp;
}
public String getRouterIp() {
return routerIp;
}
public String getPublicIp() {
return publicIp;
}
public boolean isAdd() {
return add;
}
public boolean isOneToOneNat(){
return this.oneToOneNat;
}
public boolean isFirstIP() {
return firstIP;
}
@Override
public boolean executeInSequence() {
return false;
@ -91,27 +56,9 @@ public class IPAssocCommand extends RoutingCommand {
return routerName;
}
public void setSourceNat(boolean sourceNat) {
this.sourceNat = sourceNat;
}
public IpAddressTO[] getIpAddresses() {
return ipAddresses;
}
public boolean isSourceNat() {
return sourceNat;
}
public String getVlanId() {
return vlanId;
}
public String getVlanGateway() {
return vlanGateway;
}
public String getVlanNetmask() {
return vlanNetmask;
}
public String getVifMacAddress() {
return vifMacAddress;
}
}

View File

@ -0,0 +1,54 @@
/**
* 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.agent.api.routing;
import com.cloud.agent.api.Answer;
/**
*
* @author alena
*
*/
public class IpAssocAnswer extends Answer{
String[] results;
public static final String errorResult = "Failed";
protected IpAssocAnswer() {
super();
}
public IpAssocAnswer(IPAssocCommand cmd, String[] results) {
boolean finalResult = true;
for (String result : results) {
if (result.equals(errorResult)) {
finalResult = false;
break;
}
}
this.result = finalResult;
this.details = null;
assert(cmd.getIpAddresses().length == results.length) : "Shouldn't the results match the commands?";
this.results = results;
}
String[] getResults() {
return results;
}
}

View File

@ -46,9 +46,11 @@ import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.IPAssocCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.LoadBalancerCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Manager;
import com.cloud.utils.script.OutputInterpreter;
@ -203,11 +205,19 @@ public class VirtualRoutingResource implements Manager {
}
protected Answer execute(final IPAssocCommand cmd) {
final String result = assignPublicIpAddress(cmd.getRouterName(), cmd.getRouterIp(), cmd.getPublicIp(), cmd.isAdd(), cmd.isSourceNat(), cmd.getVlanId(), cmd.getVlanGateway(), cmd.getVlanNetmask());
if (result != null) {
return new Answer(cmd, false, result);
IpAddressTO[] ips = cmd.getIpAddresses();
String[] results = new String[cmd.getIpAddresses().length];
int i = 0;
String result = null;
for (IpAddressTO ip : ips) {
result = assignPublicIpAddress(cmd.getRouterName(), cmd.getRouterIp(), ip.getPublicIp(), ip.isAdd(), ip.isSourceNat(), ip.getVlanId(), ip.getVlanGateway(), ip.getVlanNetmask());
if (result != null) {
results[i++] = IpAssocAnswer.errorResult;
} else {
results[i++] = result;
}
}
return new Answer(cmd);
return new IpAssocAnswer(cmd, results);
}
private String setLoadBalancerConfig(final String cfgFile,

View File

@ -121,6 +121,7 @@ import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.IPAssocCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.LoadBalancerCfgCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
@ -138,6 +139,7 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.storage.ShareAnswer;
import com.cloud.agent.api.storage.ShareCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StorageFilerTO;
@ -1255,14 +1257,22 @@ public abstract class CitrixResourceBase implements ServerResource {
protected Answer execute(final IPAssocCommand cmd) {
Connection conn = getConnection();
String[] results = new String[cmd.getIpAddresses().length];
int i = 0;
try {
assignPublicIpAddress(conn, cmd.getRouterName(), cmd.getRouterIp(), cmd.getPublicIp(), cmd.isAdd(), cmd.isFirstIP(), cmd.isSourceNat(), cmd.getVlanId(),
cmd.getVlanGateway(), cmd.getVlanNetmask(), cmd.getVifMacAddress(), cmd.getGuestIp());
IpAddressTO[] ips = cmd.getIpAddresses();
for (IpAddressTO ip : ips) {
assignPublicIpAddress(conn, cmd.getRouterName(), cmd.getRouterIp(), ip.getPublicIp(), ip.isAdd(), ip.isFirstIP(), ip.isSourceNat(), ip.getVlanId(),
ip.getVlanGateway(), ip.getVlanNetmask(), ip.getVifMacAddress(), ip.getGuestIp());
results[i++] = ip.getPublicIp() + " - success";
}
} catch (InternalErrorException e) {
return new Answer(cmd, false, e.getMessage());
s_logger.error(
"Ip Assoc failure on applying one ip due to exception: ", e);
results[i++] = IpAssocAnswer.errorResult;
}
return new Answer(cmd);
return new IpAssocAnswer(cmd, results);
}
protected GetVncPortAnswer execute(GetVncPortCommand cmd) {

View File

@ -529,7 +529,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
@DB
public Pod editPod(UpdatePodCmd cmd)
{
//Input validation
String startIp = cmd.getStartIp();
String endIp = cmd.getEndIp();
@ -2171,7 +2170,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
stmt.executeUpdate();
stmt.close();
} catch (Exception ex) {
s_logger.debug("Exception saving public IP range: " + ex);
s_logger.warn("Exception saving public IP range: ", ex);
return false;
}
startIPLong += 1;

View File

@ -38,7 +38,6 @@ import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.routing.IPAssocCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
@ -101,8 +100,8 @@ import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.router.DomainRouterManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.PortForwardingRuleVO;
@ -395,7 +394,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress();
}
cmds.addCommand(new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress));
//cmds.addCommand(new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress));
firstIP = false;
}

View File

@ -20,6 +20,7 @@ package com.cloud.network.router;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -54,6 +55,7 @@ import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
@ -129,7 +131,6 @@ import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.PortForwardingRuleVO;
import com.cloud.network.rules.RulesManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
@ -580,41 +581,41 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute
return startRouter(cmd.getId());
}
private boolean resendRouterState(final DomainRouterVO router) {
if (router.getRole() == Role.DHCP_FIREWALL_LB_PASSWD_USERDATA) {
//source NAT address is stored in /proc/cmdline of the domR and gets
//reassigned upon powerup. Source NAT rule gets configured in StartRouter command
final List<IPAddressVO> ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(router.getAccountId(), router.getDataCenterId(), null);
final List<String> ipAddrList = new ArrayList<String>();
for (final IPAddressVO ipVO : ipAddrs) {
ipAddrList.add(ipVO.getAddress());
}
if (!ipAddrList.isEmpty()) {
try {
final boolean success = _networkMgr.associateIP(router, ipAddrList, true, 0);
if (!success) {
return false;
}
} catch (ConcurrentOperationException e) {
s_logger.warn("unable to associate ip due to ", e);
return false;
}
}
final List<PortForwardingRuleVO> fwRules = new ArrayList<PortForwardingRuleVO>();
//FIXME: for (final IPAddressVO ipVO : ipAddrs) {
// //We need only firewall rules that are either forwarding or for load balancers
// fwRules.addAll(_rulesDao.listIPForwarding(ipVO.getAddress(), true));
// fwRules.addAll(_rulesDao.listIpForwardingRulesForLoadBalancers(ipVO.getAddress()));
// private boolean resendRouterState(final DomainRouterVO router) {
// if (router.getRole() == Role.DHCP_FIREWALL_LB_PASSWD_USERDATA) {
// //source NAT address is stored in /proc/cmdline of the domR and gets
// //reassigned upon powerup. Source NAT rule gets configured in StartRouter command
// final List<IPAddressVO> ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(router.getAccountId(), router.getDataCenterId(), null);
// final List<String> ipAddrList = new ArrayList<String>();
// for (final IPAddressVO ipVO : ipAddrs) {
// ipAddrList.add(ipVO.getAddress());
// }
// final List<PortForwardingRuleVO> result = _networkMgr.updateFirewallRules(router
// .getPublicIpAddress(), fwRules, router);
// if (result.size() != fwRules.size()) {
// return false;
// if (!ipAddrList.isEmpty()) {
// try {
// final boolean success = _networkMgr.associateIP(router, ipAddrList, true, 0);
// if (!success) {
// return false;
// }
// } catch (ConcurrentOperationException e) {
// s_logger.warn("unable to associate ip due to ", e);
// return false;
// }
// }
}
return resendDhcpEntries(router) && resendVpnServerData(router);
}
// final List<PortForwardingRuleVO> fwRules = new ArrayList<PortForwardingRuleVO>();
////FIXME: for (final IPAddressVO ipVO : ipAddrs) {
//// //We need only firewall rules that are either forwarding or for load balancers
//// fwRules.addAll(_rulesDao.listIPForwarding(ipVO.getAddress(), true));
//// fwRules.addAll(_rulesDao.listIpForwardingRulesForLoadBalancers(ipVO.getAddress()));
//// }
//// final List<PortForwardingRuleVO> result = _networkMgr.updateFirewallRules(router
//// .getPublicIpAddress(), fwRules, router);
//// if (result.size() != fwRules.size()) {
//// return false;
//// }
// }
// return resendDhcpEntries(router) && resendVpnServerData(router);
//
// }
private boolean resendDhcpEntries(final DomainRouterVO router){
final List<? extends UserVm> vms = _vmDao.listBy(router.getId(), State.Creating, State.Starting, State.Running, State.Stopping, State.Stopped, State.Migrating);
@ -1987,35 +1988,53 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute
// }
private Commands getAssociateIPCommands(final DomainRouterVO router, final List<? extends PublicIpAddress> ipAddrList, Commands cmds, long vmId) {
//Ip addresses have to be sorted before sending
Collections.sort(ipAddrList, new Comparator<IpAddress>() {
@Override
public int compare(IpAddress o1, IpAddress o2) {
return o1.getAddress().compareTo(o2.getAddress());
} });
boolean firstIP = true;
for (final PublicIpAddress ip: ipAddrList) {
private Commands getAssociateIPCommands(final DomainRouterVO router, final List<? extends PublicIpAddress> ips, Commands cmds, long vmId) {
//Ensure that in multiple vlans case we first send all ip addresses of vlan1, then all ip addresses of vlan2, etc..
Map<String, ArrayList<PublicIpAddress>> vlanIpMap = new HashMap<String, ArrayList<PublicIpAddress>>();
for (final PublicIpAddress ipAddress: ips) {
String vlanTag = ipAddress.getVlanTag();
ArrayList<PublicIpAddress> ipList = vlanIpMap.get(vlanTag);
if (ipList == null) {
ipList = new ArrayList<PublicIpAddress>();
}
ipList.add(ipAddress);
vlanIpMap.put(vlanTag, ipList);
}
for (Map.Entry<String, ArrayList<PublicIpAddress>> vlanAndIp: vlanIpMap.entrySet()) {
List<PublicIpAddress> ipAddrList = vlanAndIp.getValue();
//Source nat ip address should always be sent first
Collections.sort(ipAddrList, new Comparator<PublicIpAddress>() {
@Override
public int compare(PublicIpAddress o1, PublicIpAddress o2) {
boolean s1 = o1.isSourceNat();
boolean s2 = o2.isSourceNat();
return (s1 ^ s2) ? ((s1 ^ true) ? 1 : -1) : 0;
} });
boolean add = (ip.getState() == IpAddress.State.Releasing ? false : true);
boolean sourceNat = ip.isSourceNat();
String vlanId = ip.getVlanTag();
String vlanGateway = ip.getGateway();
String vlanNetmask = ip.getNetmask();
String vifMacAddress = ip.getMacAddress();
String vmGuestAddress = null;
if(vmId!=0){
vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress();
IpAddressTO[] ipsToSend = new IpAddressTO[ipAddrList.size()];
int i = 0;
boolean firstIP = true;
for (final PublicIpAddress ipAddr: ipAddrList) {
boolean add = (ipAddr.getState() == IpAddress.State.Releasing ? false : true);
boolean sourceNat = ipAddr.isSourceNat();
String vlanId = ipAddr.getVlanTag();
String vlanGateway = ipAddr.getGateway();
String vlanNetmask = ipAddr.getNetmask();
String vifMacAddress = ipAddr.getMacAddress();
String vmGuestAddress = null;
if(vmId!=0){
vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress();
}
IpAddressTO ip = new IpAddressTO(ipAddr.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress);
ipsToSend[i++] = ip;
firstIP = false;
}
cmds.addCommand("IPAssocCommand", new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress));
firstIP = false;
}
cmds.addCommand("IPAssocCommand", new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ipsToSend));
}
return cmds;
}

View File

@ -3194,15 +3194,16 @@ public class ManagementServerImpl implements ManagementServer {
+ " and parentId " + parentId);
return dbDomain;
} catch (IllegalArgumentException ex) {
s_logger.warn("Failed to create domain ", ex);
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
+ " and parentId " + parentId);
throw ex;
}
} else {
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
+ " and parentId " + parentId);
throw new InvalidParameterValueException("Domain with name " + name + " already exists for the parent id=" + parentId);
}
return null;
}
@Override

View File

@ -134,6 +134,7 @@ import com.cloud.network.router.DomainRouterManager;
import com.cloud.network.rules.RulesManager;
import com.cloud.network.security.SecurityGroupManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.service.ServiceOfferingVO;
@ -2504,15 +2505,12 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
throw new InvalidParameterValueException("Unable to find network by id " + networkId);
} else {
if (!network.isShared()) {
//Iterate through account/network map
//Check account permissions
List<NetworkVO> networkMap = _networkDao.listBy(accountId, networkId);
if (networkMap == null || networkMap.isEmpty()) {
throw new PermissionDeniedException("Unable to create a vm using network with id " + networkId + ", permission denied");
}
} else if (network.getTrafficType() != TrafficType.Guest) {
throw new InvalidParameterValueException("Unable to create a vm using network which traffic type is " + network.getTrafficType() + ". " +
"Only Guest traffic type is acceptes");
}
}
networks.add(new Pair<NetworkVO, NicProfile>(network, null));
}
}