diff --git a/agent-simulator/scripts/zucchini/setup.py b/agent-simulator/scripts/zucchini/setup.py index e69207f937a..233f782de5f 100644 --- a/agent-simulator/scripts/zucchini/setup.py +++ b/agent-simulator/scripts/zucchini/setup.py @@ -44,10 +44,10 @@ def getGlobalSettings(): 'use.user.concentrated.pod.allocation':'false', 'vm.allocation.algorithm':'firstfit', 'capacity.check.period':'0', - 'host.stats.interval':'-1', - 'vm.stats.interval':'-1', - 'storage.stats.interval':'-1', - 'router.stats.interval':'-1', +# 'host.stats.interval':'-1', +# 'vm.stats.interval':'-1', +# 'storage.stats.interval':'-1', +# 'router.stats.interval':'-1', 'vm.op.wait.interval':'5', 'xen.public.network.device':'10.10.10.10', #only a dummy for the simulator 'guest.domain.suffix':'zcloud.simulator', @@ -55,7 +55,7 @@ def getGlobalSettings(): 'direct.agent.load.size':'1000', 'default.page.size':'10000', 'linkLocalIp.nums':'4', - 'systemvm.use.local.storage':'true', + 'system.vm.use.local.storage':'true', 'use.local.storage':'true', 'check.pod.cidrs':'false', } diff --git a/agent-simulator/scripts/zucchini/tests/testListVm.py b/agent-simulator/scripts/zucchini/tests/testListVm.py new file mode 100644 index 00000000000..12fdb869eb6 --- /dev/null +++ b/agent-simulator/scripts/zucchini/tests/testListVm.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +''' +List Virtual Machine tests +''' +try: + import unittest2 as unittest +except ImportError: + import unittest + +import timeit +import random +from cloudstackAPI import * +from cloudstackTestCase import * + +class ListVmTests(cloudstackTestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + def test_listAllVm(self): + numVms = 0 + def time_listAllVm(): + api = self.testClient.getApiClient() + listVmCmd = listVirtualMachines.listVirtualMachinesCmd() + listVmCmd.account = 'admin' + listVmCmd.zoneid = 1 + listVmCmd.domainid = 1 + numVms = len(api.listVirtualMachines(listVmCmd)) + + t = timeit.Timer(time_listAllVm) + l = t.repeat(5, 5) + self.debug("Number of VMs: " + str(len(numVms)) + ", time for last 5 listVM calls : " + str(l)) diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 6229e184b0a..d4eb27762a1 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; @@ -386,6 +387,31 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected String getDefaultStorageScriptsDir() { return "scripts/storage/qcow2"; } + + private void saveProperties(Map params) throws ConfigurationException { + final File file = PropertiesUtil.findConfigFile("agent.properties"); + if (file == null) { + throw new ConfigurationException("Unable to find agent.properties."); + } + + s_logger.info("agent.properties found at " + file.getAbsolutePath()); + + try { + Properties _properties = new Properties(); + _properties.load(new FileInputStream(file)); + Set names = _properties.stringPropertyNames(); + for (String key : params.keySet()) { + if (!names.contains(key)) { + _properties.setProperty(key, (String)params.get(key)); + } + } + _properties.store(new FileOutputStream(file), ""); + } catch (final FileNotFoundException ex) { + throw new CloudRuntimeException("Cannot find the file: " + file.getAbsolutePath(), ex); + } catch (final IOException ex) { + throw new CloudRuntimeException("IOException in reading " + file.getAbsolutePath(), ex); + } + } @Override public boolean configure(String name, Map params) @@ -560,8 +586,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - - _localStoragePath = (String)params.get("local.storage.path"); if (_localStoragePath == null) { _localStoragePath = "/var/lib/libvirt/images/"; @@ -569,7 +593,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv _localStorageUUID = (String)params.get("local.storage.uuid"); if (_localStorageUUID == null) { - throw new ConfigurationException("Can't find local.storage.uuid"); + _localStorageUUID = UUID.randomUUID().toString(); + params.put("local.storage.uuid", _localStorageUUID); } value = (String)params.get("scripts.timeout"); @@ -663,6 +688,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv _storageResource = new LibvirtStorageResource(this, _storage, _createvmPath, _timeout, _mountPoint, _monitor); + saveProperties(params); return true; } @@ -903,7 +929,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } else if (cmd instanceof CopyVolumeCommand) { return execute((CopyVolumeCommand)cmd); } else { - s_logger.warn("Unsupported command "); + s_logger.warn("Unsupported command :"+cmd.toString()); return Answer.createUnsupportedCommandAnswer(cmd); } } catch (final IllegalArgumentException e) { @@ -1596,7 +1622,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv cmd.stringifyRules(), vif, brname); if (!result) { - s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); + s_logger.warn("Failed to program Ingress network rules for vm " + cmd.getVmName()); return new SecurityIngressRuleAnswer(cmd, false, "programming network rules failed"); } else { s_logger.debug("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); @@ -1624,7 +1650,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv cmd.stringifyRules(), vif, brname); if (!result) { - s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); + s_logger.warn("Failed to program Egress network rules for vm " + cmd.getVmName()); return new SecurityEgressRuleAnswer(cmd, false, "programming network rules failed"); } else { s_logger.debug("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); @@ -3490,7 +3516,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv cmd.add("--vmid", vmId); cmd.add("--vmip", guestIP); /* type of the rule : ingress or egress */ - cmd.add("--type", type); + cmd.add("--ruletype", type); cmd.add("--sig", sig); cmd.add("--seq", seq); cmd.add("--vmmac", mac); diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index bf88bfe65f3..3495a3e5c23 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -91,6 +91,7 @@ public interface Network extends ControlledEntity { public static final Provider DhcpServer = new Provider("DhcpServer"); public static final Provider JuniperSRX = new Provider("JuniperSRX"); public static final Provider F5BigIp = new Provider("F5BigIp"); + public static final Provider NetscalerMPX = new Provider("NetscalerMPX"); public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer"); public static final Provider ExternalGateWay = new Provider("ExternalGateWay"); public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm"); diff --git a/build/build-cloud.xml b/build/build-cloud.xml index 1e3c64f10e5..04dc45d147c 100755 --- a/build/build-cloud.xml +++ b/build/build-cloud.xml @@ -13,6 +13,7 @@ --> + @@ -62,6 +63,7 @@ + @@ -145,11 +147,18 @@ + + + + + + + diff --git a/build/build-tests.xml b/build/build-tests.xml index 289394c936a..400465dde51 100755 --- a/build/build-tests.xml +++ b/build/build-tests.xml @@ -25,14 +25,14 @@ - + - + diff --git a/build/developer.xml b/build/developer.xml index 2ace5c0a1c0..52c6866869c 100755 --- a/build/developer.xml +++ b/build/developer.xml @@ -20,6 +20,9 @@ + + + @@ -143,8 +146,16 @@ - - + + + + + + + + + + diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 21cd03bbb06..7d120e4d36b 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -4,6 +4,8 @@ #Labels +label.ocfs2=OCFS2 + label.action.edit.host=Edit Host network.rate=Network Rate diff --git a/client/WEB-INF/classes/resources/messages_es.properties b/client/WEB-INF/classes/resources/messages_es.properties index 30f0c3a88c8..de8a434065a 100644 --- a/client/WEB-INF/classes/resources/messages_es.properties +++ b/client/WEB-INF/classes/resources/messages_es.properties @@ -4,6 +4,8 @@ #Labels +label.ocfs2=OCFS2 + label.action.edit.host=edición Anfitrión network.rate=Tasa de red diff --git a/client/WEB-INF/classes/resources/messages_ja.properties b/client/WEB-INF/classes/resources/messages_ja.properties index defd567977c..7e0fe33e401 100644 --- a/client/WEB-INF/classes/resources/messages_ja.properties +++ b/client/WEB-INF/classes/resources/messages_ja.properties @@ -4,6 +4,8 @@ #Labels +label.ocfs2=OCFS2 + label.action.edit.host=ホストを編集する network.rate=ネットワーク速度 diff --git a/client/WEB-INF/classes/resources/messages_zh_CN.properties b/client/WEB-INF/classes/resources/messages_zh_CN.properties index 8de433f026f..c18156aa439 100644 --- a/client/WEB-INF/classes/resources/messages_zh_CN.properties +++ b/client/WEB-INF/classes/resources/messages_zh_CN.properties @@ -4,6 +4,8 @@ #Labels +label.ocfs2=OCFS2 + label.action.edit.host=编辑主机 network.rate=网络速率 diff --git a/client/tomcatconf/components-premium.xml.in b/client/tomcatconf/components-premium.xml.in index 82a903864c4..3d73ed27c10 100755 --- a/client/tomcatconf/components-premium.xml.in +++ b/client/tomcatconf/components-premium.xml.in @@ -31,7 +31,8 @@ - + + diff --git a/cloud.spec b/cloud.spec index 6024b83c0c5..111e1660826 100644 --- a/cloud.spec +++ b/cloud.spec @@ -509,8 +509,6 @@ fi %{_javadir}/vmware*.jar %{_javadir}/%{name}-jnetpcap.jar %{_javadir}/%{name}-junit.jar -%{_javadir}/%{name}-selenium-java-client-driver.jar -%{_javadir}/%{name}-selenium-server.jar %files core diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 91974d93be5..78da408dcac 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -325,7 +325,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { vm.destroy(conn); } catch (Exception e) { - s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to " + e.toString()); + s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e); success = false; } } @@ -481,6 +481,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return execute((CheckSshCommand)cmd); } else if (clazz == SecurityIngressRulesCmd.class) { return execute((SecurityIngressRulesCmd) cmd); + } else if (clazz == SecurityEgressRulesCmd.class) { + return execute((SecurityEgressRulesCmd) cmd); } else if (clazz == OvsCreateGreTunnelCommand.class) { return execute((OvsCreateGreTunnelCommand)cmd); } else if (clazz == OvsSetTagAndFlowCommand.class) { @@ -1910,7 +1912,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe stats = getVmStatsRawXML(conn); } } catch (Exception e1) { - s_logger.warn("Error whilst collecting raw stats from plugin:" + e1); + s_logger.warn("Error whilst collecting raw stats from plugin: ", e1); return null; } @@ -1929,7 +1931,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(statsSource); } catch (Exception e) { - s_logger.warn("Exception caught whilst processing the document via document factory:"+e); + s_logger.warn("Exception caught whilst processing the document via document factory:", e); return null; } @@ -2779,7 +2781,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vm.hardShutdown(conn); } catch (Exception e) { String msg = "VM hardshutdown failed due to " + e.toString(); - s_logger.warn(msg); + s_logger.warn(msg, e); } } if (vm.getPowerState(conn) == VmPowerState.HALTED) { @@ -2787,12 +2789,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vm.destroy(conn); } catch (Exception e) { String msg = "VM destroy failed due to " + e.toString(); - s_logger.warn(msg); + s_logger.warn(msg, e); } } } catch (Exception e) { String msg = "VM getPowerState failed due to " + e.toString(); - s_logger.warn(msg); + s_logger.warn(msg, e); } } if (mounts != null) { @@ -2803,7 +2805,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vbds = vdi.getVBDs(conn); } catch (Exception e) { String msg = "VDI getVBDS failed due to " + e.toString(); - s_logger.warn(msg); + s_logger.warn(msg, e); continue; } for (VBD vbd : vbds) { @@ -2812,7 +2814,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vbd.destroy(conn); } catch (Exception e) { String msg = "VBD destroy failed due to " + e.toString(); - s_logger.warn(msg); + s_logger.warn(msg, e); } } } @@ -2999,8 +3001,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (Exception e1) { - s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " - + e1.toString()); + s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to ", e1); } } } @@ -3017,7 +3018,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } } catch (Exception e) { - s_logger.warn("swift download failed due to " + e.toString()); + s_logger.warn("swift download failed due to ", e); } return false; } @@ -3033,7 +3034,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } } catch (Exception e) { - s_logger.warn("swift download failed due to " + e.toString()); + s_logger.warn("swift download failed due to ", e); } return false; } @@ -3048,7 +3049,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } } catch (Exception e) { - s_logger.warn("swift download failed due to " + e.toString()); + s_logger.warn("swift download failed due to ", e); } return false; } @@ -3133,8 +3134,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (Exception e1) { - s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " - + e1.toString()); + s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to ", e1); } } } @@ -4091,7 +4091,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe sr = pbd.getSR(conn); srRec = sr.getRecord(conn); } catch (Exception e) { - s_logger.warn("pbd.getSR get Exception due to " + e.toString()); + s_logger.warn("pbd.getSR get Exception due to ", e); continue; } String type = srRec.type; @@ -4104,7 +4104,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe pbd.destroy(conn); sr.forget(conn); } catch (Exception e) { - s_logger.warn("forget SR catch Exception due to " + e.toString()); + s_logger.warn("forget SR catch Exception due to ", e); } } } diff --git a/core/src/com/cloud/network/resource/NetscalerMPXResource.java b/core/src/com/cloud/network/resource/NetscalerMPXResource.java new file mode 100644 index 00000000000..2893ae270a8 --- /dev/null +++ b/core/src/com/cloud/network/resource/NetscalerMPXResource.java @@ -0,0 +1,812 @@ +/** + * * 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.resource; + +import java.net.URL; +import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import com.cloud.agent.IAgentControl; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; +import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalLoadBalancerCommand; +import com.cloud.agent.api.routing.IpAssocAnswer; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.LoadBalancerConfigCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.LoadBalancerTO; +import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.resource.ServerResource; +import com.cloud.serializer.GsonHelper; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.exception.ExecutionException; +import com.cloud.utils.net.NetUtils; +import com.google.gson.Gson; + +import com.citrix.netscaler.nitro.service.nitro_service; +import com.citrix.netscaler.nitro.resource.base.base_response; +import com.citrix.netscaler.nitro.exception.nitro_exception; +import com.citrix.netscaler.nitro.resource.config.ns.nsconfig; +import com.citrix.netscaler.nitro.resource.config.lb.lbvserver; +import com.citrix.netscaler.nitro.resource.config.basic.service; +import com.citrix.netscaler.nitro.resource.config.network.*; +import com.citrix.netscaler.nitro.resource.config.ns.*; +import com.citrix.netscaler.nitro.resource.config.basic.server_service_binding; +import org.apache.axis.types.*; +import org.apache.log4j.Logger; + +class NitroError { + static final int NS_RESOURCE_EXISTS = 273; + static final int NS_RESOURCE_NOT_EXISTS=258; + static final int NS_NO_SERIVCE = 344; +} + +public class NetscalerMPXResource implements ServerResource { + + // deployment configuration + private String _name; + private String _zoneId; + private String _ip; + private String _username; + private String _password; + private String _publicInterface; + private String _privateInterface; + private Integer _numRetries; + private String _guid; + private boolean _inline; + + private static final Logger s_logger = Logger.getLogger(NetscalerMPXResource.class); + protected Gson _gson; + private String _objectNamePathSep = "-"; + + nitro_service nsService ; + Long timeout = new Long(100000); + base_response apiCallResult; + + public NetscalerMPXResource () { + _gson = GsonHelper.getGsonLogger(); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + try { + _name = (String) params.get("name"); + if (_name == null) { + throw new ConfigurationException("Unable to find name"); + } + + _zoneId = (String) params.get("zoneId"); + if (_zoneId == null) { + throw new ConfigurationException("Unable to find zone"); + } + + _ip = (String) params.get("ip"); + if (_ip == null) { + throw new ConfigurationException("Unable to find IP"); + } + + _username = (String) params.get("username"); + if (_username == null) { + throw new ConfigurationException("Unable to find username"); + } + + _password = (String) params.get("password"); + if (_password == null) { + throw new ConfigurationException("Unable to find password"); + } + + _publicInterface = (String) params.get("publicInterface"); + if (_publicInterface == null) { + throw new ConfigurationException("Unable to find public interface"); + } + + _privateInterface = (String) params.get("privateInterface"); + if (_privateInterface == null) { + throw new ConfigurationException("Unable to find private interface"); + } + + _numRetries = NumbersUtil.parseInt((String) params.get("numRetries"), 1); + + _guid = (String)params.get("guid"); + if (_guid == null) { + throw new ConfigurationException("Unable to find the guid"); + } + + _inline = Boolean.parseBoolean((String) params.get("inline")); + + if (!login()) { + throw new ExecutionException("Failed to login to the Netscaler device."); + } + + if (!enableNetScalerLoadBalancing()) { + throw new ExecutionException("Failed to enable load balancing feature on the Netscaler device."); + } + + return true; + } catch (Exception e) { + throw new ConfigurationException(e.getMessage()); + } + } + + private boolean login() { + try { + nsService = new nitro_service(_ip, "https"); + apiCallResult = nsService.login(_username, _password, timeout); + if (apiCallResult.errorcode == 0) { + return true; + } else { + s_logger.debug("Failed to log in to Netscaler device at " + _ip + " due to " + apiCallResult.message); + return false; + } + } catch (nitro_exception e) { + s_logger.debug("Failed to log in to Netscaler device at " + _ip + " due to " + e.response[0].message); + } catch (Exception e) { + s_logger.debug("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); + } + return false; + } + + private boolean enableNetScalerLoadBalancing() { + try { + String[] feature = new String[1]; + feature[0] = "LB"; + nsService.enable_features(feature); + return true; + } catch (nitro_exception e) { + System.out.println("Enabling netscaler load balancing feature failed errorcode="+e.getErrorCode()+",message="+ e.getMessage()); + } catch (Exception e) { + System.out.println("Enabling netscaler load balancing feature failed due to "+e.getMessage()); + } + return false; + } + + @Override + public StartupCommand[] initialize() { + StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand(); + cmd.setName(_name); + cmd.setDataCenter(_zoneId); + cmd.setPod(""); + cmd.setPrivateIpAddress(_ip); + cmd.setStorageIpAddress(""); + cmd.setVersion(""); + cmd.setGuid(_guid); + return new StartupCommand[]{cmd}; + } + + @Override + public Answer executeRequest(Command cmd) { + return executeRequest(cmd, _numRetries); + } + + private Answer executeRequest(Command cmd, int numRetries) { + if (cmd instanceof ReadyCommand) { + return execute((ReadyCommand) cmd); + } else if (cmd instanceof MaintainCommand) { + return execute((MaintainCommand) cmd); + } else if (cmd instanceof IpAssocCommand) { + return execute((IpAssocCommand) cmd, numRetries); + } else if (cmd instanceof LoadBalancerConfigCommand) { + return execute((LoadBalancerConfigCommand) cmd, numRetries); + } else if (cmd instanceof ExternalNetworkResourceUsageCommand) { + return execute((ExternalNetworkResourceUsageCommand) cmd); + } else if (cmd instanceof MaintainCommand) { + return execute((MaintainCommand) cmd); + } else { + return Answer.createUnsupportedCommandAnswer(cmd); + } + } + + private Answer execute(ReadyCommand cmd) { + return new ReadyAnswer(cmd); + } + + protected Answer execute(MaintainCommand cmd) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource MaintainCommand"); + } + return new MaintainAnswer(cmd, "Put host in maintaince"); + } + + private synchronized Answer execute(IpAssocCommand cmd, int numRetries) { + String[] results = new String[cmd.getIpAddresses().length]; + int i = 0; + try { + IpAddressTO[] ips = cmd.getIpAddresses(); + for (IpAddressTO ip : ips) { + long guestVlanTag = Long.valueOf(ip.getVlanId()); + String vlanSelfIp = ip.getVlanGateway(); + String vlanNetmask = ip.getVlanNetmask(); + + // Check and delete any existing guest VLAN with this tag, self IP, and netmask + deleteGuestVlan(guestVlanTag, vlanSelfIp, vlanNetmask); + + if (ip.isAdd()) { + // Add a new guest VLAN and its subnet and bind it to private interface + addGuestVlanAndSubnet(guestVlanTag, vlanSelfIp, vlanNetmask); + } + + saveConfiguration(); + results[i++] = ip.getPublicIp() + " - success"; + } + } catch (ExecutionException e) { + s_logger.error("Failed to execute IPAssocCommand due to " + e); + + if (shouldRetry(numRetries)) { + return retry(cmd, numRetries); + } else { + results[i++] = IpAssocAnswer.errorResult; + } + } + + return new IpAssocAnswer(cmd, results); + } + + private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) { + try { + String lbProtocol; + String lbMethod; + LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers(); + + for (LoadBalancerTO loadBalancer : loadBalancers) { + + if (loadBalancer.getProtocol() == null) { + lbProtocol = "TCP"; + } else if (loadBalancer.getProtocol().equals(NetUtils.TCP_PROTO)){ + lbProtocol = "TCP"; + } else if (loadBalancer.getProtocol().equals(NetUtils.UDP_PROTO)) { + lbProtocol = "UDP"; + } else { + throw new ExecutionException("Got invalid protocol: " + loadBalancer.getProtocol()); + } + + if (loadBalancer.getAlgorithm().equals("roundrobin")) { + lbMethod = "ROUNDROBIN"; + } else if (loadBalancer.getAlgorithm().equals("leastconn")) { + lbMethod = "LEASTCONNECTION"; + } else { + throw new ExecutionException("Got invalid load balancing algorithm: " + loadBalancer.getAlgorithm()); + } + + String srcIp = loadBalancer.getSrcIp(); + int srcPort = loadBalancer.getSrcPort(); + String nsVirtualServerName = generateNSVirtualServerName(srcIp, srcPort, lbProtocol); + + boolean destinationsToAdd = false; + for (DestinationTO destination : loadBalancer.getDestinations()) { + if (!destination.isRevoked()) { + destinationsToAdd = true; + break; + } + } + + if (!loadBalancer.isRevoked() && destinationsToAdd) { + + // create a load balancing virtual server + addLBVirtualServer(nsVirtualServerName, srcIp, srcPort, lbMethod, lbProtocol); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created load balancing virtual server " + nsVirtualServerName + " on the Netscaler device"); + } + + List activePoolMembers = new ArrayList(); + for (DestinationTO destination : loadBalancer.getDestinations()) { + + String nsServerName = generateNSServerName(destination.getDestIp()); + String nsServiceName = generateNSServiceName(destination.getDestIp(), destination.getDestPort()); + + if (!destination.isRevoked()) { + // add a new destination to deployed load balancing rule + + // add a new server + if (!nsServerExists(nsServerName)) { + com.citrix.netscaler.nitro.resource.config.basic.server nsServer = new com.citrix.netscaler.nitro.resource.config.basic.server(); + nsServer.set_name(nsServerName); + nsServer.set_ipaddress(destination.getDestIp()); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.add(nsService, nsServer); + if ((apiCallResult.errorcode != 0) && (apiCallResult.errorcode != NitroError.NS_RESOURCE_EXISTS)) { + throw new ExecutionException("Failed to add server " + destination.getDestIp() + " due to" + apiCallResult.message); + } + } + + // create a new service using the server added + if (!nsServiceExists(nsServiceName)) { + com.citrix.netscaler.nitro.resource.config.basic.service newService = new com.citrix.netscaler.nitro.resource.config.basic.service(); + newService.set_name(nsServiceName); + newService.set_port(destination.getDestPort()); + newService.set_servername(nsServerName); + newService.set_state("ENABLED"); + newService.set_servicetype(lbProtocol); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.add(nsService, newService); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to create service " + nsServiceName + " using server " + nsServerName + " due to" + apiCallResult.message); + } + } + + //bind service to load balancing virtual server + if (!nsServiceBindingExists(nsVirtualServerName, nsServiceName)) { + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding svcBinding = new com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding(); + svcBinding.set_name(nsVirtualServerName); + svcBinding.set_servicename(nsServiceName); + apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.add(nsService, svcBinding); + + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to bind service: " + nsServiceName + " to the lb virtual server: " + nsVirtualServerName + " on Netscaler device"); + } + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully added LB destination: " + destination.getDestIp() + ":" + destination.getDestPort() + " to load balancer " + srcIp + ":" + srcPort); + } + } else { + // remove a destination from the deployed load balancing rule + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(nsService, nsVirtualServerName); + if (serviceBindings != null) { + for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { + if (nsServiceName.equalsIgnoreCase(binding.get_servicename())) { + // delete the binding + apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(nsService, binding); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to delete the binding between the virtual server: " + nsVirtualServerName + " and service:" + nsServiceName); + } + + // delete the service + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(nsService, nsServiceName); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to delete service: " + nsServiceName); + } + + // delete the server if there is no associated services + server_service_binding[] services = server_service_binding.get(nsService, nsServerName); + if ((services == null) || (services.length == 0)) { + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(nsService, nsServerName); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove server:" + nsServerName); + } + } + } + } + } + } + } + } else { + // delete the implemented load balancing rule and its destinations + lbvserver lbserver = lbvserver.get(nsService, nsVirtualServerName); + if (lbserver == null) { + throw new ExecutionException("Failed to find virtual server with name:" + nsVirtualServerName); + } + //unbind the all services associated with this virtual server + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(nsService, nsVirtualServerName); + + if (serviceBindings != null) { + for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { + String serviceName = binding.get_servicename(); + apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(nsService, binding); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to unbind servic from the lb virtual server: " + nsVirtualServerName); + } + + com.citrix.netscaler.nitro.resource.config.basic.service svc = com.citrix.netscaler.nitro.resource.config.basic.service.get(nsService, serviceName); + String nsServerName = svc.get_servername(); + + // delete the service + com.citrix.netscaler.nitro.resource.config.basic.service.delete(nsService, serviceName); + + //delete the server if no more services attached + server_service_binding[] services = server_service_binding.get(nsService, nsServerName); + if ((services == null) || (services.length == 0)) { + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(nsService, nsServerName); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove server:" + nsServerName); + } + } + } + } + removeLBVirtualServer(nsVirtualServerName); + } + } + + if (s_logger.isInfoEnabled()) { + s_logger.info("Successfully executed resource LoadBalancerConfigCommand: " + _gson.toJson(cmd)); + } + + saveConfiguration(); + return new Answer(cmd); + } catch (ExecutionException e) { + s_logger.error("Failed to execute LoadBalancerConfigCommand due to " + e.getMessage()); + if (shouldRetry(numRetries)) { + return retry(cmd, numRetries); + } else { + return new Answer(cmd, e); + } + } catch (Exception e) { + s_logger.error("Failed to execute LoadBalancerConfigCommand due to " + e.getMessage()); + if (shouldRetry(numRetries)) { + return retry(cmd, numRetries); + } else { + return new Answer(cmd, e); + } + } + } + + private synchronized ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) { + try { + return getPublicIpBytesSentAndReceived(cmd); + } catch (ExecutionException e) { + return new ExternalNetworkResourceUsageAnswer(cmd, e); + } + } + + private void addGuestVlanAndSubnet(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException { + org.apache.axis.types.UnsignedInt result; + + try { + String vlanName = generateVlanName(vlanTag); + if (!nsVlanExists(vlanTag)) { + // add new vlan + vlan vlanObj = new vlan(); + vlanObj.set_id(vlanTag); + apiCallResult = vlan.add(nsService, vlanObj); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to add new vlan with tag:" + vlanTag + "due to" + apiCallResult.message); + } + + // add self-ip and subnet to the Netscaler + nsip selfIp = new nsip(); + selfIp.set_ipaddress(vlanSelfIp); + selfIp.set_netmask(vlanNetmask); + selfIp.set_type("SNIP"); + apiCallResult = nsip.add(nsService, selfIp); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to add new self-ip due to "+ apiCallResult.message); + } + + //bind the vlan to guest subnet + vlan_nsip_binding ipVlanBinding = new vlan_nsip_binding(); + ipVlanBinding.set_id(vlanTag); + ipVlanBinding.set_ipaddress(vlanSelfIp); + ipVlanBinding.set_netmask(vlanNetmask); + apiCallResult = vlan_nsip_binding.add(nsService, ipVlanBinding); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to bind vlan with tag:" + vlanTag + " to the subnet due to" + apiCallResult.message); + } + + // bind vlan to the private interface + vlan_interface_binding vlanBinding = new vlan_interface_binding(); + vlanBinding.set_ifnum(_privateInterface); + vlanBinding.set_tagged(true); + vlanBinding.set_id(vlanTag); + apiCallResult = vlan_interface_binding.add(nsService, vlanBinding); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to bind vlan with tag:" + vlanTag + " with the interface " + _privateInterface + " due to " + apiCallResult.message); + } + } else { + throw new ExecutionException("Failed to configure Netscaler device for vlan with tag " + vlanTag + " as vlan already exisits"); + } + } catch (nitro_exception e) { + throw new ExecutionException("Failed to implement guest network on the Netscaler device"); + } catch (Exception e) { + throw new ExecutionException("Failed to implement guest network on the Netscaler device"); + } + } + + private void deleteGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException { + org.apache.axis.types.UnsignedInt result; + + try { + if (nsVlanExists(vlanTag)) { + + // Delete all servers and associated services from this guest VLAN + deleteServersInGuestVlan(vlanTag, vlanSelfIp, vlanNetmask); + + // unbind vlan to the private interface + vlan_interface_binding vlanIfBinding = new vlan_interface_binding(); + vlanIfBinding.set_id(vlanTag); + vlanIfBinding.set_ifnum(_privateInterface); + vlanIfBinding.set_tagged(true); + apiCallResult = vlan_interface_binding.delete(nsService, vlanIfBinding); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to unbind vlan:" + vlanTag + " with the private interface due to " + apiCallResult.message); + } + + //unbind the vlan to subnet + vlan_nsip_binding vlanSnipBinding = new vlan_nsip_binding(); + vlanSnipBinding.set_netmask(vlanNetmask); + vlanSnipBinding.set_ipaddress(vlanSelfIp); + vlanSnipBinding.set_id(vlanTag); + apiCallResult = vlan_nsip_binding.delete(nsService, vlanSnipBinding); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to unbind vlan:" + vlanTag + " with the subnet due to " + apiCallResult.message); + } + + // remove subnet IP + nsip subnetIp = nsip.get(nsService, vlanSelfIp); + apiCallResult = nsip.delete(nsService, subnetIp); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove subnet ip:" + vlanTag + " to the subnet due to" + apiCallResult.message); + } + + // remove vlan + apiCallResult = com.citrix.netscaler.nitro.resource.config.network.vlan.delete(nsService, vlanTag); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove vlan with tag:" + vlanTag + "due to" + apiCallResult.message); + } + } + } catch (nitro_exception e) { + throw new ExecutionException("Failed to delete guest vlan network on the Netscaler device"); + } catch (Exception e) { + s_logger.error(e); + throw new ExecutionException(e.getMessage()); + } + } + + private boolean nsVlanExists(long vlanTag) {// throws ExecutionException { + try { + if (vlan.get(nsService, new Long(vlanTag)) != null) { + return true; + } + return false; + } catch (Exception e) { + return false; + } + } + + private boolean nsServerExists(String serverName) throws ExecutionException { + try { + if (com.citrix.netscaler.nitro.resource.config.basic.server.get(nsService, serverName) != null) { + return true; + } else { + return false; + } + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return false; + } else { + throw new ExecutionException(e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException(e.getMessage()); + } + } + + private boolean nsServiceExists(String serviceName) throws ExecutionException { + try { + if (com.citrix.netscaler.nitro.resource.config.basic.service.get(nsService, serviceName) != null) { + return true; + } else { + return false; + } + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_NO_SERIVCE) { + return false; + } else { + throw new ExecutionException(e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException(e.getMessage()); + } + } + + private boolean nsServiceBindingExists(String lbVirtualServer, String serviceName) throws ExecutionException { + try { + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(nsService, lbVirtualServer); + if (serviceBindings != null) { + for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { + if (serviceName.equalsIgnoreCase(binding.get_servicename())) { + return true; + } + } + } + return false; + } catch (nitro_exception e) { + throw new ExecutionException(e.getMessage()); + } catch (Exception e) { + throw new ExecutionException(e.getMessage()); + } + } + + private void deleteServersInGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException { + try { + com.citrix.netscaler.nitro.resource.config.basic.server[] serverList = com.citrix.netscaler.nitro.resource.config.basic.server.get(nsService); + + if (serverList == null) { + return; + } + + // remove the server and services associated with guest vlan + for (com.citrix.netscaler.nitro.resource.config.basic.server server : serverList) { + // check if server belong to same subnet as one associated with vlan + if (NetUtils.sameSubnet(vlanSelfIp, server.get_ipaddress(), vlanNetmask)) { + // first remove services associated with this server + com.citrix.netscaler.nitro.resource.config.basic.service serveicesList[] = com.citrix.netscaler.nitro.resource.config.basic.service.get(nsService); + if (serveicesList != null) { + for (com.citrix.netscaler.nitro.resource.config.basic.service svc : serveicesList) { + if (svc.get_servername().equals(server.get_ipaddress())) { + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(nsService, svc.get_name()); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove service:" + svc.get_name()); + } + } + } + } + // remove the server + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(nsService, server.get_name()); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove server:" + server.get_name()); + } + } + } + } catch (Exception e) { + throw new ExecutionException("Failed to delete server and services in the guest vlan:" + vlanTag + " on the Netscaler device due to: "+ e.getMessage()); + } + } + + private void addLBVirtualServer(String virtualServerName, String srcIp, int srcPort, String lbMethod, String lbProtocol) throws ExecutionException { + try { + lbvserver vserver = new lbvserver(); + vserver.set_name(virtualServerName); + vserver.set_ipv46(srcIp); + vserver.set_port(srcPort); + vserver.set_servicetype(lbProtocol); + vserver.set_lbmethod(lbMethod); + apiCallResult = lbvserver.add(nsService,vserver); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to create new virtual server:" + virtualServerName); + } + } catch (nitro_exception e) { + if (e.getErrorCode() != NitroError.NS_RESOURCE_EXISTS) { + throw new ExecutionException("Failed to create new virtual server:" + virtualServerName + " due to " + e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException("Failed to create new virtual server:" + virtualServerName + " due to " + e.getMessage()); + } + } + + private void removeLBVirtualServer (String virtualServerName) throws ExecutionException { + try { + lbvserver vserver = lbvserver.get(nsService, virtualServerName); + if (vserver == null) { + throw new ExecutionException("Failed to find virtual server with name:" + virtualServerName); + } + apiCallResult = lbvserver.delete(nsService, vserver); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Failed to remove virtual server:" + virtualServerName); + } + } catch (nitro_exception e) { + throw new ExecutionException("Failed remove virtual server:" + virtualServerName +" due to " + e.getMessage()); + } catch (Exception e) { + throw new ExecutionException("Failed remove virtual server:" + virtualServerName +" due to " + e.getMessage()); + } + } + + private void saveConfiguration() throws ExecutionException { + try { + apiCallResult = nsconfig.save(nsService); + if (apiCallResult.errorcode != 0) { + throw new ExecutionException("Error occured while saving configuration changes to Netscaler device due to error:" + apiCallResult.errorcode); + } + } catch (nitro_exception e) { + throw new ExecutionException("Failed to save configuration changes to Netscaler device due to " + e.getMessage()); + } catch (Exception e) { + throw new ExecutionException("Failed to save configuration changes to Netscaler device due to " + e.getMessage()); + } + } + + private ExternalNetworkResourceUsageAnswer getPublicIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException { + ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd); + + try { + //TODO: add the stats collection + } catch (Exception e) { + s_logger.error(e); + throw new ExecutionException(e.getMessage()); + } + + return answer; + } + + private Answer retry(Command cmd, int numRetries) { + int numRetriesRemaining = numRetries - 1; + s_logger.error("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetriesRemaining); + return executeRequest(cmd, numRetriesRemaining); + } + + private boolean shouldRetry(int numRetries) { + return (numRetries > 0 && login()); + } + + private String generateVlanName(long vlanTag) { + return genObjectName("cloud-vlan", String.valueOf(vlanTag)); + } + + private String generateNSVirtualServerName(String srcIp, long srcPort, String protocol) { + return genObjectName("cloud-VirtualServer", protocol, srcIp, srcPort); + } + + private String generateNSServerName(String serverIP) { + return genObjectName("cloud-server", serverIP); + } + + private String generateNSServiceName(String ip, long port) { + return genObjectName("cloud-Service", ip, port); + } + + private String genObjectName(Object... args) { + String objectName = ""; + for (int i = 0; i < args.length; i++) { + objectName += args[i]; + if (i != args.length -1) { + objectName += _objectNamePathSep; + } + } + return objectName; + } + + @Override + public IAgentControl getAgentControl() { + return null; + } + + @Override + public PingCommand getCurrentStatus(long id) { + return new PingCommand(Host.Type.ExternalLoadBalancer, id); + } + + @Override + public Type getType() { + return Host.Type.ExternalLoadBalancer; + } + + @Override + public void setAgentControl(IAgentControl agentControl) { + return; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public void disconnected() { + return; + } +} diff --git a/deps/cloud-netscaler.jar b/deps/cloud-netscaler.jar new file mode 100644 index 00000000000..8c1bf8d3fc6 Binary files /dev/null and b/deps/cloud-netscaler.jar differ diff --git a/ovm/.classpath b/ovm/.classpath new file mode 100644 index 00000000000..63ab0e2109f --- /dev/null +++ b/ovm/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/ovm/.project b/ovm/.project new file mode 100755 index 00000000000..4b9d34562c4 --- /dev/null +++ b/ovm/.project @@ -0,0 +1,23 @@ + + + ovm + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + org.python.pydev.pythonNature + + diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py index 1acee497968..f5a1ebbf654 100644 --- a/python/lib/cloudutils/serviceConfig.py +++ b/python/lib/cloudutils/serviceConfig.py @@ -587,6 +587,7 @@ class cloudAgentConfig(serviceCfgBase): cfo.save() self.syscfg.svo.stopService("cloud-agent") + bash("sleep 30") self.syscfg.svo.enableService("cloud-agent") return True except: diff --git a/python/lib/cloudutils/utilities.py b/python/lib/cloudutils/utilities.py index d9f47e46088..17c81573607 100644 --- a/python/lib/cloudutils/utilities.py +++ b/python/lib/cloudutils/utilities.py @@ -88,11 +88,9 @@ class Distribution: if os.path.exists("/etc/fedora-release"): self.distro = "Fedora" - elif os.path.exists("/etc/centos-release"): - self.distro = "CentOS" elif os.path.exists("/etc/redhat-release"): version = file("/etc/redhat-release").readline() - if version.find("Red Hat Enterprise Linux Server release 6") != -1 or version.find("Scientific Linux release 6") != -1 or version.find("CentOS release 6") != -1: + if version.find("Red Hat Enterprise Linux Server release 6") != -1 or version.find("Scientific Linux release 6") != -1 or version.find("CentOS Linux release 6") != -1: self.distro = "RHEL6" elif version.find("CentOS release") != -1: self.distro = "CentOS" diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index de59df698c6..37f94f9cdcf 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -82,6 +82,7 @@ def ipset(ipsetname, proto, start, end, ips): def destroy_network_rules_for_vm(vm_name, vif=None): vmchain = vm_name + vmchain_egress = vm_name + "-egress" vmchain_default = None delete_rules_for_vm_in_bridge_firewall_chain(vm_name) @@ -111,7 +112,19 @@ def destroy_network_rules_for_vm(vm_name, vif=None): execute("iptables -X " + vmchain) except: logging.debug("Ignoring failure to delete chain " + vmchain) + + + try: + execute("iptables -F " + vmchain_egress) + except: + logging.debug("Ignoring failure to delete chain " + vmchain_egress) + try: + execute("iptables -X " + vmchain_egress) + except: + logging.debug("Ignoring failure to delete chain " + vmchain_egress) + + if vif is not None: try: dnats = execute("iptables -t nat -S | grep " + vif + " | sed 's/-A/-D/'").split("\n") @@ -246,6 +259,7 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname): domID = getvmId(vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vmName) vmchain = vm_name + vmchain_egress = vm_name +"-egress" vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def" destroy_ebtables_rules(vmName, vif) @@ -254,7 +268,12 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname): execute("iptables -N " + vmchain) except: execute("iptables -F " + vmchain) - + + try: + execute("iptables -N " + vmchain_egress) + except: + execute("iptables -F " + vmchain_egress) + try: execute("iptables -N " + vmchain_default) except: @@ -270,7 +289,7 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname): #don't let vm spoof its ip address if vm_ip is not None: - execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j ACCEPT") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j " + vmchain_egress) execute("iptables -A " + vmchain_default + " -j " + vmchain) execute("iptables -A " + vmchain + " -j DROP") except: @@ -552,12 +571,17 @@ def remove_rule_log_for_vm(vmName): return result -def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif, brname): +def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif, brname,ruletype): try: vmName = vm_name domId = getvmId(vmName) - vmchain = vm_name + if ruletype == 'egress': + vmchain = vm_name + "-egress" + else: + vmchain = vm_name + + changes = [] changes = check_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno) @@ -704,6 +728,7 @@ if __name__ == '__main__': parser.add_option("--vmid", dest="vmID") parser.add_option("--vmmac", dest="vmMAC") parser.add_option("--vif", dest="vif") + parser.add_option("--ruletype", dest="ruletype") parser.add_option("--sig", dest="sig") parser.add_option("--seq", dest="seq") parser.add_option("--rules", dest="rules") @@ -724,7 +749,7 @@ if __name__ == '__main__': elif cmd == "get_rule_logs_for_vms": get_rule_logs_for_vms() elif cmd == "add_network_rules": - add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules, option.vif, option.brname) + add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules, option.vif, option.brname,option.ruletype) elif cmd == "cleanup_rules": cleanup_rules() elif cmd == "post_default_network_rules": diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 1dd107fce07..6de90f67989 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -731,7 +731,7 @@ public class ApiServer implements HttpRequestHandler { return; } - throw new CloudAuthenticationException("Unable to find user " + username + " in domain " + domainId); + throw new CloudAuthenticationException("Failed to authenticate user " + username + " in domain " + domainId + "; please provide valid credentials"); } public void logoutUser(long userId) { diff --git a/server/src/com/cloud/api/response/SecurityGroupResultObject.java b/server/src/com/cloud/api/response/SecurityGroupResultObject.java index 221955b4238..6b25382101f 100644 --- a/server/src/com/cloud/api/response/SecurityGroupResultObject.java +++ b/server/src/com/cloud/api/response/SecurityGroupResultObject.java @@ -175,11 +175,6 @@ public class SecurityGroupResultObject { currentGroup = groupResult; } - SecurityGroupRulesVO dummyIngressobj=new SecurityGroupRulesVO(); - SecurityGroupEgressRulesVO dummyEgressobj=new SecurityGroupEgressRulesVO() ; -String str=dummyIngressobj.getClass().getName(); - -String s1=netGroupRule.getClass().getSimpleName(); if (netGroupRule.getRuleId() != null && netGroupRule.getClass().getSimpleName().indexOf("SecurityGroupRulesVO") != -1) { // there's at least one ingress rule for this network group, add the ingress rule data @@ -246,6 +241,9 @@ String s1=netGroupRule.getClass().getSimpleName(); if (!ingressDataList.isEmpty()) { currentGroup.setIngressRules(ingressDataList); } + if (!egressDataList.isEmpty()) { + currentGroup.setEgressRules(egressDataList); + } resultObjects.add(currentGroup); } } diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java index 037d08e993e..652b922c815 100644 --- a/server/src/com/cloud/async/AsyncJobManagerImpl.java +++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java @@ -629,7 +629,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe if(blockItems != null && blockItems.size() > 0) { for(SyncQueueItemVO item : blockItems) { if(item.getContentType().equalsIgnoreCase("AsyncJob")) { - completeAsyncJob(item.getContentId(), 2, 0, getResetResultMessage("Job is cancelled as it has been blocking others for too long")); + completeAsyncJob(item.getContentId(), 2, 0, getResetResultResponse("Job is cancelled as it has been blocking others for too long")); } // purge the item and resume queue processing @@ -667,7 +667,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe Long jobId = item.getContentId(); if(jobId != null) { s_logger.warn("Mark job as failed as its correspoding queue-item has been discarded. job id: " + jobId); - completeAsyncJob(jobId, AsyncJobResult.STATUS_FAILED, 0, getResetResultMessage("Execution was cancelled because of server shutdown")); + completeAsyncJob(jobId, AsyncJobResult.STATUS_FAILED, 0, getResetResultResponse("Execution was cancelled because of server shutdown")); } } _queueMgr.purgeItem(item.getId()); @@ -754,7 +754,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe List items = _queueMgr.getActiveQueueItems(msHost.getId(), true); cleanupPendingJobs(items); _queueMgr.resetQueueProcess(msHost.getId()); - _jobDao.resetJobProcess(msHost.getId(), BaseCmd.INTERNAL_ERROR, getResetResultMessage("job cancelled because of management server restart")); + _jobDao.resetJobProcess(msHost.getId(), BaseCmd.INTERNAL_ERROR, getSerializedErrorMessage("job cancelled because of management server restart")); txn.commit(); } catch(Throwable e) { s_logger.warn("Unexpected exception ", e); @@ -775,7 +775,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe List l = _queueMgr.getActiveQueueItems(getMsid(), false); cleanupPendingJobs(l); _queueMgr.resetQueueProcess(getMsid()); - _jobDao.resetJobProcess(getMsid(), BaseCmd.INTERNAL_ERROR, getResetResultMessage("job cancelled because of management server restart")); + _jobDao.resetJobProcess(getMsid(), BaseCmd.INTERNAL_ERROR, getSerializedErrorMessage("job cancelled because of management server restart")); } catch(Throwable e) { s_logger.error("Unexpected exception " + e.getMessage(), e); } @@ -788,11 +788,15 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe return true; } - private static String getResetResultMessage(String messageText) { + private static ExceptionResponse getResetResultResponse(String errorMessage) { ExceptionResponse resultObject = new ExceptionResponse(); resultObject.setErrorCode(BaseCmd.INTERNAL_ERROR); - resultObject.setErrorText(messageText); - return ApiSerializerHelper.toSerializedStringOld(resultObject); + resultObject.setErrorText(errorMessage); + return resultObject; + } + + private static String getSerializedErrorMessage(String errorMessage) { + return ApiSerializerHelper.toSerializedStringOld(getResetResultResponse(errorMessage)); } @Override diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 6a20c3e17aa..d9cec7ccef0 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -87,7 +87,6 @@ public enum Config { RemoteAccessVpnUserLimit("Network", AgentManager.class, String.class, "remote.access.vpn.user.limit", "8", "The maximum number of VPN users that can be created per account", null), // Usage - CapacityCheckPeriod("Usage", ManagementServer.class, Integer.class, "capacity.check.period", "300000", "The interval in milliseconds between capacity checks", null), StorageAllocatedCapacityThreshold("Usage", ManagementServer.class, Float.class, "storage.allocated.capacity.threshold", "0.85", "Percentage (as a value between 0 and 1) of allocated storage utilization above which alerts will be sent about low storage available.", null), StorageCapacityThreshold("Usage", ManagementServer.class, Float.class, "storage.capacity.threshold", "0.85", "Percentage (as a value between 0 and 1) of storage utilization above which alerts will be sent about low storage available.", null), diff --git a/server/src/com/cloud/domain/dao/DomainDao.java b/server/src/com/cloud/domain/dao/DomainDao.java index 6daa75a0133..5ccd860d512 100644 --- a/server/src/com/cloud/domain/dao/DomainDao.java +++ b/server/src/com/cloud/domain/dao/DomainDao.java @@ -29,5 +29,6 @@ public interface DomainDao extends GenericDao { public boolean isChildDomain(Long parentId, Long childId); DomainVO findImmediateChildForParent(Long parentId); List findImmediateChildrenForParent(Long parentId); - List findAllChildren(String path, Long parentId); + List findAllChildren(String path, Long parentId); + List findInactiveDomains(); } diff --git a/server/src/com/cloud/domain/dao/DomainDaoImpl.java b/server/src/com/cloud/domain/dao/DomainDaoImpl.java index 69cc7b56634..51ef94de4e9 100644 --- a/server/src/com/cloud/domain/dao/DomainDaoImpl.java +++ b/server/src/com/cloud/domain/dao/DomainDaoImpl.java @@ -27,6 +27,7 @@ import javax.ejb.Local; import org.apache.log4j.Logger; +import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; @@ -44,6 +45,7 @@ public class DomainDaoImpl extends GenericDaoBase implements Dom protected SearchBuilder DomainPairSearch; protected SearchBuilder ImmediateChildDomainSearch; protected SearchBuilder FindAllChildrenSearch; + protected SearchBuilder AllFieldsSearch; public DomainDaoImpl () { DomainNameLikeSearch = createSearchBuilder(); @@ -67,6 +69,14 @@ public class DomainDaoImpl extends GenericDaoBase implements Dom FindAllChildrenSearch.and("path", FindAllChildrenSearch.entity().getPath(), SearchCriteria.Op.LIKE); FindAllChildrenSearch.and("id", FindAllChildrenSearch.entity().getId(), SearchCriteria.Op.NEQ); FindAllChildrenSearch.done(); + + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("owner", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("path", AllFieldsSearch.entity().getPath(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("parent", AllFieldsSearch.entity().getParent(), SearchCriteria.Op.EQ); + AllFieldsSearch.done(); } @@ -238,5 +248,12 @@ public class DomainDaoImpl extends GenericDaoBase implements Dom } } return result; + } + + @Override + public List findInactiveDomains() { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("state", Domain.State.Inactive); + return listBy(sc); } } diff --git a/server/src/com/cloud/network/ExternalNetworkManager.java b/server/src/com/cloud/network/ExternalNetworkManager.java index 6e62bba7f5a..83eab3939f8 100644 --- a/server/src/com/cloud/network/ExternalNetworkManager.java +++ b/server/src/com/cloud/network/ExternalNetworkManager.java @@ -44,6 +44,7 @@ public interface ExternalNetworkManager extends Manager { public static final ExternalNetworkDeviceType F5BigIP = new ExternalNetworkDeviceType("F5BigIP"); public static final ExternalNetworkDeviceType JuniperSRX = new ExternalNetworkDeviceType("JuniperSRX"); + public static final ExternalNetworkDeviceType NetscalerMPX = new ExternalNetworkDeviceType("NetscalerMPX"); public ExternalNetworkDeviceType(String name) { _name = name; diff --git a/server/src/com/cloud/network/ExternalNetworkManagerImpl.java b/server/src/com/cloud/network/ExternalNetworkManagerImpl.java index 14ed6f9b28d..c44ebe6a969 100644 --- a/server/src/com/cloud/network/ExternalNetworkManagerImpl.java +++ b/server/src/com/cloud/network/ExternalNetworkManagerImpl.java @@ -81,6 +81,7 @@ import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.resource.F5BigIpResource; import com.cloud.network.resource.JuniperSrxResource; +import com.cloud.network.resource.NetscalerMPXResource; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; @@ -123,7 +124,8 @@ import com.cloud.vm.dao.NicDao; public class ExternalNetworkManagerImpl implements ExternalNetworkManager { public enum ExternalNetworkResourceName { JuniperSrx, - F5BigIp; + F5BigIp, + NetscalerMPX; } @Inject AgentManager _agentMgr; @@ -251,12 +253,15 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { deviceType = cmd.getType(); if (deviceType ==null) { - deviceType = ExternalNetworkDeviceType.F5BigIP.getName(); //default it to F5 for now + deviceType = ExternalNetworkDeviceType.NetscalerMPX.getName(); //TODO: default it to NetscalerMPX for now, till UI support Netscaler & F5 } if (deviceType.equalsIgnoreCase(ExternalNetworkDeviceType.F5BigIP.getName())) { resource = new F5BigIpResource(); - guid = getExternalNetworkResourceGuid(zoneId, ExternalNetworkResourceName.F5BigIp, ipAddress); + guid = getExternalNetworkResourceGuid(zoneId, ExternalNetworkResourceName.F5BigIp, ipAddress); + } else if (deviceType.equalsIgnoreCase(ExternalNetworkDeviceType.NetscalerMPX.getName())) { + resource = new NetscalerMPXResource(); + guid = getExternalNetworkResourceGuid(zoneId, ExternalNetworkResourceName.NetscalerMPX, ipAddress); } else { throw new CloudRuntimeException("An unsupported networt device type is added as external load balancer."); } @@ -284,6 +289,8 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { if (host != null) { if (deviceType.equalsIgnoreCase(ExternalNetworkDeviceType.F5BigIP.getName())) { zone.setLoadBalancerProvider(Network.Provider.F5BigIp.getName()); + } else if (deviceType.equalsIgnoreCase(ExternalNetworkDeviceType.NetscalerMPX.getName())) { + zone.setLoadBalancerProvider(Network.Provider.NetscalerMPX.getName()); } _dcDao.update(zone.getId(), zone); return host; @@ -504,7 +511,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { Answer answer = _agentMgr.easySend(externalLoadBalancer.getId(), cmd); if (answer == null || !answer.getResult()) { String details = (answer != null) ? answer.getDetails() : "details unavailable"; - String msg = "Unable to apply load balancer rules to the F5 BigIp appliance in zone " + zone.getName() + " due to: " + details + "."; + String msg = "Unable to apply load balancer rules to the external load balancer appliance in zone " + zone.getName() + " due to: " + details + "."; s_logger.error(msg); throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 5f4090ce7ae..3b058c46517 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2809,8 +2809,15 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag DataCenterVO zone = _dcDao.findById(zoneId); if (zone.getNetworkType() == NetworkType.Advanced) { - return (zone.getGatewayProvider() != null && zone.getGatewayProvider().equals(Network.Provider.JuniperSRX.getName()) && - zone.getFirewallProvider() != null && zone.getFirewallProvider().equals(Network.Provider.JuniperSRX.getName())); + + if (zone.getGatewayProvider() != null && zone.getGatewayProvider().equals(Network.Provider.JuniperSRX.getName()) && + zone.getFirewallProvider() != null && zone.getFirewallProvider().equals(Network.Provider.JuniperSRX.getName())) { + return true; + } else if (zone.getGatewayProvider() != null && zone.getLoadBalancerProvider() != null && zone.getLoadBalancerProvider().equals(Network.Provider.NetscalerMPX.getName())) { + return true; + } else { + return false; + } } else { return (zone.getFirewallProvider() != null && zone.getFirewallProvider().equals(Network.Provider.JuniperSRX.getName())); } @@ -3121,7 +3128,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag vm = _vmDao.findById(vmId); } Network network = getNetwork(networkId); - NetworkOffering networkOffering = _configMgr.getNetworkOffering(network.getNetworkOfferingId()); + NetworkOffering ntwkOff = _configMgr.getNetworkOffering(network.getNetworkOfferingId()); // For default userVm Default network and domR guest/public network, get rate information from the service offering; for other situations get information // from the network offering @@ -3130,14 +3137,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (vm != null) { if (vm.getType() == Type.User && network.isDefault()) { isUserVmsDefaultNetwork = true; - } else if (vm.getType() == Type.DomainRouter && networkOffering.getTrafficType() == TrafficType.Public && networkOffering.getGuestType() == null) { + } else if (vm.getType() == Type.DomainRouter && ((ntwkOff.getTrafficType() == TrafficType.Public && ntwkOff.getGuestType() == null) || (ntwkOff.getGuestType() != null && ntwkOff.getTrafficType() == TrafficType.Guest))) { isDomRGuestOrPublicNetwork = true; } } if (isUserVmsDefaultNetwork || isDomRGuestOrPublicNetwork) { return _configMgr.getServiceOfferingNetworkRate(vm.getServiceOfferingId()); } else { - return _configMgr.getNetworkOfferingNetworkRate(networkOffering.getId()); + return _configMgr.getNetworkOfferingNetworkRate(ntwkOff.getId()); } } diff --git a/server/src/com/cloud/network/element/ExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java similarity index 97% rename from server/src/com/cloud/network/element/ExternalLoadBalancerElement.java rename to server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 2e1bd0ae683..ff4d51a28be 100644 --- a/server/src/com/cloud/network/element/ExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -53,9 +53,9 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @Local(value=NetworkElement.class) -public class ExternalLoadBalancerElement extends AdapterBase implements NetworkElement { +public class F5ExternalLoadBalancerElement extends AdapterBase implements NetworkElement { - private static final Logger s_logger = Logger.getLogger(ExternalLoadBalancerElement.class); + private static final Logger s_logger = Logger.getLogger(F5ExternalLoadBalancerElement.class); @Inject NetworkManager _networkManager; @Inject ExternalNetworkManager _externalNetworkManager; diff --git a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java new file mode 100644 index 00000000000..1b618d2463c --- /dev/null +++ b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java @@ -0,0 +1,162 @@ +/** + * * 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.element; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.configuration.ConfigurationManager; +import com.cloud.dc.DataCenter; +import com.cloud.deploy.DeployDestination; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientNetworkCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.ExternalNetworkManager; +import com.cloud.network.Network; +import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.NetworkManager; +import com.cloud.network.Networks.TrafficType; +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.AdapterBase; +import com.cloud.utils.component.Inject; +import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=NetworkElement.class) +public class NetscalerExternalLoadBalancerElement extends AdapterBase implements NetworkElement { + + private static final Logger s_logger = Logger.getLogger(NetscalerExternalLoadBalancerElement.class); + + @Inject NetworkManager _networkManager; + @Inject ExternalNetworkManager _externalNetworkManager; + @Inject ConfigurationManager _configMgr; + + private boolean canHandle(Network config) { + DataCenter zone = _configMgr.getZone(config.getDataCenterId()); + if (config.getGuestType() != Network.GuestIpType.Virtual || config.getTrafficType() != TrafficType.Guest) { + s_logger.trace("Not handling network with guest Type " + config.getGuestType() + " and traffic type " + config.getTrafficType()); + return false; + } + + return (_networkManager.zoneIsConfiguredForExternalNetworking(zone.getId()) && + zone.getLoadBalancerProvider() != null && zone.getLoadBalancerProvider().equals(Network.Provider.NetscalerMPX.getName())); + } + + @Override + public boolean implement(Network guestConfig, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException, InsufficientNetworkCapacityException { + + if (!canHandle(guestConfig)) { + return false; + } + + return _externalNetworkManager.manageGuestNetworkWithExternalLoadBalancer(true, guestConfig); + } + + @Override + public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientNetworkCapacityException, ResourceUnavailableException { + return true; + } + + @Override + public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) { + return true; + } + + @Override + public boolean shutdown(Network guestConfig, ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException { + if (!canHandle(guestConfig)) { + return false; + } + + return _externalNetworkManager.manageGuestNetworkWithExternalLoadBalancer(false, guestConfig); + } + + @Override + public boolean destroy(Network config) { + return true; + } + + @Override + public boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException { + return true; + } + + @Override + public boolean applyRules(Network config, List rules) throws ResourceUnavailableException { + if (!canHandle(config)) { + return false; + } + + return _externalNetworkManager.applyLoadBalancerRules(config, rules); + } + + @Override + public Map> getCapabilities() { + Map> capabilities = new HashMap>(); + + // Set capabilities for LB service + Map lbCapabilities = new HashMap(); + + // Specifies that the RoundRobin and Leastconn algorithms are supported for load balancing rules + lbCapabilities.put(Capability.SupportedLBAlgorithms, "roundrobin,leastconn"); + + // Specifies that load balancing rules can be made for either TCP or UDP traffic + lbCapabilities.put(Capability.SupportedProtocols, "tcp,udp"); + + // Specifies that this element can measure network usage on a per public IP basis + lbCapabilities.put(Capability.TrafficStatistics, "per public ip"); + + // Specifies that load balancing rules can only be made with public IPs that aren't source NAT IPs + lbCapabilities.put(Capability.LoadBalancingSupportedIps, "additional"); + + capabilities.put(Service.Lb, lbCapabilities); + + return capabilities; + } + + @Override + public Provider getProvider() { + return Provider.NetscalerMPX; + } + + @Override + public boolean restart(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException{ + return true; + } + + @Override + public boolean applyStaticNats(Network config, List rules) throws ResourceUnavailableException { + return false; + } + +} diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index 789d6e99639..90a6de68893 100755 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -988,10 +988,10 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG Account caller = UserContext.current().getCaller(); Long id = cmd.getId(); - IngressRuleVO rule = _ingressRuleDao.findById(id); + EgressRuleVO rule = _egressRuleDao.findById(id); if (rule == null) { - s_logger.debug("Unable to find ingress rule with id " + id); - throw new InvalidParameterValueException("Unable to find ingress rule with id " + id); + s_logger.debug("Unable to find egress rule with id " + id); + throw new InvalidParameterValueException("Unable to find egress rule with id " + id); } // Check permissions @@ -1010,8 +1010,8 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return false; } - _ingressRuleDao.remove(id); - s_logger.debug("revokeSecurityGroupIngress succeeded for ingress rule id: " + id); + _egressRuleDao.remove(id); + s_logger.debug("revokeSecurityGroupEgress succeeded for ingress rule id: " + id); final Set affectedVms = new HashSet(); affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(groupHandle.getId())); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 1e7bd894984..8ef12abeb24 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2947,7 +2947,7 @@ public class ManagementServerImpl implements ManagementServer { String name = cmd.getDomainName(); Long parentId = cmd.getParentDomainId(); Long ownerId = UserContext.current().getCaller().getId(); - Account account = UserContext.current().getCaller(); + Account caller = UserContext.current().getCaller(); String networkDomain = cmd.getNetworkDomain(); if (ownerId == null) { @@ -2962,11 +2962,13 @@ public class ManagementServerImpl implements ManagementServer { if (parentDomain == null) { throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found."); } - - if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) { - throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied."); + + if (parentDomain.getState().equals(Domain.State.Inactive)) { + throw new CloudRuntimeException("The domain cannot be created as the parent domain " + parentDomain.getName() + " is being deleted"); } + _accountMgr.checkAccess(caller, parentDomain); + if (networkDomain != null) { if (!NetUtils.verifyDomainName(networkDomain)) { throw new InvalidParameterValueException( @@ -2995,41 +2997,48 @@ public class ManagementServerImpl implements ManagementServer { @Override @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_DELETE, eventDescription = "deleting Domain", async = true) public boolean deleteDomain(DeleteDomainCmd cmd) { - Account account = UserContext.current().getCaller(); + Account caller = UserContext.current().getCaller(); Long domainId = cmd.getId(); Boolean cleanup = cmd.getCleanup(); - - if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) { - throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied."); + + DomainVO domain = _domainDao.findById(domainId); + + if (domain == null) { + throw new InvalidParameterValueException("Failed to delete domain " + domainId + ", domain not found"); + } else if (domainId == DomainVO.ROOT_DOMAIN) { + throw new PermissionDeniedException("Can't delete ROOT domain"); } + + _accountMgr.checkAccess(caller, domain); + + //mark domain as inactive + s_logger.debug("Marking domain id=" + domainId + " as " + Domain.State.Inactive + " before actually deleting it"); + domain.setState(Domain.State.Inactive); + _domainDao.update(domainId, domain); try { - DomainVO domain = _domainDao.findById(domainId); - if (domain != null) { - long ownerId = domain.getAccountId(); - if ((cleanup != null) && cleanup.booleanValue()) { - boolean success = cleanupDomain(domainId, ownerId); - if (!success) { - s_logger.error("Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ")."); - return false; - } - } else { + long ownerId = domain.getAccountId(); + if ((cleanup != null) && cleanup.booleanValue()) { + if (!cleanupDomain(domainId, ownerId)) { + s_logger.error("Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ")."); + return false; + } + } else { + List accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domainId); + if (accountsForCleanup.isEmpty()) { if (!_domainDao.remove(domainId)) { s_logger.error("Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting"); return false; - } else { - domain.setState(Domain.State.Inactive); - _domainDao.update(domainId, domain); - } + } + } else { + s_logger.warn("Can't delete the domain yet because it has " + accountsForCleanup.size() + "accounts that need a cleanup"); + return false; } - } else { - throw new InvalidParameterValueException("Failed to delete domain " + domainId + ", domain not found"); } + cleanupDomainOfferings(domainId); return true; - } catch (InvalidParameterValueException ex) { - throw ex; } catch (Exception ex) { s_logger.error("Exception deleting domain with id " + domainId, ex); return false; @@ -3079,21 +3088,25 @@ public class ManagementServerImpl implements ManagementServer { } } - { - // delete users which will also delete accounts and release resources for those accounts - SearchCriteria sc = _accountDao.createSearchCriteria(); - sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); - List accounts = _accountDao.search(sc, null); - for (AccountVO account : accounts) { - success = (success && _accountMgr.deleteAccount(account, UserContext.current().getCallerUserId(), UserContext.current().getCaller())); - if (!success) { - s_logger.warn("Failed to cleanup account id=" + account.getId() + " as a part of domain cleanup"); - } + // delete users which will also delete accounts and release resources for those accounts + SearchCriteria sc = _accountDao.createSearchCriteria(); + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); + List accounts = _accountDao.search(sc, null); + for (AccountVO account : accounts) { + success = (success && _accountMgr.deleteAccount(account, UserContext.current().getCallerUserId(), UserContext.current().getCaller())); + if (!success) { + s_logger.warn("Failed to cleanup account id=" + account.getId() + " as a part of domain cleanup"); } } - - // delete the domain itself - boolean deleteDomainSuccess = _domainDao.remove(domainId); + + //don't remove the domain if there are accounts required cleanup + boolean deleteDomainSuccess = true; + List accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domainId); + if (accountsForCleanup.isEmpty()) { + deleteDomainSuccess = _domainDao.remove(domainId); + } else { + s_logger.debug("Can't delete the domain yet because it has " + accountsForCleanup.size() + "accounts that need a cleanup"); + } return success && deleteDomainSuccess; } diff --git a/server/src/com/cloud/template/HyervisorTemplateAdapter.java b/server/src/com/cloud/template/HyervisorTemplateAdapter.java index d6e3e9424d2..db6a672719f 100644 --- a/server/src/com/cloud/template/HyervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HyervisorTemplateAdapter.java @@ -100,6 +100,14 @@ public class HyervisorTemplateAdapter extends TemplateAdapterBase implements Tem throw new InvalidParameterValueException("Please specify a valid "+ cmd.getFormat().toLowerCase()); } + if ((cmd.getFormat().equalsIgnoreCase("vhd") && (!url.toLowerCase().endsWith("vhd") && !url.toLowerCase().endsWith("vhd.zip") && !url.toLowerCase().endsWith("vhd.bz2") && !url.toLowerCase().endsWith("vhd.gz") )) + || (cmd.getFormat().equalsIgnoreCase("qcow2") && (!url.toLowerCase().endsWith("qcow2") && !url.toLowerCase().endsWith("qcow2.zip") && !url.toLowerCase().endsWith("qcow2.bz2") && !url.toLowerCase().endsWith("qcow2.gz") )) + || (cmd.getFormat().equalsIgnoreCase("ova") && (!url.toLowerCase().endsWith("ova") && !url.toLowerCase().endsWith("ova.zip") && !url.toLowerCase().endsWith("ova.bz2") && !url.toLowerCase().endsWith("ova.gz"))) + || (cmd.getFormat().equalsIgnoreCase("img") && !url.toLowerCase().endsWith("img")) + || (cmd.getFormat().equalsIgnoreCase("raw") && !url.toLowerCase().endsWith("raw")) ) { + throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is a invalid for the format " + cmd.getFormat().toLowerCase()); + } + profile.setUrl(validateUrl(url)); return profile; } diff --git a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java index c4111be6035..a85b1cc01fe 100755 --- a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -42,6 +42,7 @@ import com.cloud.upgrade.dao.Upgrade217to218; import com.cloud.upgrade.dao.Upgrade218to22; import com.cloud.upgrade.dao.Upgrade218to224DomainVlans; import com.cloud.upgrade.dao.Upgrade2210to2211; +import com.cloud.upgrade.dao.Upgrade2211to2212; import com.cloud.upgrade.dao.Upgrade221to222; import com.cloud.upgrade.dao.Upgrade222to224; import com.cloud.upgrade.dao.Upgrade224to225; @@ -73,19 +74,20 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { public DatabaseUpgradeChecker() { _dao = ComponentLocator.inject(VersionDaoImpl.class); - _upgradeMap.put("2.1.7", new DbUpgrade[] { new Upgrade217to218(), new Upgrade218to22(), new Upgrade221to222(), new UpgradeSnapshot217to224(), new Upgrade222to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.1.8", new DbUpgrade[] { new Upgrade218to22(), new Upgrade221to222(), new UpgradeSnapshot217to224(), new Upgrade222to224(), new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.1.9", new DbUpgrade[] { new Upgrade218to22(), new Upgrade221to222(), new UpgradeSnapshot217to224(), new Upgrade222to224(), new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.1", new DbUpgrade[] { new Upgrade221to222(), new UpgradeSnapshot223to224(), new Upgrade222to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.2", new DbUpgrade[] { new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.3", new DbUpgrade[] { new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.4", new DbUpgrade[] { new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.5", new DbUpgrade[] { new Upgrade225to226(), new Upgrade227to228(),new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211() }); - _upgradeMap.put("2.2.6", new DbUpgrade[] { new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.7", new DbUpgrade[] { new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.8", new DbUpgrade[] { new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.9", new DbUpgrade[] { new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.10", new DbUpgrade[] { new Upgrade2210to2211()}); + _upgradeMap.put("2.1.7", new DbUpgrade[] { new Upgrade217to218(), new Upgrade218to22(), new Upgrade221to222(), new UpgradeSnapshot217to224(), new Upgrade222to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.1.8", new DbUpgrade[] { new Upgrade218to22(), new Upgrade221to222(), new UpgradeSnapshot217to224(), new Upgrade222to224(), new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.1.9", new DbUpgrade[] { new Upgrade218to22(), new Upgrade221to222(), new UpgradeSnapshot217to224(), new Upgrade222to224(), new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.1", new DbUpgrade[] { new Upgrade221to222(), new UpgradeSnapshot223to224(), new Upgrade222to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.2", new DbUpgrade[] { new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.3", new DbUpgrade[] { new Upgrade222to224(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.4", new DbUpgrade[] { new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.5", new DbUpgrade[] { new Upgrade225to226(), new Upgrade227to228(),new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212() }); + _upgradeMap.put("2.2.6", new DbUpgrade[] { new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.7", new DbUpgrade[] { new Upgrade227to228(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.8", new DbUpgrade[] { new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.9", new DbUpgrade[] { new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.10", new DbUpgrade[] { new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.11", new DbUpgrade[] { new Upgrade2211to2212()}); } protected void runScript(Connection conn, File file) { diff --git a/server/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java b/server/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java index fcc79bb87fc..e6bb45bd3df 100755 --- a/server/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java +++ b/server/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java @@ -25,6 +25,7 @@ import com.cloud.upgrade.dao.Upgrade217to218; import com.cloud.upgrade.dao.Upgrade218to224DomainVlans; import com.cloud.upgrade.dao.Upgrade218to22Premium; import com.cloud.upgrade.dao.Upgrade2210to2211; +import com.cloud.upgrade.dao.Upgrade2211to2212; import com.cloud.upgrade.dao.Upgrade221to222Premium; import com.cloud.upgrade.dao.Upgrade222to224Premium; import com.cloud.upgrade.dao.Upgrade224to225; @@ -42,21 +43,22 @@ import com.cloud.utils.component.SystemIntegrityChecker; public class PremiumDatabaseUpgradeChecker extends DatabaseUpgradeChecker { public PremiumDatabaseUpgradeChecker() { _dao = ComponentLocator.inject(VersionDaoImpl.class); - _dao = ComponentLocator.inject(VersionDaoImpl.class); - _upgradeMap.put("2.1.7", new DbUpgrade[] { new Upgrade217to218(), new Upgrade218to22Premium(), new Upgrade221to222Premium(), new UpgradeSnapshot217to224(), new Upgrade222to224Premium(),new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); + _upgradeMap.put("2.1.7", new DbUpgrade[] { new Upgrade217to218(), new Upgrade218to22Premium(), new Upgrade221to222Premium(), new UpgradeSnapshot217to224(), new Upgrade222to224Premium(), + new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); _upgradeMap.put("2.1.8", new DbUpgrade[] { new Upgrade218to22Premium(), new Upgrade221to222Premium(), new UpgradeSnapshot217to224(), new Upgrade222to224Premium(), - new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211() }); + new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212() }); _upgradeMap.put("2.1.9", new DbUpgrade[] { new Upgrade218to22Premium(), new Upgrade221to222Premium(), new UpgradeSnapshot217to224(), new Upgrade222to224Premium(), - new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.1", new DbUpgrade[] { new Upgrade221to222Premium(), new Upgrade222to224Premium(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.2", new DbUpgrade[] { new Upgrade222to224Premium(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.3", new DbUpgrade[] { new Upgrade222to224Premium(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.4", new DbUpgrade[] { new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.5", new DbUpgrade[] { new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.6", new DbUpgrade[] { new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.7", new DbUpgrade[] { new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.8", new DbUpgrade[] { new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.9", new DbUpgrade[] { new Upgrade229to2210(), new Upgrade2210to2211()}); - _upgradeMap.put("2.2.10", new DbUpgrade[] { new Upgrade2210to2211()}); + new Upgrade218to224DomainVlans(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.1", new DbUpgrade[] { new Upgrade221to222Premium(), new Upgrade222to224Premium(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.2", new DbUpgrade[] { new Upgrade222to224Premium(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.3", new DbUpgrade[] { new Upgrade222to224Premium(), new UpgradeSnapshot223to224(), new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.4", new DbUpgrade[] { new Upgrade224to225(), new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.5", new DbUpgrade[] { new Upgrade225to226(), new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.6", new DbUpgrade[] { new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.7", new DbUpgrade[] { new Upgrade227to228Premium(), new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.8", new DbUpgrade[] { new Upgrade228to229(), new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.9", new DbUpgrade[] { new Upgrade229to2210(), new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.10", new DbUpgrade[] { new Upgrade2210to2211(), new Upgrade2211to2212()}); + _upgradeMap.put("2.2.11", new DbUpgrade[] { new Upgrade2211to2212()}); } } diff --git a/server/src/com/cloud/upgrade/dao/Upgrade2211to2212.java b/server/src/com/cloud/upgrade/dao/Upgrade2211to2212.java new file mode 100644 index 00000000000..81c6cc9baa3 --- /dev/null +++ b/server/src/com/cloud/upgrade/dao/Upgrade2211to2212.java @@ -0,0 +1,65 @@ +/** + * 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.upgrade.dao; + +import java.io.File; +import java.sql.Connection; + +import org.apache.log4j.Logger; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +public class Upgrade2211to2212 implements DbUpgrade { + final static Logger s_logger = Logger.getLogger(Upgrade2211to2212.class); + + @Override + public String[] getUpgradableVersionRange() { + return new String[] { "2.2.11", "2.2.11"}; + } + + @Override + public String getUpgradedVersion() { + return "2.2.12"; + } + + @Override + public boolean supportsRollingUpgrade() { + return true; + } + + @Override + public File[] getPrepareScripts() { + String script = Script.findScript("", "db/schema-2211to2212.sql"); + if (script == null) { + throw new CloudRuntimeException("Unable to find db/schema-2211to2212.sql"); + } + + return new File[] { new File(script) }; + } + + @Override + public void performDataMigration(Connection conn) { + } + + @Override + public File[] getCleanupScripts() { + return null; + } + +} diff --git a/server/src/com/cloud/upgrade/dao/Upgrade229to2210.java b/server/src/com/cloud/upgrade/dao/Upgrade229to2210.java index 5ce4468083c..7d5e4a8f6ee 100644 --- a/server/src/com/cloud/upgrade/dao/Upgrade229to2210.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade229to2210.java @@ -60,13 +60,52 @@ public class Upgrade229to2210 implements DbUpgrade { @Override public void performDataMigration(Connection conn) { updateFirewallRules(conn); + updateSnapshots(conn); } @Override public File[] getCleanupScripts() { return null; } - + + private void updateSnapshots(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + long currentSnapshotId = 0; + try { + pstmt = conn.prepareStatement("select id, prev_snap_id from snapshots where sechost_id is NULL and prev_snap_id is not NULL and status=\"BackedUp\" and removed is NULL order by id"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + long preSnapId = rs.getLong(2); + currentSnapshotId = id; + pstmt = conn.prepareStatement("select sechost_id from snapshots where id=? and sechost_id is not NULL"); + pstmt.setLong(1, preSnapId); + ResultSet sechost = pstmt.executeQuery(); + if (sechost.next()) { + long secHostId = sechost.getLong(1); + pstmt = conn.prepareStatement("update snapshots set sechost_id=? where id=?"); + pstmt.setLong(1, secHostId); + pstmt.setLong(2, id); + pstmt.executeUpdate(); + } + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to update snapshots id=" + currentSnapshotId, e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } + private void updateFirewallRules(Connection conn) { PreparedStatement pstmt = null; ResultSet rs = null; diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 11eb0d7a6b9..82d97d25f9c 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -1846,12 +1846,15 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag txn = Transaction.open(Transaction.CLOUD_DB); //Cleanup removed accounts - List removedAccounts = _accountDao.findCleanupsForRemovedAccounts(); + List removedAccounts = _accountDao.findCleanupsForRemovedAccounts(null); s_logger.info("Found " + removedAccounts.size() + " removed accounts to cleanup"); for (AccountVO account : removedAccounts) { s_logger.debug("Cleaning up " + account.getId()); try { - cleanupAccount(account, getSystemUser().getId(), getSystemAccount()); + if (cleanupAccount(account, getSystemUser().getId(), getSystemAccount())) { + account.setNeedsCleanup(false); + _accountDao.update(account.getId(), account); + } } catch (Exception e) { s_logger.error("Skipping due to error on account " + account.getId(), e); } @@ -1872,6 +1875,23 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } } + //cleanup inactive domains + List inactiveDomains = _domainDao.findInactiveDomains(); + s_logger.info("Found " + inactiveDomains.size() + " inactive domains to cleanup"); + for (DomainVO inactiveDomain : inactiveDomains) { + long domainId = inactiveDomain.getId(); + try { + List accountsForCleanupInDomain = _accountDao.findCleanupsForRemovedAccounts(domainId); + if (accountsForCleanupInDomain.isEmpty()) { + s_logger.debug("Removing inactive domain id=" + domainId); + _domainDao.remove(domainId); + } else { + s_logger.debug("Can't remove inactive domain id=" + domainId + " as it has accounts that need clenaup"); + } + } catch (Exception e) { + s_logger.error("Skipping due to error on domain " + domainId, e); + } + } } catch (Exception e) { s_logger.error("Exception ", e); diff --git a/server/src/com/cloud/user/dao/AccountDao.java b/server/src/com/cloud/user/dao/AccountDao.java index 2ff13f983ff..12465b27257 100644 --- a/server/src/com/cloud/user/dao/AccountDao.java +++ b/server/src/com/cloud/user/dao/AccountDao.java @@ -37,7 +37,7 @@ public interface AccountDao extends GenericDao { List findActiveAccounts(Long maxAccountId, Filter filter); List findRecentlyDeletedAccounts(Long maxAccountId, Date earliestRemovedDate, Filter filter); List findNewAccounts(Long minAccountId, Filter filter); - List findCleanupsForRemovedAccounts(); + List findCleanupsForRemovedAccounts(Long domainId); List findAdminAccountsForDomain(Long domainId); List findActiveAccountsForDomain(Long domain); void markForCleanup(long accountId); diff --git a/server/src/com/cloud/user/dao/AccountDaoImpl.java b/server/src/com/cloud/user/dao/AccountDaoImpl.java index 1d000b9b92a..57ad47018ce 100755 --- a/server/src/com/cloud/user/dao/AccountDaoImpl.java +++ b/server/src/com/cloud/user/dao/AccountDaoImpl.java @@ -71,7 +71,8 @@ public class AccountDaoImpl extends GenericDaoBase implements A CleanupForRemovedAccountsSearch = createSearchBuilder(); CleanupForRemovedAccountsSearch.and("cleanup", CleanupForRemovedAccountsSearch.entity().getNeedsCleanup(), SearchCriteria.Op.EQ); - CleanupForRemovedAccountsSearch.and("removed", CleanupForRemovedAccountsSearch.entity().getRemoved(), SearchCriteria.Op.NNULL); + CleanupForRemovedAccountsSearch.and("removed", CleanupForRemovedAccountsSearch.entity().getRemoved(), SearchCriteria.Op.NNULL); + CleanupForRemovedAccountsSearch.and("domainid", CleanupForRemovedAccountsSearch.entity().getDomainId(), SearchCriteria.Op.EQ); CleanupForRemovedAccountsSearch.done(); CleanupForDisabledAccountsSearch = createSearchBuilder(); @@ -82,9 +83,13 @@ public class AccountDaoImpl extends GenericDaoBase implements A } @Override - public List findCleanupsForRemovedAccounts() { + public List findCleanupsForRemovedAccounts(Long domainId) { SearchCriteria sc = CleanupForRemovedAccountsSearch.create(); - sc.setParameters("cleanup", true); + sc.setParameters("cleanup", true); + + if (domainId != null) { + sc.setParameters("domainid", domainId); + } return searchIncludingRemoved(sc, null, null, false); } diff --git a/setup/db/db/schema-2210to2211.sql b/setup/db/db/schema-2210to2211.sql index cd7d30c6cd0..e69de29bb2d 100644 --- a/setup/db/db/schema-2210to2211.sql +++ b/setup/db/db/schema-2210to2211.sql @@ -1,6 +0,0 @@ ---; --- Schema upgrade from 2.2.10 to 2.2.11; ---; - -ALTER TABLE `cloud`.`vm_template` ADD COLUMN `template_tag` varchar(255) COMMENT 'template tag'; - diff --git a/setup/db/db/schema-2211to2212.sql b/setup/db/db/schema-2211to2212.sql new file mode 100644 index 00000000000..7cec25f5e4e --- /dev/null +++ b/setup/db/db/schema-2211to2212.sql @@ -0,0 +1,6 @@ +--; +-- Schema upgrade from 2.2.11 to 2.2.12; +--; + +ALTER TABLE `cloud`.`vm_template` ADD COLUMN `template_tag` varchar(255) COMMENT 'template tag'; + diff --git a/setup/db/db/schema-229to2210.sql b/setup/db/db/schema-229to2210.sql index eb6d6f3671d..8e7aaec5445 100644 --- a/setup/db/db/schema-229to2210.sql +++ b/setup/db/db/schema-229to2210.sql @@ -47,6 +47,9 @@ INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-serv INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'vmware.reserve.mem', 'false', 'Specify whether or not to reserve memory based on memory overprovisioning factor'); INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'mem.overprovisioning.factor', '1', 'Used for memory overprovisioning calculation'); +INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'AgentManager', 'remote.access.vpn.psk.length', '24', 'The length of the ipsec preshared key (minimum 8, maximum 256)'); +INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'AgentManager', 'remote.access.vpn.client.iprange', '10.1.2.1-10.1.2.8', 'The range of ips to be allocated to remote access vpn clients. The first ip in the range is used by the VPN server'); +INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'AgentManager', 'remote.access.vpn.user.limit', '8', 'The maximum number of VPN users that can be created per account'); CREATE TABLE IF NOT exists `cloud`.`elastic_lb_vm_map` ( `id` bigint unsigned NOT NULL auto_increment, @@ -60,14 +63,3 @@ CREATE TABLE IF NOT exists `cloud`.`elastic_lb_vm_map` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; UPDATE `cloud`.`network_offerings` SET lb_service=1 where unique_name='System-Guest-Network'; - -UPDATE `cloud`.`vm_template` SET type='SYSTEM' WHERE name='systemvm-xenserver-2.2.10'; -UPDATE `cloud`.`vm_template` SET type='SYSTEM' WHERE name='systemvm-kvm-2.2.10'; -UPDATE `cloud`.`vm_template` SET type='SYSTEM' WHERE name='systemvm-vSphere-2.2.10'; - -UPDATE vm_instance SET vm_template_id=(SELECT id FROM vm_template WHERE name='systemvm-xenserver-2.2.10' AND removed IS NULL) where vm_template_id=1; -UPDATE vm_instance SET vm_template_id=(SELECT id FROM vm_template WHERE name='systemvm-kvm-2.2.10' AND removed IS NULL) where vm_template_id=3; -UPDATE vm_instance SET vm_template_id=(SELECT id FROM vm_template WHERE name='systemvm-vSphere-2.2.10' AND removed IS NULL) where vm_template_id=8; - --- Update system Vms using systemvm-xenserver-2.2.4 template; -UPDATE vm_instance SET vm_template_id=(SELECT id FROM vm_template WHERE name='systemvm-xenserver-2.2.10' AND removed IS NULL) where vm_template_id=(SELECT id FROM vm_template WHERE name='systemvm-xenserver-2.2.4' AND removed IS NULL); diff --git a/tools/testClient/cloudstackTestCase.py b/tools/testClient/cloudstackTestCase.py index 39696b2ca9f..8625d683cb5 100644 --- a/tools/testClient/cloudstackTestCase.py +++ b/tools/testClient/cloudstackTestCase.py @@ -1,5 +1,8 @@ from cloudstackAPI import * -import unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import cloudstackTestClient class cloudstackTestCase(unittest.case.TestCase): def __init__(self, args): diff --git a/deps/cloud-selenium-java-client-driver.jar b/tools/tooljars/cloud-selenium-java-client-driver.jar similarity index 100% rename from deps/cloud-selenium-java-client-driver.jar rename to tools/tooljars/cloud-selenium-java-client-driver.jar diff --git a/deps/cloud-selenium-server.jar b/tools/tooljars/cloud-selenium-server.jar similarity index 100% rename from deps/cloud-selenium-server.jar rename to tools/tooljars/cloud-selenium-server.jar diff --git a/ui/index.jsp b/ui/index.jsp index 8286c509ff0..6118cae3ca3 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -91,6 +91,7 @@ 'label.path': '', 'label.SR.name': '', 'label.nfs': '', + 'label.ocfs2': '', 'label.SharedMountPoint': '', 'label.PreSetup': '', 'label.iscsi': '', diff --git a/ui/scripts/cloud.core.pod.js b/ui/scripts/cloud.core.pod.js index ebcf7a54f08..14a79edf02c 100644 --- a/ui/scripts/cloud.core.pod.js +++ b/ui/scripts/cloud.core.pod.js @@ -808,6 +808,8 @@ function bindAddPrimaryStorageButton($leftmenuItem1) { if (protocol == "nfs" || protocol == "PreSetup" || protocol == "SharedMountPoint") { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Path", $thisDialog.find("#add_pool_path"), $thisDialog.find("#add_pool_path_errormsg")); + } else if(protocol == "ocfs2") { + isValid &= validateString("Path", $thisDialog.find("#add_pool_path"), $thisDialog.find("#add_pool_path_errormsg")); } else if(protocol == "iscsi") { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Target IQN", $thisDialog.find("#add_pool_iqn"), $thisDialog.find("#add_pool_iqn_errormsg")); @@ -846,7 +848,13 @@ function bindAddPrimaryStorageButton($leftmenuItem1) { if(path.substring(0,1)!="/") path = "/" + path; url = presetupURL(server, path); - } + } + else if (protocol == "ocfs2") { + var path = trim($thisDialog.find("#add_pool_path").val()); + if(path.substring(0,1)!="/") + path = "/" + path; + url = ocfs2URL(server, path); + } else if (protocol == "SharedMountPoint") { var path = trim($thisDialog.find("#add_pool_path").val()); if(path.substring(0,1)!="/") @@ -1103,6 +1111,15 @@ function presetupURL(server, path) { return url; } +function ocfs2URL(server, path) { + var url; + if(server.indexOf("://")==-1) + url = "ocfs2://" + server + path; + else + url = server + path; + return url; +} + function SharedMountPointURL(server, path) { var url; if(server.indexOf("://")==-1) diff --git a/ui/scripts/cloud.core.resource.js b/ui/scripts/cloud.core.resource.js index 4c94ab520ff..287dd38fcda 100644 --- a/ui/scripts/cloud.core.resource.js +++ b/ui/scripts/cloud.core.resource.js @@ -1818,6 +1818,8 @@ function initAddPrimaryStorageShortcut($midmenuAddLink2, currentPageInRightPanel if (protocol == "nfs" || protocol == "PreSetup" || protocol == "SharedMountPoint") { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Path", $thisDialog.find("#add_pool_path"), $thisDialog.find("#add_pool_path_errormsg")); + } else if(protocol == "ocfs2") { + isValid &= validateString("Path", $thisDialog.find("#add_pool_path"), $thisDialog.find("#add_pool_path_errormsg")); } else if(protocol == "iscsi") { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Target IQN", $thisDialog.find("#add_pool_iqn"), $thisDialog.find("#add_pool_iqn_errormsg")); @@ -1865,7 +1867,13 @@ function initAddPrimaryStorageShortcut($midmenuAddLink2, currentPageInRightPanel if(path.substring(0,1)!="/") path = "/" + path; url = presetupURL(server, path); - } + } + else if (protocol == "ocfs2") { + var path = trim($thisDialog.find("#add_pool_path").val()); + if(path.substring(0,1)!="/") + path = "/" + path; + url = ocfs2URL(server, path); + } else if (protocol == "SharedMountPoint") { var path = trim($thisDialog.find("#add_pool_path").val()); if(path.substring(0,1)!="/") @@ -1958,7 +1966,8 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { else if(clusterObj.hypervisortype == "Ovm") { $protocolSelector.empty(); $protocolSelector.append(''); - } + $protocolSelector.append(''); + } else { $protocolSelector.empty(); } @@ -1976,8 +1985,17 @@ function bindEventHandlerToDialogAddPool($dialogAddPool) { $dialogAddPool.find("#add_pool_nfs_server").val(""); $dialogAddPool.find("#add_pool_server_container").show(); - } - if($(this).val() == "PreSetup") { + } + else if($(this).val() == "ocfs2") {//ocfs2 is the same as nfs, except no server field. + $('li[input_group="nfs"]', $dialogAddPool).show(); + $('li[input_group="iscsi"]', $dialogAddPool).hide(); + $('li[input_group="vmfs"]', $dialogAddPool).hide(); + $dialogAddPool.find("#add_pool_path_container").find("label").text(g_dictionary["label.path"]+":"); + + $dialogAddPool.find("#add_pool_nfs_server").val(""); + $dialogAddPool.find("#add_pool_server_container").hide(); + } + else if($(this).val() == "PreSetup") { $("#add_pool_server_container", $dialogAddPool).show(); $('li[input_group="nfs"]', $dialogAddPool).show(); $('li[input_group="iscsi"]', $dialogAddPool).hide(); diff --git a/ui/scripts/cloud.core.zone.js b/ui/scripts/cloud.core.zone.js index b8919de9973..202b01f7fa5 100644 --- a/ui/scripts/cloud.core.zone.js +++ b/ui/scripts/cloud.core.zone.js @@ -985,6 +985,8 @@ function bindAddPrimaryStorageButtonOnZonePage($button, zoneId, zoneName) { if (protocol == "nfs" || protocol == "PreSetup" || protocol == "SharedMountPoint") { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Path", $thisDialog.find("#add_pool_path"), $thisDialog.find("#add_pool_path_errormsg")); + } else if(protocol == "ocfs2") { + isValid &= validateString("Path", $thisDialog.find("#add_pool_path"), $thisDialog.find("#add_pool_path_errormsg")); } else if(protocol == "iscsi") { isValid &= validateString("Server", $thisDialog.find("#add_pool_nfs_server"), $thisDialog.find("#add_pool_nfs_server_errormsg")); isValid &= validateString("Target IQN", $thisDialog.find("#add_pool_iqn"), $thisDialog.find("#add_pool_iqn_errormsg")); @@ -1032,6 +1034,12 @@ function bindAddPrimaryStorageButtonOnZonePage($button, zoneId, zoneName) { path = "/" + path; url = presetupURL(server, path); } + else if (protocol == "ocfs2") { + var path = trim($thisDialog.find("#add_pool_path").val()); + if(path.substring(0,1)!="/") + path = "/" + path; + url = ocfs2URL(server, path); + } else if (protocol == "SharedMountPoint") { var path = trim($thisDialog.find("#add_pool_path").val()); if(path.substring(0,1)!="/") diff --git a/utils/src/com/cloud/utils/ssh/SSHKeysHelper.java b/utils/src/com/cloud/utils/ssh/SSHKeysHelper.java index 85eae351976..8f286bb9c2d 100644 --- a/utils/src/com/cloud/utils/ssh/SSHKeysHelper.java +++ b/utils/src/com/cloud/utils/ssh/SSHKeysHelper.java @@ -18,16 +18,16 @@ package com.cloud.utils.ssh; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.KeyPair; -import com.jcraft.jsch.JSch; - import java.io.ByteArrayOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.apache.commons.codec.binary.Base64; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.KeyPair; + public class SSHKeysHelper { private KeyPair keyPair; @@ -56,6 +56,9 @@ public class SSHKeysHelper { public static String getPublicKeyFingerprint(String publicKey) { String key[] = publicKey.split(" "); + if (key.length < 2) { + throw new RuntimeException("Incorrect public key is passed in"); + } byte[] keyBytes = Base64.decodeBase64(key[1]); MessageDigest md5 = null;