diff --git a/core/src/com/cloud/vm/DomainRouterVO.java b/core/src/com/cloud/vm/DomainRouterVO.java index 02ab3a5c18f..6cd95d38271 100755 --- a/core/src/com/cloud/vm/DomainRouterVO.java +++ b/core/src/com/cloud/vm/DomainRouterVO.java @@ -68,6 +68,21 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter { super(id, serviceOfferingId, name, name, Type.DomainRouter, templateId, hypervisorType, guestOSId, domainId, accountId, haEnabled); this.networkId = networkId; } + + public DomainRouterVO(long id, + long serviceOfferingId, + String name, + long templateId, + HypervisorType hypervisorType, + long guestOSId, + long domainId, + long accountId, + long networkId, + boolean haEnabled, + VirtualMachine.Type vmType) { + super(id, serviceOfferingId, name, name, vmType, templateId, hypervisorType, guestOSId, domainId, accountId, haEnabled); + this.networkId = networkId; + } public void setPublicIpAddress(String publicIpAddress) { this.publicIpAddress = publicIpAddress; diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index d649812051c..c7e5a524ce4 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -423,6 +423,33 @@ setup_console_proxy() { chkconfig nfs-common off } +setup_elbvm() { + log_it "Setting up Elastic Load Balancer system vm" + local hyp=$1 + setup_common eth0 eth1 + sed -i /gateway/d /etc/hosts + public_ip=$ETH2_IP + [ "$ETH2_IP" == "0.0.0.0" ] || [ "$ETH2_IP" == "" ] && public_ip=$ETH0_IP + echo "$public_ip $NAME" >> /etc/hosts + + if [ "$SSHONGUEST" == "true" ] + then + sed '/3922/s/eth1/eth0/' + setup_sshd $ETH0_IP + else + cp /etc/iptables/iptables-elbvm /etc/iptables/rules + setup_sshd $ETH1_IP + fi + + enable_fwding 0 + enable_svc haproxy 0 + enable_svc dnsmasq 0 + enable_svc cloud-passwd-srvr 0 + enable_svc cloud 0 + chkconfig nfs-common off + chkconfig portmap off +} + setup_default() { cat > /etc/network/interfaces << EOF auto lo eth0 @@ -457,6 +484,10 @@ start() { [ "$NAME" == "" ] && NAME=consoleproxy setup_console_proxy $hyp; ;; + elbvm) + [ "$NAME" == "" ] && NAME=elb + setup_elbvm + ;; unknown) [ "$NAME" == "" ] && NAME=systemvm setup_default; diff --git a/patches/systemvm/debian/config/etc/iptables/iptables-elbvm b/patches/systemvm/debian/config/etc/iptables/iptables-elbvm new file mode 100755 index 00000000000..30dbcc1013a --- /dev/null +++ b/patches/systemvm/debian/config/etc/iptables/iptables-elbvm @@ -0,0 +1,17 @@ +*nat +:PREROUTING ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -i eth2 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p icmp -j ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT +COMMIT + diff --git a/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh b/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh index e9bcc5ebe2f..85361b55307 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh @@ -90,6 +90,16 @@ dhcpsrvr_svcs() { echo "cloud nfs-common haproxy portmap" > /var/cache/cloud/disabled_svcs } +elbvm_svcs() { + chkconfig cloud off + chkconfig haproxy on ; + chkconfig ssh on + chkconfig nfs-common off + chkconfig portmap off + echo "ssh haproxy" > /var/cache/cloud/enabled_svcs + echo "cloud cloud-passwd-srvr dnsmasq apache2 nfs-common portmap" > /var/cache/cloud/disabled_svcs +} + enable_pcihotplug() { sed -i -e "/acpiphp/d" /etc/modules sed -i -e "/pci_hotplug/d" /etc/modules @@ -188,4 +198,14 @@ then fi fi +if [ "$TYPE" == "elbvm" ] +then + elbvm_svcs + if [ $? -gt 0 ] + then + printf "Failed to execute elbvm svcs\n" >$logfile + exit 9 + fi +fi + exit $? diff --git a/patches/systemvm/debian/config/root/loadbalancer.sh b/patches/systemvm/debian/config/root/loadbalancer.sh index d620b58415c..4a7d2c7cd48 100755 --- a/patches/systemvm/debian/config/root/loadbalancer.sh +++ b/patches/systemvm/debian/config/root/loadbalancer.sh @@ -52,8 +52,8 @@ ip_entry() { for i in $a do - logger -t cloud "Adding public ips for load balancing" local pubIp=$(echo $i | cut -d: -f1) + logger -t cloud "Adding public ip $pubIp for load balancing" for vif in $VIF_LIST; do sudo ip addr add dev $vif $pubIp/32 #ignore error since it is because the ip is already there @@ -64,6 +64,7 @@ ip_entry() { do logger -t cloud "Removing public ips for deleted loadbalancers" local pubIp=$(echo $i | cut -d: -f1) + logger -t cloud "Removing public ip $pubIp for deleted loadbalancers" for vif in $VIF_LIST; do sudo ip addr del $pubIp/32 dev $vif done @@ -92,9 +93,9 @@ fw_entry() { for i in $a do - logger -t cloud "Opening up firewall (INPUT chain) for load balancing" local pubIp=$(echo $i | cut -d: -f1) local dport=$(echo $i | cut -d: -f2) + logger -t cloud "Opening up firewall $pubIp:$dport (INPUT chain) for load balancing" for vif in $VIF_LIST; do sudo iptables -D INPUT -i $vif -p tcp -d $pubIp --dport $dport -j ACCEPT 2> /dev/null @@ -109,9 +110,9 @@ fw_entry() { for i in $r do - logger -t cloud "Closing up firewall (INPUT chain) for deleted load balancers" local pubIp=$(echo $i | cut -d: -f1) local dport=$(echo $i | cut -d: -f2) + logger -t cloud "Closing up firewall (INPUT chain) $pubIp:$dport for deleted load balancers" for vif in $VIF_LIST; do sudo iptables -D INPUT -i $vif -p tcp -d $pubIp --dport $dport -j ACCEPT @@ -154,6 +155,7 @@ get_vif_list() { vif_list="eth0" fi + logger -t cloud "Loadbalancer public interfaces = $vif_list" echo $vif_list } @@ -219,7 +221,7 @@ reconfig_lb $cfgfile if [ $? -gt 0 ] then - printf "Reconfiguring loadbalancer failed\n" + logger -t cloud "Reconfiguring loadbalancer failed" #FIXME: make this explicit via check on vm type or passed in flag if [ "$VIF_LIST" == "eth0" ] then diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index bf2193509bc..ce0dc03f965 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -348,11 +348,10 @@ def chain_name(vm_name): if vm_name.startswith('i-') or vm_name.startswith('r-'): if vm_name.endswith('untagged'): return '-'.join(vm_name.split('-')[:-1]) - return '-'.join(vm_name.split('-')) return vm_name def chain_name_def(vm_name): - if vm_name.startswith('i-') or vm_name.startswith('r-'): + if vm_name.startswith('i-'): if vm_name.endswith('untagged'): return '-'.join(vm_name.split('-')[:-2]) + "-def" return '-'.join(vm_name.split('-')[:-1]) + "-def" @@ -442,7 +441,7 @@ def destroy_network_rules_for_vm(session, args): vmchain_default = chain_name_def(vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - if vm_name.startswith('i-') or vm_name.startswith('r-'): + if vm_name.startswith('i-') or vm_name.startswith('r-') or vm_name.startswith('l-'): try: util.pread2(['iptables', '-F', vmchain_default]) util.pread2(['iptables', '-X', vmchain_default]) @@ -461,7 +460,7 @@ def destroy_network_rules_for_vm(session, args): remove_rule_log_for_vm(vm_name) - if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]: + if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: return 'true' try: @@ -735,7 +734,7 @@ def network_rules_for_rebooted_vm(session, vmName): util.SMlog("Found a rebooted VM -- reprogramming rules for " + vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]: + if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: default_network_rules_systemvm(session, {"vmName":vm_name}) return True @@ -823,7 +822,7 @@ def get_rule_logs_for_vms(session, args): result = [] try: for name in [session.xenapi.VM.get_name_label(x) for x in vms]: - if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-'] ]: + if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-', 'l-'] ]: continue network_rules_for_rebooted_vm(session, name) if name.startswith('i-'): @@ -840,7 +839,7 @@ def cleanup_rules_for_dead_vms(session): vms = session.xenapi.VM.get_all() cleaned = 0 for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]: - if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]: + if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]: vm = session.xenapi.VM.get_by_name_label(vm_name) if len(vm) != 1: continue @@ -868,11 +867,11 @@ def cleanup_rules(session, args): cleaned = 0 cleanup = [] for chain in chains: - if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]: + if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]: vm = session.xenapi.VM.get_by_name_label(chain) if len(vm) != 1: util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up") - cleanup.append(vm_name) + cleanup.append(chain) continue vm_rec = session.xenapi.VM.get_record(vm[0]) state = vm_rec.get('power_state') diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 040ac8c4919..90aaa2a3050 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -752,7 +752,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag NetworkOfferingVO guestNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemGuestNetwork, "System Offering for System-Guest-Network", TrafficType.Guest, true, false, null, null, null, true, Availability.Required, // services - all true except for firewall/lb/vpn and gateway services - true, true, true, false, false, false, false, GuestIpType.Direct); + true, true, true, false, false, true, false, GuestIpType.Direct); guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering); _systemNetworks.put(NetworkOfferingVO.SystemGuestNetwork, guestNetworkOffering); diff --git a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 4fca666805e..a15ba2fb819 100644 --- a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -37,6 +37,9 @@ 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.StopAnswer; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.to.LoadBalancerTO; @@ -45,6 +48,8 @@ import com.cloud.api.commands.CreateLoadBalancerRuleCmd; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.Pod; import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.Vlan.VlanType; @@ -64,6 +69,7 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.ElasticLbVmMapVO; import com.cloud.network.IPAddressVO; import com.cloud.network.LoadBalancerVO; @@ -108,8 +114,12 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineGuru; import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachineGuru; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VirtualMachineProfile; @@ -118,7 +128,7 @@ import com.cloud.vm.dao.DomainRouterDao; @Local(value = { ElasticLoadBalancerManager.class }) public class ElasticLoadBalancerManagerImpl implements - ElasticLoadBalancerManager, Manager { + ElasticLoadBalancerManager, Manager, VirtualMachineGuru { private static final Logger s_logger = Logger .getLogger(ElasticLoadBalancerManagerImpl.class); @@ -172,6 +182,8 @@ public class ElasticLoadBalancerManagerImpl implements String _name; String _instance; + static final private String _elbVmNamePrefix = "l"; + static final private String _systemVmType = "elbvm"; boolean _enabled; TrafficType _frontendTrafficType = TrafficType.Guest; @@ -179,6 +191,8 @@ public class ElasticLoadBalancerManagerImpl implements Account _systemAcct; ServiceOfferingVO _elasticLbVmOffering; ScheduledExecutorService _gcThreadPool; + String _mgmtCidr; + String _mgmtHost; Set _gcCandidateElbVmIds = Collections.newSetFromMap(new ConcurrentHashMap()); @@ -355,6 +369,9 @@ public class ElasticLoadBalancerManagerImpl implements if (_instance == null) { _instance = "VM"; } + _mgmtCidr = _configDao.getValue(Config.ManagementNetwork.key()); + _mgmtHost = _configDao.getValue(Config.ManagementHostIPAdr.key()); + boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key())); _elasticLbVmRamSize = NumbersUtil.parseInt(configs.get(Config.ElasticLoadBalancerVmMemory.key()), DEFAULT_ELB_VM_RAMSIZE); @@ -366,6 +383,8 @@ public class ElasticLoadBalancerManagerImpl implements _elasticLbVmOffering.setUniqueName("Cloud.Com-ElasticLBVm"); _elasticLbVmOffering = _serviceOfferingDao.persistSystemServiceOffering(_elasticLbVmOffering); + + String enabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key()); _enabled = (enabled == null) ? false: Boolean.parseBoolean(enabled); s_logger.info("Elastic Load balancer enabled: " + _enabled); @@ -384,6 +403,7 @@ public class ElasticLoadBalancerManagerImpl implements s_logger.info("Elastic Load Balancer: scheduling GC to run every " + gcIntervalMinutes + " minutes" ); _gcThreadPool = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ELBVM-GC")); _gcThreadPool.scheduleAtFixedRate(new CleanupThread(), gcIntervalMinutes, gcIntervalMinutes, TimeUnit.MINUTES); + _itMgr.registerGuru(VirtualMachine.Type.ElasticLoadBalancerVm, this); } @@ -454,16 +474,18 @@ public class ElasticLoadBalancerManagerImpl implements List> networks = new ArrayList>(2); NicProfile guestNic = new NicProfile(); + guestNic.setDefaultNic(true); networks.add(new Pair((NetworkVO) guestNetwork, guestNic)); networks.add(new Pair(controlConfig, null)); VMTemplateVO template = _templateDao.findSystemVMTemplate(dcId); - elbVm = new DomainRouterVO(id, _elasticLbVmOffering.getId(), VirtualMachineName.getRouterName(id, _instance), template.getId(), template.getHypervisorType(), template.getGuestOSId(), - owner.getDomainId(), owner.getId(), guestNetwork.getId(), _elasticLbVmOffering.getOfferHA()); + elbVm = new DomainRouterVO(id, _elasticLbVmOffering.getId(), VirtualMachineName.getSystemVmName(id, _instance, _elbVmNamePrefix), template.getId(), template.getHypervisorType(), template.getGuestOSId(), + owner.getDomainId(), owner.getId(), guestNetwork.getId(), _elasticLbVmOffering.getOfferHA(), VirtualMachine.Type.ElasticLoadBalancerVm); elbVm.setRole(Role.LB); elbVm = _itMgr.allocate(elbVm, template, _elasticLbVmOffering, networks, plan, null, owner); + //TODO: create usage stats } State state = elbVm.getState(); @@ -723,4 +745,212 @@ public class ElasticLoadBalancerManagerImpl implements s_logger.debug("ELB mgr: releasing ip " + lb.getSourceIpAddressId() + " since the LB rule is deleted"); releaseIp(lb.getSourceIpAddressId(), userId, caller); } + + + @Override + public DomainRouterVO findByName(String name) { + if (!VirtualMachineName.isValidSystemVmName(name, _instance, _elbVmNamePrefix)) { + return null; + } + + return _routerDao.findById(VirtualMachineName.getSystemVmId(name)); + } + + + @Override + public DomainRouterVO findById(long id) { + return _routerDao.findById(id); + } + + + @Override + public DomainRouterVO persist(DomainRouterVO elbVm) { + return _routerDao.persist(elbVm); + } + + + @Override + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + DomainRouterVO elbVm = profile.getVirtualMachine(); + NetworkVO network = _networkDao.findById(elbVm.getNetworkId()); + + DataCenter dc = dest.getDataCenter(); + + StringBuilder buf = profile.getBootArgsBuilder(); + buf.append(" template=domP type=" + _systemVmType); + buf.append(" name=").append(profile.getHostName()); + NicProfile controlNic = null; + String defaultDns1 = null; + String defaultDns2 = null; + + for (NicProfile nic : profile.getNics()) { + int deviceId = nic.getDeviceId(); + buf.append(" eth").append(deviceId).append("ip=").append(nic.getIp4Address()); + buf.append(" eth").append(deviceId).append("mask=").append(nic.getNetmask()); + if (nic.isDefaultNic()) { + buf.append(" gateway=").append(nic.getGateway()); + defaultDns1 = nic.getDns1(); + defaultDns2 = nic.getDns2(); + } + if (nic.getTrafficType() == TrafficType.Management) { + buf.append(" localgw=").append(dest.getPod().getGateway()); + } else if (nic.getTrafficType() == TrafficType.Control) { + // control command is sent over management network in VMware + if (dest.getHost().getHypervisorType() == HypervisorType.VMware) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Check if we need to add management server explicit route to elb vm. pod cidr: " + dest.getPod().getCidrAddress() + "/" + dest.getPod().getCidrSize() + + ", pod gateway: " + dest.getPod().getGateway() + ", management host: " + _mgmtHost); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Added management server explicit route to elb vm."); + } + // always add management explicit route, for basic networking setup + buf.append(" mgmtcidr=").append(_mgmtCidr); + buf.append(" localgw=").append(dest.getPod().getGateway()); + + if (dc.getNetworkType() == NetworkType.Basic) { + // ask elb vm to setup SSH on guest network + buf.append(" sshonguest=true"); + } + } + + controlNic = nic; + } + } + String domain = network.getNetworkDomain(); + if (domain != null) { + buf.append(" domain=" + domain); + } + + buf.append(" dns1=").append(defaultDns1); + if (defaultDns2 != null) { + buf.append(" dns2=").append(defaultDns2); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Boot Args for " + profile + ": " + buf.toString()); + } + + if (controlNic == null) { + throw new CloudRuntimeException("Didn't start a control port"); + } + + return true; + } + + + @Override + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException { + DomainRouterVO elbVm = profile.getVirtualMachine(); + + List nics = profile.getNics(); + for (NicProfile nic : nics) { + if (nic.getTrafficType() == TrafficType.Public) { + elbVm.setPublicIpAddress(nic.getIp4Address()); + elbVm.setPublicNetmask(nic.getNetmask()); + elbVm.setPublicMacAddress(nic.getMacAddress()); + } else if (nic.getTrafficType() == TrafficType.Guest) { + elbVm.setGuestIpAddress(nic.getIp4Address()); + } else if (nic.getTrafficType() == TrafficType.Control) { + elbVm.setPrivateIpAddress(nic.getIp4Address()); + elbVm.setPrivateMacAddress(nic.getMacAddress()); + } + } + _routerDao.update(elbVm.getId(), elbVm); + + finalizeCommandsOnStart(cmds, profile); + return true; + } + + + @Override + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + CheckSshAnswer answer = (CheckSshAnswer) cmds.getAnswer("checkSsh"); + if (answer == null || !answer.getResult()) { + s_logger.warn("Unable to ssh to the ELB VM: " + answer.getDetails()); + return false; + } + + return true; + } + + + @Override + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + DomainRouterVO elbVm = profile.getVirtualMachine(); + DataCenterVO dcVo = _dcDao.findById(elbVm.getDataCenterIdToDeployIn()); + + NicProfile controlNic = null; + + if(profile.getHypervisorType() == HypervisorType.VMware && dcVo.getNetworkType() == NetworkType.Basic) { + // TODO this is a ugly to test hypervisor type here + // for basic network mode, we will use the guest NIC for control NIC + for (NicProfile nic : profile.getNics()) { + if (nic.getTrafficType() == TrafficType.Guest && nic.getIp4Address() != null) { + controlNic = nic; + } + } + } else { + for (NicProfile nic : profile.getNics()) { + if (nic.getTrafficType() == TrafficType.Control && nic.getIp4Address() != null) { + controlNic = nic; + } + } + } + + if (controlNic == null) { + s_logger.error("Control network doesn't exist for the ELB vm " + elbVm); + return false; + } + + cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922, 5, 20)); + + // Re-apply load balancing rules + List lbs = _elbVmMapDao.listLbsForElbVm(elbVm.getId()); + List lbRules = new ArrayList(); + for (LoadBalancerVO lb : lbs) { + List dstList = _lbMgr.getExistingDestinations(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList); + lbRules.add(loadBalancing); + } + + s_logger.debug("Found " + lbRules.size() + " load balancing rule(s) to apply as a part of ELB vm " + elbVm + " start."); + if (!lbRules.isEmpty()) { + createApplyLoadBalancingRulesCommands(lbRules, elbVm, cmds); + } + + return true; + } + + + @Override + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + if (answer != null) { + VMInstanceVO vm = profile.getVirtualMachine(); + DomainRouterVO elbVm = _routerDao.findById(vm.getId()); + processStopOrRebootAnswer(elbVm, answer); + } + } + + public void processStopOrRebootAnswer(final DomainRouterVO elbVm, Answer answer) { + //TODO: process network usage stats + } + + + @Override + public void finalizeExpunge(DomainRouterVO vm) { + // no-op + + } + + + @Override + public Long convertToId(String vmName) { + if (!VirtualMachineName.isValidSystemVmName(vmName, _instance, _elbVmNamePrefix)) { + return null; + } + + return VirtualMachineName.getSystemVmId(vmName); + } } diff --git a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java index 9a8921cb0f7..ff529012923 100644 --- a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java +++ b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java @@ -21,6 +21,7 @@ package com.cloud.network.lb.dao; import java.util.List; import com.cloud.network.ElasticLbVmMapVO; +import com.cloud.network.LoadBalancerVO; import com.cloud.utils.db.GenericDao; import com.cloud.vm.DomainRouterVO; @@ -33,5 +34,6 @@ public interface ElasticLbVmMapDao extends GenericDao { List listByLbId(long lbId); int deleteLB(long lbId); List listUnusedElbVms(); + List listLbsForElbVm(long elbVmId); } diff --git a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java index 8c3c8c2aadc..9a753e63080 100644 --- a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java +++ b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java @@ -16,13 +16,17 @@ * */ -package com.cloud.network.lb.dao; - +package com.cloud.network.lb.dao; + import java.util.List; import javax.ejb.Local; import com.cloud.network.ElasticLbVmMapVO; +import com.cloud.network.LoadBalancerVO; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.LoadBalancerDaoImpl; +import com.cloud.network.router.VirtualRouter.Role; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.GenericDaoBase; @@ -32,21 +36,27 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.DomainRouterDaoImpl; - -@Local(value={ElasticLbVmMapDao.class}) + +@Local(value={ElasticLbVmMapDao.class}) public class ElasticLbVmMapDaoImpl extends GenericDaoBase implements ElasticLbVmMapDao { protected final DomainRouterDao _routerDao = ComponentLocator.inject(DomainRouterDaoImpl.class); + protected final LoadBalancerDao _loadbalancerDao = ComponentLocator.inject(LoadBalancerDaoImpl.class); + protected final SearchBuilder AllFieldsSearch; protected final SearchBuilder UnusedVmSearch; + protected final SearchBuilder LoadBalancersForElbVmSearch; - protected final SearchBuilder ElbVmSearch; - - protected ElasticLbVmMapDaoImpl() { + + protected final SearchBuilder ElbVmSearch; + + protected final SearchBuilder LoadBalancerSearch; + + protected ElasticLbVmMapDaoImpl() { AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("ipId", AllFieldsSearch.entity().getIpAddressId(), SearchCriteria.Op.EQ); - AllFieldsSearch.and("lbId", AllFieldsSearch.entity().getLbId(), SearchCriteria.Op.EQ); - AllFieldsSearch.and("elbVmId", AllFieldsSearch.entity().getElbVmId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("ipId", AllFieldsSearch.entity().getIpAddressId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("lbId", AllFieldsSearch.entity().getLbId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("elbVmId", AllFieldsSearch.entity().getElbVmId(), SearchCriteria.Op.EQ); AllFieldsSearch.done(); ElbVmSearch = _routerDao.createSearchBuilder(); @@ -56,36 +66,43 @@ public class ElasticLbVmMapDaoImpl extends GenericDaoBase sc = AllFieldsSearch.create(); + sc.setParameters("lbId", lbId); + sc.setParameters("elbVmId", elbVmId); + return findOneBy(sc); + } + + @Override + public List listByLbId(long lbId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("lbId", lbId); + return listBy(sc); + } + + @Override + public List listByElbVmId(long elbVmId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("elbVmId", elbVmId); + return listBy(sc); + } - } - @Override - public ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("lbId", lbId); - sc.setParameters("elbVmId", elbVmId); - return findOneBy(sc); - } - - @Override - public List listByLbId(long lbId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("lbId", lbId); - return listBy(sc); - } - - @Override - public List listByElbVmId(long elbVmId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("elbVmId", elbVmId); - return listBy(sc); - } - - @Override public int deleteLB(long lbId) { SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("lbId", lbId); - return super.expunge(sc); + sc.setParameters("lbId", lbId); + return super.expunge(sc); } @Override @@ -108,5 +125,12 @@ public class ElasticLbVmMapDaoImpl extends GenericDaoBase listLbsForElbVm(long elbVmId) { + SearchCriteria sc = LoadBalancerSearch.create(); + sc.setJoinParameters("LoadBalancersForElbVm", "elbVmId", elbVmId); + return _loadbalancerDao.search(sc, null); + } + +} diff --git a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java.orig b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java.orig new file mode 100644 index 00000000000..cc10a41c600 --- /dev/null +++ b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java.orig @@ -0,0 +1,138 @@ +/** + * Copyright (C) 2011 Citrix Systems, 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.network.lb.dao; + +import java.util.List; + +import javax.ejb.Local; + +import com.cloud.network.ElasticLbVmMapVO; +<<<<<<< HEAD +import com.cloud.network.LoadBalancerVO; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.LoadBalancerDaoImpl; +======= +>>>>>>> 2.2.8.nectarine +import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder.JoinType; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.DomainRouterDaoImpl; + +@Local(value={ElasticLbVmMapDao.class}) +public class ElasticLbVmMapDaoImpl extends GenericDaoBase implements ElasticLbVmMapDao { + protected final DomainRouterDao _routerDao = ComponentLocator.inject(DomainRouterDaoImpl.class); + protected final LoadBalancerDao _loadbalancerDao = ComponentLocator.inject(LoadBalancerDaoImpl.class); + + + protected final SearchBuilder AllFieldsSearch; + protected final SearchBuilder UnusedVmSearch; + protected final SearchBuilder LoadBalancersForElbVmSearch; + + + protected final SearchBuilder ElbVmSearch; + + protected final SearchBuilder LoadBalancerSearch; + + protected ElasticLbVmMapDaoImpl() { + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("ipId", AllFieldsSearch.entity().getIpAddressId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("lbId", AllFieldsSearch.entity().getLbId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("elbVmId", AllFieldsSearch.entity().getElbVmId(), SearchCriteria.Op.EQ); + AllFieldsSearch.done(); + + ElbVmSearch = _routerDao.createSearchBuilder(); + ElbVmSearch.and("role", ElbVmSearch.entity().getRole(), SearchCriteria.Op.EQ); + UnusedVmSearch = createSearchBuilder(); + UnusedVmSearch.and("elbVmId", UnusedVmSearch.entity().getElbVmId(), SearchCriteria.Op.NULL); + ElbVmSearch.join("UnusedVmSearch", UnusedVmSearch, ElbVmSearch.entity().getId(), UnusedVmSearch.entity().getElbVmId(), JoinType.LEFTOUTER); + ElbVmSearch.done(); + UnusedVmSearch.done(); + + LoadBalancerSearch = _loadbalancerDao.createSearchBuilder(); + LoadBalancersForElbVmSearch = createSearchBuilder(); + LoadBalancersForElbVmSearch.and("elbVmId", LoadBalancersForElbVmSearch.entity().getElbVmId(), SearchCriteria.Op.EQ); + LoadBalancerSearch.join("LoadBalancersForElbVm", LoadBalancersForElbVmSearch, LoadBalancerSearch.entity().getSourceIpAddressId(), LoadBalancersForElbVmSearch.entity().getIpAddressId(), JoinType.INNER); + LoadBalancersForElbVmSearch.done(); + LoadBalancerSearch.done(); + + } + + @Override + public ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("lbId", lbId); + sc.setParameters("elbVmId", elbVmId); + return findOneBy(sc); + } + + @Override + public List listByLbId(long lbId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("lbId", lbId); + return listBy(sc); + } + + @Override + public List listByElbVmId(long elbVmId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("elbVmId", elbVmId); + return listBy(sc); + } + + @Override + public int deleteLB(long lbId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("lbId", lbId); + return super.expunge(sc); + } + + @Override + public ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("ipId", ipId); + sc.setParameters("elbVmId", elbVmId); + return findOneBy(sc); + } + + @Override + public ElasticLbVmMapVO findOneByIp(long ipId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("ipId", ipId); + return findOneBy(sc); + } + + public List listUnusedElbVms() { + SearchCriteria sc = ElbVmSearch.create(); + sc.setParameters("role", Role.LB); + return _routerDao.search(sc, null); + } + + @Override + public List listLbsForElbVm(long elbVmId) { + SearchCriteria sc = LoadBalancerSearch.create(); + sc.setJoinParameters("LoadBalancersForElbVm", "elbVmId", elbVmId); + return _loadbalancerDao.search(sc, null); + } + +} diff --git a/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java b/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java index ff1b3ec5f60..228e115a234 100644 --- a/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java +++ b/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java @@ -5,6 +5,7 @@ import java.util.List; import junit.framework.TestCase; import com.cloud.network.ElasticLbVmMapVO; +import com.cloud.network.LoadBalancerVO; import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl; import com.cloud.utils.component.ComponentLocator; import com.cloud.vm.DomainRouterVO; @@ -30,4 +31,15 @@ public class ElbVmMapDaoTest extends TestCase { System.out.println("Found"); } } + + public void testFindLB() { + ElasticLbVmMapDaoImpl dao = ComponentLocator.inject(ElasticLbVmMapDaoImpl.class); + + List lbs = dao.listLbsForElbVm(5); + if (lbs == null) { + System.out.println("Not Found"); + } else { + System.out.println("Found " + lbs.size() + " lbs"); + } + } }