diff --git a/api/src/com/cloud/api/commands/RestartNetworkCmd.java b/api/src/com/cloud/api/commands/RestartNetworkCmd.java new file mode 100644 index 00000000000..0936069fff5 --- /dev/null +++ b/api/src/com/cloud/api/commands/RestartNetworkCmd.java @@ -0,0 +1,120 @@ +/** + * 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 . + * + */ +package com.cloud.api.commands; + +import java.util.List; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseCmd; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.IPAddressResponse; +import com.cloud.api.response.SuccessResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.user.UserContext; + +@Implementation(description="Reapplies all ip addresses for the particular network", responseObject=IPAddressResponse.class) +public class RestartNetworkCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(RestartNetworkCmd.class.getName()); + private static final String s_name = "restartnetworkresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account to associate with this IP address") + private String accountName; + + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the domain to associate with this IP address") + private Long domainId; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=true, description="the ID of the availability zone you want to acquire an public IP address from") + private Long zoneId; + + @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="The network this ip address should be associated to.") + private Long networkId; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + if (accountName != null) { + return accountName; + } + return UserContext.current().getAccount().getAccountName(); + } + + public long getDomainId() { + if (domainId != null) { + return domainId; + } + return UserContext.current().getAccount().getDomainId(); + } + + public long getZoneId() { + return zoneId; + } + + public Long getNetworkId() { + if (networkId != null) { + return networkId; + } + + List networks = _networkService.getVirtualNetworksOwnedByAccountInZone(getAccountName(), getDomainId(), getZoneId()); + if (networks.size() == 0) { + return null; + } + assert (networks.size() <= 1) : "Too many virtual networks. This logic should be obsolete"; + return networks.get(0).getId(); + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + + @Override + public String getCommandName() { + return s_name; + } + + public static String getResultObjectName() { + return "addressinfo"; + } + + @Override + public void execute() throws ResourceUnavailableException, ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { + boolean result = _networkService.restartNetwork(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to restart network"); + } + } +} diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index de04505bd1f..b075ff34565 100644 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -23,10 +23,10 @@ import com.cloud.api.commands.AddVpnUserCmd; import com.cloud.api.commands.AssociateIPAddrCmd; import com.cloud.api.commands.CreateNetworkCmd; import com.cloud.api.commands.CreateRemoteAccessVpnCmd; -import com.cloud.api.commands.DeleteNetworkCmd; import com.cloud.api.commands.DeleteRemoteAccessVpnCmd; import com.cloud.api.commands.DisassociateIPAddrCmd; import com.cloud.api.commands.ListNetworksCmd; +import com.cloud.api.commands.RestartNetworkCmd; import com.cloud.api.commands.RemoveVpnUserCmd; import com.cloud.exception.AccountLimitException; import com.cloud.exception.ConcurrentOperationException; @@ -86,5 +86,6 @@ public interface NetworkService { Network createNetwork(CreateNetworkCmd cmd) throws InvalidParameterValueException, PermissionDeniedException; List searchForNetworks(ListNetworksCmd cmd) throws InvalidParameterValueException, PermissionDeniedException; boolean deleteNetwork(long networkId) throws InvalidParameterValueException, PermissionDeniedException; - + + boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException; } diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java index 0e8a439e039..e4357baeabe 100644 --- a/api/src/com/cloud/network/element/NetworkElement.java +++ b/api/src/com/cloud/network/element/NetworkElement.java @@ -68,23 +68,15 @@ public interface NetworkElement extends Adapter { */ boolean shutdown(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException; + /** - * Associate a new ip address to this network + * Apply ip addresses to this network * @param network * @param ipAddress * @return * @throws ResourceUnavailableException */ - boolean associate(Network network, List ipAddress) throws ResourceUnavailableException; - - /** - * Disassociate the ip address from this network - * @param network - * @param ipAddress - * @return - * @throws ResourceUnavailableException - */ - boolean disassociate(Network network, List ipAddress) throws ResourceUnavailableException; + boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; /** * Apply rules diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index fce70935f63..f9f77d817b5 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -102,6 +102,7 @@ listVlanIpRanges=com.cloud.api.commands.ListVlanIpRangesCmd;1 associateIpAddress=com.cloud.api.commands.AssociateIPAddrCmd;15 disassociateIpAddress=com.cloud.api.commands.DisassociateIPAddrCmd;15 listPublicIpAddresses=com.cloud.api.commands.ListPublicIpAddressesCmd;15 +restartNetwork=com.cloud.api.commands.RestartNetworkCmd;15 #### firewall commands listPortForwardingRules=com.cloud.api.commands.ListPortForwardingRulesCmd;15 diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 052c34af623..aa0bdf8baea 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -127,6 +127,4 @@ public interface NetworkManager extends NetworkService { boolean applyRules(Ip ip, List rules, boolean continueOnError) throws ResourceUnavailableException; - Commands getAssociateIPCommands(DomainRouterVO router, - List ipAddrList, boolean add, long vmId, Commands cmds); } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index b72463fc813..90176e4c842 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -49,6 +49,7 @@ import com.cloud.api.commands.CreateRemoteAccessVpnCmd; import com.cloud.api.commands.DeleteRemoteAccessVpnCmd; import com.cloud.api.commands.DisassociateIPAddrCmd; import com.cloud.api.commands.ListNetworksCmd; +import com.cloud.api.commands.RestartNetworkCmd; import com.cloud.api.commands.RemoveVpnUserCmd; import com.cloud.capacity.dao.CapacityDao; import com.cloud.configuration.Config; @@ -337,54 +338,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - @Override - public Commands getAssociateIPCommands(final DomainRouterVO router, final List ipAddrList, final boolean add, long vmId, Commands cmds) { - boolean sourceNat = false; - Map> vlanIpMap = new HashMap>(); - for (final String ipAddress: ipAddrList) { - IPAddressVO ip = _ipAddressDao.findById(ipAddress); - VlanVO vlan = _vlanDao.findById(ip.getVlanId()); - ArrayList ipList = vlanIpMap.get(vlan.getId()); - if (ipList == null) { - ipList = new ArrayList(); - } - ipList.add(ip); - vlanIpMap.put(vlan, ipList); - } - for (Map.Entry> vlanAndIp: vlanIpMap.entrySet()) { - boolean firstIP = true; - ArrayList ipList = vlanAndIp.getValue(); - Collections.sort(ipList, new Comparator() { - @Override - public int compare(IPAddressVO o1, IPAddressVO o2) { - return o1.getAddress().compareTo(o2.getAddress()); - } }); - - for (final IPAddressVO ip: ipList) { - sourceNat = ip.isSourceNat(); - VlanVO vlan = vlanAndIp.getKey(); - String vlanId = vlan.getVlanId(); - String vlanGateway = vlan.getVlanGateway(); - String vlanNetmask = vlan.getVlanNetmask(); - - String vifMacAddress = null; - if (firstIP && add) { - String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(ip.getDataCenterId()); - vifMacAddress = macAddresses[1]; - } - String vmGuestAddress = null; - if(vmId!=0){ - vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); - } - - cmds.addCommand("IPAssocCommand", new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress)); - - firstIP = false; - } - } - return cmds; - } @Override public boolean associateIP(final DomainRouterVO router, final List ipAddrList, final boolean add, long vmId) { @@ -501,7 +455,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag boolean success = true; for (NetworkElement element : _networkElements) { try { - element.associate(network, userIps); + element.applyIps(network, userIps); } catch (ResourceUnavailableException e) { success = false; if (!continueOnError) { @@ -611,6 +565,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag txn.commit(); success = applyIpAssociations(network, false); + if (success) { + s_logger.debug("Successfully associated ip address " + ip + " for account " + owner.getId() + " in zone " + network.getDataCenterId()); + } else { + s_logger.warn("Failed to associate ip address " + ip + " for account " + owner.getId() + " in zone " + network.getDataCenterId()); + } return ip; } catch (ResourceUnavailableException e) { @@ -1179,7 +1138,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @DB public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd) throws PermissionDeniedException, IllegalArgumentException { - Transaction txn = Transaction.currentTxn(); Long userId = UserContext.current().getUserId(); Account account = UserContext.current().getAccount(); @@ -1251,12 +1209,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new PermissionDeniedException(ipAddress + " belongs to Account wide IP pool and cannot be disassociated"); } - txn.start(); boolean success = releasePublicIpAddress(ipAddress, accountId, userId); if (success) { _accountMgr.decrementResourceCount(accountId, ResourceType.public_ip); } - txn.commit(); return success; } catch (PermissionDeniedException pde) { @@ -1264,7 +1220,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } catch (IllegalArgumentException iae) { throw iae; } catch (Throwable t) { - s_logger.error("Disassociate IP address threw an exception."); + s_logger.error("Disassociate IP address threw an exception.", t); throw new IllegalArgumentException("Disassociate IP address threw an exception"); } } @@ -2072,6 +2028,40 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag shutdownNetwork(networkId); } } - } + + + + @Override + public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException{ + String accountName = cmd.getAccountName(); + long domainId = cmd.getDomainId(); + Account caller = UserContext.current().getAccount(); + + Account owner = _accountDao.findActiveAccount(accountName, domainId); + if (owner == null) { + throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); + } + + _accountMgr.checkAccess(caller, owner); + + Long networkId = cmd.getNetworkId(); + Network network = null; + if (networkId != null) { + network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Network id is invalid: " + networkId); + } + } + + //TODO - re-apply port forwarding and load balancing rules in the future + boolean success = applyIpAssociations(network, false); + if (!success) { + s_logger.warn("Failed to reapply the ip addresses for the account " + owner.getId() + " in zone " + network.getDataCenterId() + ", in network " + network.getId()); + } else { + s_logger.debug("Ip addresses are reapplied successfully for the account " + owner.getId() + " in zone " + network.getDataCenterId() + ", in network " + network.getId()); + } + return success; + } + } diff --git a/server/src/com/cloud/network/element/DhcpElement.java b/server/src/com/cloud/network/element/DhcpElement.java index 0979555aea0..f058bee6318 100644 --- a/server/src/com/cloud/network/element/DhcpElement.java +++ b/server/src/com/cloud/network/element/DhcpElement.java @@ -115,10 +115,6 @@ public class DhcpElement extends AdapterBase implements NetworkElement { } return _routerMgr.stopRouter(router.getId(), 1); } - - protected DhcpElement() { - super(); - } @Override public boolean applyRules(Network config, List rules) throws ResourceUnavailableException { @@ -126,12 +122,7 @@ public class DhcpElement extends AdapterBase implements NetworkElement { } @Override - public boolean associate(Network network, List ipAddress) throws ResourceUnavailableException { - return true; - } - - @Override - public boolean disassociate(Network network, List ipAddress) throws ResourceUnavailableException { - return true; + public boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException { + return true; } } diff --git a/server/src/com/cloud/network/element/DomainRouterElement.java b/server/src/com/cloud/network/element/DomainRouterElement.java index 6170516cc7b..7ac9c0a5ac7 100644 --- a/server/src/com/cloud/network/element/DomainRouterElement.java +++ b/server/src/com/cloud/network/element/DomainRouterElement.java @@ -64,6 +64,7 @@ public class DomainRouterElement extends AdapterBase implements NetworkElement { @Inject UserVmDao _userVmDao; @Inject DomainRouterDao _routerDao; + private boolean canHandle(GuestIpType ipType, DeployDestination dest) { DataCenter dc = dest.getDataCenter(); String provider = dc.getGatewayProvider(); @@ -99,7 +100,6 @@ public class DomainRouterElement extends AdapterBase implements NetworkElement { } else { return false; } - } @Override @@ -115,25 +115,15 @@ public class DomainRouterElement extends AdapterBase implements NetworkElement { } return _routerMgr.stopRouter(router.getId(), 1); } - - protected DomainRouterElement() { - super(); - } @Override public boolean applyRules(Network config, List rules) throws ResourceUnavailableException { - return false; + return true; } @Override - public boolean associate(Network network, List ipAddress) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; + public boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException { + return _routerMgr.associateIP(network, ipAddress); } - @Override - public boolean disassociate(Network network, List ipAddress) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } } diff --git a/server/src/com/cloud/network/router/DomainRouterManager.java b/server/src/com/cloud/network/router/DomainRouterManager.java index 38758f696fb..ef6574c99d8 100644 --- a/server/src/com/cloud/network/router/DomainRouterManager.java +++ b/server/src/com/cloud/network/router/DomainRouterManager.java @@ -20,6 +20,7 @@ package com.cloud.network.router; import java.util.List; import java.util.Map; +import com.cloud.agent.manager.Commands; import com.cloud.api.commands.UpgradeRouterCmd; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -31,6 +32,8 @@ import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IPAddressVO; +import com.cloud.network.IpAddress; import com.cloud.network.Network; import com.cloud.network.RemoteAccessVpnVO; import com.cloud.network.VpnUserVO; @@ -158,4 +161,6 @@ public interface DomainRouterManager extends Manager { boolean deleteRemoteAccessVpn(RemoteAccessVpnVO vpnVO); DomainRouterVO addVirtualMachineIntoNetwork(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context, Boolean startDhcp) throws ConcurrentOperationException, InsufficientNetworkCapacityException, ResourceUnavailableException; + + boolean associateIP (Network network, List ipAddress); } diff --git a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java index 8d0dec6446e..c4b6b447ae7 100644 --- a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java +++ b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java @@ -2275,15 +2275,11 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute router.setPrivateMacAddress(nic.getMacAddress()); } } - //source NAT address is stored in /proc/cmdline of the domR and gets + //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 ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(router.getAccountId(), router.getDataCenterId(), null); - final List ipAddrList = new ArrayList(); - for (final IPAddressVO ipVO : ipAddrs) { - ipAddrList.add(ipVO.getAddress()); - } - if (!ipAddrList.isEmpty()) { - _networkMgr.getAssociateIPCommands(router, ipAddrList, true, 0, cmds); + if (!ipAddrs.isEmpty()) { + cmds = getAssociateIPCommands(router, ipAddrs, cmds, 0); } return true; } @@ -2295,10 +2291,7 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute s_logger.warn("Unable to ssh to the VM: " + answer.getDetails()); return false; } - - // FIXME: Need to check return values from ipassoc command - - + return true; } @@ -2557,15 +2550,15 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute return router; } - private void reconstructRouterPortForwardingRules(Commands cmds, List ipAddrs) { - List rules = _rulesMgr.gatherPortForwardingRulesForApplication(ipAddrs); - if (rules.size() == 0) { - s_logger.debug("There are not port forwarding rules to send. "); - return; - } - SetPortForwardingRulesCommand pfrCmd = new SetPortForwardingRulesCommand(rules); - cmds.addCommand(pfrCmd); - } +// private void reconstructRouterPortForwardingRules(Commands cmds, List ipAddrs) { +// List rules = _rulesMgr.gatherPortForwardingRulesForApplication(ipAddrs); +// if (rules.size() == 0) { +// s_logger.debug("There are not port forwarding rules to send. "); +// return; +// } +// SetPortForwardingRulesCommand pfrCmd = new SetPortForwardingRulesCommand(rules); +// cmds.addCommand(pfrCmd); +// } /* private List reconstructRouterIpAssocations(Commands cmds, VirtualRouter router) { List ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(router.getAccountId(), router.getDataCenterId(), null); @@ -2573,81 +2566,6 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute } */ - public boolean associateIP(final DomainRouterVO router, final List ipAddrList, final boolean add, long vmId) { - Commands cmds = new Commands(OnError.Continue); - boolean sourceNat = false; - Map> vlanIpMap = new HashMap>(); - for (final String ipAddress: ipAddrList) { - IPAddressVO ip = _ipAddressDao.findById(ipAddress); - - VlanVO vlan = _vlanDao.findById(ip.getVlanId()); - ArrayList ipList = vlanIpMap.get(vlan.getId()); - if (ipList == null) { - ipList = new ArrayList(); - } - ipList.add(ip); - vlanIpMap.put(vlan, ipList); - } - for (Map.Entry> vlanAndIp: vlanIpMap.entrySet()) { - boolean firstIP = true; - ArrayList ipList = vlanAndIp.getValue(); - Collections.sort(ipList, new Comparator() { - @Override - public int compare(IPAddressVO o1, IPAddressVO o2) { - return o1.getAddress().compareTo(o2.getAddress()); - } }); - - for (final IPAddressVO ip: ipList) { - sourceNat = ip.isSourceNat(); - VlanVO vlan = vlanAndIp.getKey(); - String vlanId = vlan.getVlanId(); - String vlanGateway = vlan.getVlanGateway(); - String vlanNetmask = vlan.getVlanNetmask(); - - String vifMacAddress = null; - if (firstIP && add) { - String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(ip.getDataCenterId()); - vifMacAddress = macAddresses[1]; - } - String vmGuestAddress = null; - if(vmId!=0){ - vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); - } - - cmds.addCommand(new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress)); - - firstIP = false; - } - } - - Answer[] answers = null; - try { - answers = _agentMgr.send(router.getHostId(), cmds); - } catch (final AgentUnavailableException e) { - s_logger.warn("Agent unavailable", e); - return false; - } catch (final OperationTimedoutException e) { - s_logger.warn("Timed Out", e); - return false; - } - - if (answers == null) { - return false; - } - - if (answers.length != ipAddrList.size()) { - return false; - } - - // FIXME: this used to be a loop for all answers, but then we always returned the - // first one in the array, so what should really be done here? - if (answers.length > 0) { - Answer ans = answers[0]; - return ans.getResult(); - } - - return true; - } /* private boolean reconstructRouterState(Network config, DomainRouterVO router, Commands cmds) { @@ -2685,39 +2603,134 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute } */ - private boolean resendDhcpEntries(Network config, DomainRouterVO router, Commands cmd){ - final List vms = _vmDao.listBy(router.getId(), State.Creating, State.Starting, State.Running, State.Stopping, State.Stopped, State.Migrating); - Commands cmds = new Commands(OnError.Continue); - for (UserVmVO vm: vms) { - if (vm.getGuestIpAddress() == null || vm.getGuestMacAddress() == null || vm.getName() == null) { - continue; - } - DhcpEntryCommand decmd = new DhcpEntryCommand(vm.getGuestMacAddress(), vm.getGuestIpAddress(), router.getPrivateIpAddress(), vm.getName()); - cmds.addCommand(decmd); +// private boolean resendDhcpEntries(Network config, DomainRouterVO router, Commands cmd){ +// final List vms = _vmDao.listBy(router.getId(), State.Creating, State.Starting, State.Running, State.Stopping, State.Stopped, State.Migrating); +// Commands cmds = new Commands(OnError.Continue); +// for (UserVmVO vm: vms) { +// if (vm.getGuestIpAddress() == null || vm.getGuestMacAddress() == null || vm.getName() == null) { +// continue; +// } +// DhcpEntryCommand decmd = new DhcpEntryCommand(vm.getGuestMacAddress(), vm.getGuestIpAddress(), router.getPrivateIpAddress(), vm.getName()); +// cmds.addCommand(decmd); +// } +// if (cmds.size() > 0) { +// try { +// _agentMgr.send(router.getHostId(), cmds); +// } catch (final AgentUnavailableException e) { +// s_logger.warn("agent unavailable", e); +// } catch (final OperationTimedoutException e) { +// s_logger.warn("Timed Out", e); +// } +// Answer[] answers = cmds.getAnswers(); +// if (answers == null ){ +// return false; +// } +// int i=0; +// while (i < cmds.size()) { +// Answer ans = answers[i]; +// i++; +// if ((ans != null) && (ans.getResult())) { +// continue; +// } else { +// return false; +// } +// } +// } +// return true; +// } + + + private Commands getAssociateIPCommands(final DomainRouterVO router, final List ipAddrList, Commands cmds, long vmId) { + boolean sourceNat = false; + Map> vlanIpMap = new HashMap>(); + for (final IpAddress ip: ipAddrList) { + VlanVO vlan = _vlanDao.findById(ip.getVlanId()); + ArrayList ipList = vlanIpMap.get(vlan); + if (ipList == null) { + ipList = new ArrayList(); + } + ipList.add(ip); + vlanIpMap.put(vlan, ipList); + } + for (Map.Entry> vlanAndIp: vlanIpMap.entrySet()) { + boolean firstIP = true; + ArrayList ipList = vlanAndIp.getValue(); + Collections.sort(ipList, new Comparator() { + @Override + public int compare(IpAddress o1, IpAddress o2) { + return o1.getAddress().compareTo(o2.getAddress()); + } }); + + for (final IpAddress ip: ipList) { + boolean add = (ip.getState() == IpAddress.State.Releasing ? false : true); + sourceNat = ip.isSourceNat(); + VlanVO vlan = vlanAndIp.getKey(); + String vlanId = vlan.getVlanId(); + String vlanGateway = vlan.getVlanGateway(); + String vlanNetmask = vlan.getVlanNetmask(); + + String vifMacAddress = null; + if (firstIP && add) { + String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(ip.getDataCenterId()); + vifMacAddress = macAddresses[1]; + } + String vmGuestAddress = null; + if(vmId!=0){ + vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); + } + + cmds.addCommand("IPAssocCommand", new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress)); + + firstIP = false; + } + } + return cmds; + } + + + private boolean sendAssociateIPCommands(final DomainRouterVO router, Commands cmds) { + Answer[] answers = null; + try { + answers = _agentMgr.send(router.getHostId(), cmds); + } catch (final OperationTimedoutException e) { + s_logger.warn("Timed Out", e); + throw new ResourceUnavailableException("Unable to assign ip addresses", e); } - if (cmds.size() > 0) { - try { - _agentMgr.send(router.getHostId(), cmds); - } catch (final AgentUnavailableException e) { - s_logger.warn("agent unavailable", e); - } catch (final OperationTimedoutException e) { - s_logger.warn("Timed Out", e); - } - Answer[] answers = cmds.getAnswers(); - if (answers == null ){ - return false; - } - int i=0; - while (i < cmds.size()) { - Answer ans = answers[i]; - i++; - if ((ans != null) && (ans.getResult())) { - continue; - } else { - return false; - } - } + + if (answers == null) { + return false; + } + + if (answers.length != cmds.size()) { + return false; + } + + // FIXME: Have to return state for individual ipAssoc command in the future + if (answers.length > 0) { + Answer ans = answers[0]; + return ans.getResult(); } return true; } + + @Override + public boolean associateIP (Network network, List ipAddress) { + DomainRouterVO router = _routerDao.findByNetworkConfiguration(network.getId()); + if (router == null) { + s_logger.warn("Unable to associate ip addresses, virtual router doesn't exist in the network " + network.getId()); + throw new ResourceUnavailableException("Unable to assign ip addresses"); + } + + if (router.getState() == State.Running || router.getState() == State.Starting) { + Commands cmds = new Commands(OnError.Continue); + //We have to resend all already associated ip addresses + cmds = getAssociateIPCommands(router, ipAddress, cmds, 0); + return sendAssociateIPCommands(router, cmds); + } else if (router.getState() == State.Stopped || router.getState() == State.Stopping){ + return true; + } else { + 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()); + } + } } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 870c0749d45..a5ebf0693c1 100644 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -115,8 +115,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster @Inject private DomainRouterDao _routerDao; @Inject private ConsoleProxyDao _consoleDao; @Inject private SecondaryStorageVmDao _secondaryDao; - @Inject private NicDao _nicDao; - @Inject private NetworkDao _networkDao; @Inject(adapter=DeploymentPlanner.class) private Adapters _planners;